Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cd36eada8 | ||
|
|
0e382df5e6 | ||
|
|
1ed30247fa | ||
|
|
25a83c0d9d | ||
|
|
6dd74f5762 | ||
|
|
61b1a4b382 | ||
|
|
2a07c46500 | ||
|
|
f5bc7896dd | ||
|
|
af8366f0fe | ||
|
|
db90802e6e | ||
|
|
59108365f1 | ||
|
|
092ee49139 | ||
|
|
c324cd5953 | ||
|
|
5cfbd72fa8 | ||
|
|
ce942b0585 | ||
|
|
91ed50d993 | ||
|
|
a93dc423f0 | ||
|
|
399df8ab68 | ||
|
|
8d383cba9d | ||
|
|
dadb12a6e5 | ||
|
|
d7cecc1d8c | ||
|
|
5b76668cbe | ||
|
|
64cc6b7af7 | ||
|
|
15f3c2ff66 | ||
|
|
0e5c654d5b | ||
|
|
de446c4240 | ||
|
|
4f335b9471 | ||
|
|
6269aa6398 | ||
|
|
da0b96a5ad | ||
|
|
db1318fed1 | ||
|
|
a0cacb5553 | ||
|
|
6cc8da120f | ||
|
|
35ca90b8f2 | ||
|
|
65e5b40223 | ||
|
|
4803180bcf | ||
|
|
7e8e954de7 | ||
|
|
0ca9b1be48 | ||
|
|
85eddfc536 | ||
|
|
0ab0fb5dd4 | ||
|
|
6705fb453e | ||
|
|
2c58475d61 | ||
|
|
a381a64b31 | ||
|
|
68c199aa64 | ||
|
|
805d8d81c5 | ||
|
|
063beddb01 | ||
|
|
59aa9c5474 | ||
|
|
a32206a6fb | ||
|
|
bec0dc3c0b | ||
|
|
cf2ec690db | ||
|
|
7daf35d898 | ||
|
|
9d3c5e50d6 | ||
|
|
9cc0c4f874 | ||
|
|
fe1ee08df4 | ||
|
|
84b2ae3e8f | ||
|
|
55054f1fa6 | ||
|
|
8aae821e59 | ||
|
|
d646edee08 | ||
|
|
b0d35f5ef8 | ||
|
|
34e81fdf87 | ||
|
|
5696f22951 | ||
|
|
8853adda62 | ||
|
|
1984b3747e | ||
|
|
c85fa98bcc | ||
|
|
7874b77104 | ||
|
|
bc7d1bc7b2 | ||
|
|
26e8d0d976 | ||
|
|
acadd069e8 | ||
|
|
6e4a5a4bb6 | ||
|
|
6212c1bb80 | ||
|
|
3358fd9b02 | ||
|
|
88e24263cf | ||
|
|
d7098e87ee | ||
|
|
64ecb553e4 | ||
|
|
2130cef3a9 | ||
|
|
f647223e94 | ||
|
|
a0ebe5ed54 | ||
|
|
b05378cdf7 | ||
|
|
423faf7af1 | ||
|
|
f9bb7ba270 | ||
|
|
4bc2de7b7b | ||
|
|
d199b41937 | ||
|
|
7fe63cdb50 | ||
|
|
f4531130b6 | ||
|
|
c6a24b3907 | ||
|
|
2c44cc9cd2 | ||
|
|
739737dc2b | ||
|
|
6bd0840863 | ||
|
|
323f41d14b | ||
|
|
8115a709e9 | ||
|
|
b0344f1426 | ||
|
|
9fb663210d | ||
|
|
881b1da6a7 | ||
|
|
8e350ca4a7 | ||
|
|
a0a355c3a7 | ||
|
|
7ac1e00d01 | ||
|
|
7e22f26b52 | ||
|
|
4f02795c60 | ||
|
|
f430aff4af | ||
|
|
f05d64b01e | ||
|
|
cae6bdf437 | ||
|
|
7d8f7aafdd | ||
|
|
5d279ed22c | ||
|
|
1edd52014e | ||
|
|
1f2f247c1d | ||
|
|
7c2a807278 | ||
|
|
21c7374177 | ||
|
|
1495285a6a | ||
|
|
bdeb96d0a7 | ||
|
|
5963294b04 | ||
|
|
2c58bdbfb2 | ||
|
|
f00bf7cf19 | ||
|
|
2fe6282157 | ||
|
|
a6cca7cfb0 | ||
|
|
2bfc62d9a5 | ||
|
|
dcc4563c8c | ||
|
|
a4f84844bc | ||
|
|
941221cba9 | ||
|
|
0b6d654ec8 | ||
|
|
b8236d55e2 | ||
|
|
4a1e21ac83 | ||
|
|
ee69dc5e44 | ||
|
|
fd06c52dec | ||
|
|
91910b4606 | ||
|
|
f10faf004e | ||
|
|
f0750997de | ||
|
|
f7333c89bb | ||
|
|
19fb3fd56c | ||
|
|
d197ddeb15 | ||
|
|
46bfd2cdac | ||
|
|
45b5545cf7 | ||
|
|
e881043787 | ||
|
|
2b95eba51b | ||
|
|
4177708e49 |
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -39,6 +39,8 @@ body:
|
||||
- Image Resizer
|
||||
- Keyboard Manager
|
||||
- MD Preview
|
||||
- PDF Preview
|
||||
- PDF Thumbnail
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
- Shortcut Guide
|
||||
|
||||
1
.github/actions/spell-check/excludes.txt
vendored
@@ -25,6 +25,7 @@ ignore$
|
||||
\.png$
|
||||
\.woff$
|
||||
\.zip$
|
||||
^doc/devdocs/akaLinks\.md$
|
||||
^src/common/logger/logger\.vcxproj\.filters$
|
||||
^src/common/notifications/BackgroundActivatorDLL/BackgroundActivator\.vcxproj\.filters$
|
||||
^src/common/notifications/BackgroundActivatorDLL/cpp\.hint$
|
||||
|
||||
70
.github/actions/spell-check/expect.txt
vendored
@@ -5,17 +5,19 @@ abcdef
|
||||
abcdefgh
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
abgr
|
||||
abi
|
||||
ABlocked
|
||||
ABOUTBOX
|
||||
Abug
|
||||
accctrl
|
||||
Acceleratorkeys
|
||||
ACCEPTFILES
|
||||
accessibile
|
||||
accessibilityinsights
|
||||
Accessible
|
||||
Acl
|
||||
aclapi
|
||||
AColumn
|
||||
Accessible
|
||||
acos
|
||||
acrt
|
||||
Actioncenter
|
||||
@@ -103,6 +105,7 @@ asm
|
||||
asmx
|
||||
aspnet
|
||||
aspx
|
||||
ASSOCCHANGED
|
||||
ASYNCWINDOWPLACEMENT
|
||||
ASYNCWINDOWPOS
|
||||
atl
|
||||
@@ -125,8 +128,9 @@ AUTOMATIONPROPERTIES
|
||||
Autorun
|
||||
AUTOSIZECOLUMNS
|
||||
AUTOUPDATE
|
||||
available
|
||||
AValid
|
||||
avialable
|
||||
awakeness
|
||||
awakeversion
|
||||
AWAYMODE
|
||||
AYUV
|
||||
@@ -182,6 +186,7 @@ Browsable
|
||||
bsd
|
||||
bstr
|
||||
bti
|
||||
btn
|
||||
BTNFACE
|
||||
Bto
|
||||
buf
|
||||
@@ -201,6 +206,7 @@ CANRENAME
|
||||
Captureascreenshot
|
||||
CAPTURECHANGED
|
||||
CASESENSITIVE
|
||||
cassert
|
||||
CAtl
|
||||
CCDDEE
|
||||
ccf
|
||||
@@ -229,10 +235,13 @@ CHILDACTIVATE
|
||||
CHILDWINDOW
|
||||
chrdavis
|
||||
chrisharris
|
||||
chromaticities
|
||||
chrono
|
||||
Chrzan
|
||||
chrzan
|
||||
CHT
|
||||
cielab
|
||||
CIEXYZ
|
||||
CImage
|
||||
cinttypes
|
||||
cla
|
||||
@@ -288,6 +297,7 @@ comhost
|
||||
cominterop
|
||||
commandline
|
||||
commctrl
|
||||
companding
|
||||
Compat
|
||||
COMPOSITIONFULL
|
||||
comsupp
|
||||
@@ -374,8 +384,8 @@ CXSMICON
|
||||
CXVIRTUALSCREEN
|
||||
cxx
|
||||
cxxopts
|
||||
CYMK
|
||||
CYSMICON
|
||||
CYVIRTUALSCREEN
|
||||
cziplib
|
||||
Dac
|
||||
dacl
|
||||
@@ -395,6 +405,7 @@ dbg
|
||||
Dbghelp
|
||||
DBLCLKS
|
||||
DBLEPSILON
|
||||
dchristensen
|
||||
DCOM
|
||||
dcomp
|
||||
DComposition
|
||||
@@ -402,6 +413,7 @@ ddd
|
||||
ddee
|
||||
ddf
|
||||
Deact
|
||||
debian
|
||||
DECLAR
|
||||
declspec
|
||||
decltype
|
||||
@@ -423,6 +435,7 @@ Delimarsky
|
||||
delims
|
||||
dend
|
||||
DENORMAL
|
||||
Deondre
|
||||
depersist
|
||||
deprioritized
|
||||
deps
|
||||
@@ -484,6 +497,8 @@ DPICHANGED
|
||||
DPolicy
|
||||
DPopup
|
||||
DPSAPI
|
||||
DQTAT
|
||||
DQTYPE
|
||||
DRAWFRAME
|
||||
drawingcolor
|
||||
dreamsofameaningfullife
|
||||
@@ -563,6 +578,7 @@ errc
|
||||
errorlevel
|
||||
ERRORMESSAGE
|
||||
ERRORTITLE
|
||||
ESettings
|
||||
esize
|
||||
estdir
|
||||
etcore
|
||||
@@ -639,6 +655,7 @@ finalizer
|
||||
findfast
|
||||
findstr
|
||||
FIXEDFILEINFO
|
||||
FFAA
|
||||
FLASHZONES
|
||||
FLASHZONESONQUICKSWITCH
|
||||
flt
|
||||
@@ -650,6 +667,7 @@ FOF
|
||||
FOFX
|
||||
FOLDERID
|
||||
folderpath
|
||||
FORCEMINIMIZE
|
||||
FORCEOFFLINE
|
||||
foreach
|
||||
formatetc
|
||||
@@ -659,6 +677,7 @@ FRAMEDOWNLOAD
|
||||
franky
|
||||
Froml
|
||||
fstream
|
||||
ftp
|
||||
ftps
|
||||
FTYPE
|
||||
FULLNAME
|
||||
@@ -734,6 +753,7 @@ HDN
|
||||
hdrop
|
||||
HDS
|
||||
HEB
|
||||
Heiko
|
||||
helptext
|
||||
HEVC
|
||||
hfile
|
||||
@@ -775,6 +795,7 @@ hotspot
|
||||
HPAINTBUFFER
|
||||
hpj
|
||||
hpp
|
||||
HRAWINPUT
|
||||
hread
|
||||
HREDRAW
|
||||
href
|
||||
@@ -794,6 +815,7 @@ Htmdid
|
||||
html
|
||||
htt
|
||||
http
|
||||
HTTRANSPARENT
|
||||
hwb
|
||||
HWINEVENTHOOK
|
||||
hwnd
|
||||
@@ -806,6 +828,7 @@ Hyperlink
|
||||
IAction
|
||||
IActivated
|
||||
IAnimatable
|
||||
ianjoneill
|
||||
IApp
|
||||
IApplication
|
||||
IAppx
|
||||
@@ -826,6 +849,7 @@ ICollection
|
||||
IColor
|
||||
ICommand
|
||||
IComparer
|
||||
ICompositor
|
||||
ICONERROR
|
||||
ICONINFORMATION
|
||||
IContext
|
||||
@@ -840,8 +864,10 @@ IDesktop
|
||||
IDictionary
|
||||
IDirectory
|
||||
IDispatch
|
||||
IDispatcher
|
||||
IDisposable
|
||||
idl
|
||||
IDLIST
|
||||
IDOK
|
||||
IDOn
|
||||
IDR
|
||||
@@ -853,6 +879,7 @@ IEasing
|
||||
IEnum
|
||||
IEnumerable
|
||||
IEnumerator
|
||||
IEnvironment
|
||||
IEquality
|
||||
IEquatable
|
||||
IEvent
|
||||
@@ -925,6 +952,7 @@ INPUTHARDWARE
|
||||
INPUTKEYBOARD
|
||||
INPUTLANGCHANGED
|
||||
INPUTMOUSE
|
||||
INPUTSINK
|
||||
INPUTTYPE
|
||||
INSTALLDESKTOPSHORTCUT
|
||||
INSTALLDIR
|
||||
@@ -992,6 +1020,7 @@ IShell
|
||||
ISingle
|
||||
ISmart
|
||||
isocpp
|
||||
iss
|
||||
IStorage
|
||||
IStream
|
||||
istreambuf
|
||||
@@ -1002,6 +1031,7 @@ ITab
|
||||
ITask
|
||||
ITemplate
|
||||
ITEMSTATEICONCLICK
|
||||
ITerminal
|
||||
ITest
|
||||
ith
|
||||
IThrottled
|
||||
@@ -1021,11 +1051,13 @@ IWeb
|
||||
IWIC
|
||||
IWindows
|
||||
IWork
|
||||
IXaml
|
||||
IXml
|
||||
ixx
|
||||
IYUV
|
||||
IZone
|
||||
IZoom
|
||||
jakeoeding
|
||||
JArray
|
||||
jarro
|
||||
Jarryd
|
||||
@@ -1050,7 +1082,9 @@ jyuwono
|
||||
kbd
|
||||
KBDLLHOOKSTRUCT
|
||||
kbm
|
||||
KERNELBASE
|
||||
KEYBDINPUT
|
||||
keybindings
|
||||
keyboardeventhandlers
|
||||
keyboardmanager
|
||||
keyboardmanagercommon
|
||||
@@ -1127,6 +1161,7 @@ lmcons
|
||||
LMEM
|
||||
LMENU
|
||||
lnk
|
||||
LOADSTRING
|
||||
LOCALAPPDATA
|
||||
LOCALDISPLAY
|
||||
localhost
|
||||
@@ -1148,6 +1183,7 @@ lowlevel
|
||||
LOWORD
|
||||
lparam
|
||||
LPBYTE
|
||||
LPCITEMIDLIST
|
||||
LPCMINVOKECOMMANDINFO
|
||||
LPCREATESTRUCT
|
||||
LPCTSTR
|
||||
@@ -1194,6 +1230,7 @@ LVS
|
||||
LVSIL
|
||||
LWA
|
||||
lwin
|
||||
LZero
|
||||
lzw
|
||||
mailto
|
||||
MAINICON
|
||||
@@ -1258,6 +1295,7 @@ mii
|
||||
MIIM
|
||||
millis
|
||||
mimetype
|
||||
mindaro
|
||||
Minimizeallwindows
|
||||
MINIMIZEBOX
|
||||
miniz
|
||||
@@ -1306,6 +1344,7 @@ msedge
|
||||
MSGFLT
|
||||
mshtmdid
|
||||
msi
|
||||
msiexec
|
||||
MSIFASTINSTALL
|
||||
MSIHANDLE
|
||||
MSIINSTALLER
|
||||
@@ -1314,6 +1353,7 @@ msiquery
|
||||
MSIRESTARTMANAGERCONTROL
|
||||
msix
|
||||
msixbundle
|
||||
MSIXCA
|
||||
MSIXVERSION
|
||||
MSLLHOOKSTRUCT
|
||||
Mso
|
||||
@@ -1445,6 +1485,7 @@ nuget
|
||||
null
|
||||
nullopt
|
||||
nullptr
|
||||
numberbox
|
||||
NUMLOCK
|
||||
NUMPAD
|
||||
nunit
|
||||
@@ -1527,6 +1568,7 @@ PCWSTR
|
||||
pdb
|
||||
pdbonly
|
||||
pdf
|
||||
pdfpreviewhandler
|
||||
pdo
|
||||
pdto
|
||||
pdtobj
|
||||
@@ -1545,6 +1587,7 @@ phwnd
|
||||
pici
|
||||
pid
|
||||
pidl
|
||||
PIDLIST
|
||||
PINDIR
|
||||
pinfo
|
||||
pinvoke
|
||||
@@ -1577,6 +1620,7 @@ powerlauncher
|
||||
powerpreview
|
||||
powerrename
|
||||
POWERRENAMETEST
|
||||
POWERRENAMEUIHOST
|
||||
powershell
|
||||
powertoy
|
||||
powertoysinterop
|
||||
@@ -1617,6 +1661,7 @@ pri
|
||||
PRINTCLIENT
|
||||
printf
|
||||
prm
|
||||
proactively
|
||||
PROCESSKEY
|
||||
PRODUCTVERSION
|
||||
PROGDLG
|
||||
@@ -1669,6 +1714,7 @@ QUERYOPEN
|
||||
QUEUESYNC
|
||||
Quickime
|
||||
QUICKLAYOUTSWITCH
|
||||
QUNS
|
||||
qwertyuiopasdfghjklzxcvbnm
|
||||
qword
|
||||
qwrtyuiopsghjklzxvnm
|
||||
@@ -1676,6 +1722,9 @@ Radiobuttons
|
||||
RAII
|
||||
RAlt
|
||||
randyrants
|
||||
RAWINPUT
|
||||
RAWINPUTDEVICE
|
||||
RAWINPUTHEADER
|
||||
RAWPATH
|
||||
rbegin
|
||||
Rbp
|
||||
@@ -1686,6 +1735,7 @@ RBUTTONUP
|
||||
rclsid
|
||||
RCONTROL
|
||||
RCtrl
|
||||
rdeveen
|
||||
RDW
|
||||
readme
|
||||
READMODE
|
||||
@@ -1759,6 +1809,7 @@ rgs
|
||||
rhs
|
||||
ricardosantos
|
||||
Richtext
|
||||
RIDEV
|
||||
RIGHTSCROLLBAR
|
||||
riid
|
||||
riverar
|
||||
@@ -1805,6 +1856,7 @@ scancode
|
||||
scanled
|
||||
schedtasks
|
||||
Scn
|
||||
SCOOBE
|
||||
SCOPEID
|
||||
screenshot
|
||||
scrollable
|
||||
@@ -1849,6 +1901,8 @@ sfgao
|
||||
SFGAOF
|
||||
SHAREIMAGELISTS
|
||||
sharpkeys
|
||||
SHCNE
|
||||
SHCNF
|
||||
shcore
|
||||
shellapi
|
||||
SHELLDLL
|
||||
@@ -1881,7 +1935,9 @@ SHOWDEFAULT
|
||||
SHOWELEVATIONPROMPT
|
||||
SHOWMAXIMIZED
|
||||
SHOWMINIMIZED
|
||||
SHOWMINNOACTIVE
|
||||
SHOWNA
|
||||
SHOWNOACTIVATE
|
||||
SHOWNORMAL
|
||||
SHOWWINDOW
|
||||
shtypes
|
||||
@@ -1944,6 +2000,7 @@ SRCCOPY
|
||||
sre
|
||||
sregex
|
||||
SResize
|
||||
SRGB
|
||||
srme
|
||||
srre
|
||||
srw
|
||||
@@ -1977,6 +2034,7 @@ stdlib
|
||||
STDMETHODCALLTYPE
|
||||
STDMETHODIMP
|
||||
stdout
|
||||
stefan
|
||||
STEPIT
|
||||
stgm
|
||||
STGMEDIUM
|
||||
@@ -2103,6 +2161,7 @@ todo
|
||||
toggleswitch
|
||||
toolbar
|
||||
Toolchain
|
||||
toolkitcontrols
|
||||
toolkitconverters
|
||||
toolset
|
||||
toolstrip
|
||||
@@ -2120,6 +2179,7 @@ traies
|
||||
transcoded
|
||||
transparrent
|
||||
TRAYMOUSEMESSAGE
|
||||
triaging
|
||||
TRK
|
||||
trl
|
||||
trunc
|
||||
@@ -2129,7 +2189,9 @@ tsx
|
||||
TYMED
|
||||
typedef
|
||||
TYPEKEY
|
||||
TYPEKEYBOARD
|
||||
TYPELIB
|
||||
TYPEMOUSE
|
||||
typename
|
||||
typeof
|
||||
typeparam
|
||||
@@ -2432,6 +2494,7 @@ XSmall
|
||||
XStr
|
||||
XToolset
|
||||
xunit
|
||||
XVIRTUALSCREEN
|
||||
Yaml
|
||||
YDiff
|
||||
YIncrement
|
||||
@@ -2442,6 +2505,7 @@ YStr
|
||||
YUY
|
||||
yuyoyuppe
|
||||
YUYV
|
||||
YVIRTUALSCREEN
|
||||
YVU
|
||||
YVYU
|
||||
ZEROINIT
|
||||
|
||||
@@ -9,7 +9,11 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: "windevbuildagents"
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
timeoutInMinutes: 120
|
||||
strategy:
|
||||
maxParallel: 10
|
||||
|
||||
@@ -121,7 +121,10 @@ steps:
|
||||
testSelector: 'testAssemblies'
|
||||
testAssemblyVer2: |
|
||||
**\UnitTests-SvgThumbnailProvider.dll
|
||||
**\UnitTests-PdfThumbnailProvider.dll
|
||||
**\Microsoft.PowerToys.Settings.UI.UnitTests.dll
|
||||
**\UnitTests-MarkdownPreviewHandler.dll
|
||||
**\UnitTests-PdfPreviewHandler.dll
|
||||
**\UnitTests-SvgPreviewHandler.dll
|
||||
**\UnitTests-PreviewHandlerCommon.dll
|
||||
**\PreviewPaneUnitTests.dll
|
||||
@@ -135,7 +138,8 @@ steps:
|
||||
**\Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest.dll
|
||||
**\Microsoft.Plugin.Uri.UnitTests.dll
|
||||
**\Wox.Test.dll
|
||||
**\Microsoft.PowerToys.Run.Plugin.System.UnitTests.dll
|
||||
**\Microsoft.PowerToys.Run.Plugin.System.UnitTests.dll
|
||||
**\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests.dll
|
||||
!**\obj\**
|
||||
|
||||
# Native dlls
|
||||
|
||||
@@ -32,6 +32,9 @@ restore:
|
||||
- !!defaultcommand
|
||||
name: 'Restore Installer'
|
||||
command: '.pipelines\restore-installer.cmd'
|
||||
- !!defaultcommand
|
||||
name: 'Restore Installer BootStrapper'
|
||||
command: '.pipelines\restore-bootstrapper.cmd'
|
||||
- !!defaultcommand
|
||||
name: 'Restore Localization packages'
|
||||
command: '.pipelines\restore-localization.cmd'
|
||||
@@ -39,8 +42,6 @@ restore:
|
||||
name: 'Restore Tools packages'
|
||||
command: '.pipelines\restore-tools.cmd'
|
||||
|
||||
|
||||
|
||||
build:
|
||||
commands:
|
||||
# Localize the files before the Build PowerToys step to generate translated resx files from the lcl files
|
||||
@@ -61,11 +62,12 @@ build:
|
||||
- 'x64/**/*.pdb'
|
||||
exclude:
|
||||
- 'x64/Release/obj/**/*.pdb'
|
||||
# TODO(yuyoyuppe): uncomment when VCM should be enabled
|
||||
- from: 'x86/Release'
|
||||
to: 'Build_Output'
|
||||
include:
|
||||
- 'modules\VideoConference\VideoConferenceProxyFilter_x86.dll'
|
||||
signing_options:
|
||||
sign_inline: true # This does signing as soon as this command completes
|
||||
- from: 'x64/Release'
|
||||
to: 'Build_Output'
|
||||
include:
|
||||
@@ -108,6 +110,10 @@ build:
|
||||
- 'modules\FileExplorerPreview\ManagedTelemetry.dll'
|
||||
- 'modules\FileExplorerPreview\MarkdownPreviewHandler.dll'
|
||||
- 'modules\FileExplorerPreview\MarkdownPreviewHandler.comhost.dll'
|
||||
- 'modules\FileExplorerPreview\PdfPreviewHandler.dll'
|
||||
- 'modules\FileExplorerPreview\PdfPreviewHandler.comhost.dll'
|
||||
- 'modules\FileExplorerPreview\PdfThumbnailProvider.dll'
|
||||
- 'modules\FileExplorerPreview\PdfThumbnailProvider.comhost.dll'
|
||||
- 'modules\FileExplorerPreview\powerpreview.dll'
|
||||
- 'modules\FileExplorerPreview\PreviewHandlerCommon.dll'
|
||||
- 'modules\FileExplorerPreview\SvgPreviewHandler.dll'
|
||||
@@ -153,6 +159,8 @@ build:
|
||||
- 'modules\launcher\Plugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll'
|
||||
- 'modules\launcher\Plugins\Service\Microsoft.PowerToys.Run.Plugin.Service.dll'
|
||||
- 'modules\launcher\Plugins\System\Microsoft.PowerToys.Run.Plugin.System.dll'
|
||||
- 'modules\launcher\Plugins\WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll'
|
||||
- 'modules\launcher\Plugins\WindowsTerminal\ManagedTelemetry.dll'
|
||||
- 'modules\launcher\PowerLauncher.dll'
|
||||
- 'modules\launcher\PowerLauncher.exe'
|
||||
- 'modules\launcher\PowerLauncher.Telemetry.dll'
|
||||
@@ -162,13 +170,14 @@ build:
|
||||
- 'modules\launcher\Wox.dll'
|
||||
- 'modules\launcher\Wox.Infrastructure.dll'
|
||||
- 'modules\launcher\Wox.Plugin.dll'
|
||||
- 'modules\MouseUtils\FindMyMouse.dll'
|
||||
- 'modules\PowerRename\PowerRenameExt.dll'
|
||||
- 'modules\PowerRename\PowerRenameUILib.dll'
|
||||
- 'modules\PowerRename\PowerRename.exe'
|
||||
- 'modules\ShortcutGuide\ShortcutGuide\PowerToys.ShortcutGuide.exe'
|
||||
- 'modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.dll'
|
||||
# TODO(yuyoyuppe): uncomment when VCM should be enabled
|
||||
- 'modules\VideoConference\VideoConferenceModule.dll'
|
||||
- 'modules\VideoConference\VideoConferenceProxyFilter_x64.dll'
|
||||
- 'modules\VideoConference\VideoConferenceProxyFilter_x86.dll'
|
||||
- 'Settings\ManagedTelemetry.dll'
|
||||
- 'Settings\Microsoft.PowerToys.Settings.UI.exe'
|
||||
- 'Settings\Microsoft.PowerToys.Settings.UI.Lib.dll'
|
||||
@@ -224,7 +233,6 @@ build:
|
||||
signing_options:
|
||||
sign_inline: true # This does signing as soon as this command completes
|
||||
|
||||
|
||||
#package:
|
||||
# commands:
|
||||
# - !!buildcommand
|
||||
|
||||
3
.pipelines/restore-bootstrapper.cmd
Normal file
@@ -0,0 +1,3 @@
|
||||
cd /D "%~dp0"
|
||||
|
||||
nuget restore ../installer/PowerToysBootstrapper/PowerToysBootstrapper.sln || exit /b 1
|
||||
@@ -9,6 +9,9 @@ Names are in alphabetical order based on first name.
|
||||
### [@davidegiacometti](https://github.com/davidegiacometti) - [Davide Giacometti](https://www.linkedin.com/in/davidegiacometti/)
|
||||
Davide has helped fix multiple bugs, added new features, as well as help us with the ARM64 effort by porting applications to .NET Core.
|
||||
|
||||
### [@htcfreek](https://github.com/htcfreek) - Heiko
|
||||
Heiko has helped triaging, discussing, and creating a substantial number of issues and contributed features/fixes to PowerToys Run.
|
||||
|
||||
### [@jsoref](https://github.com/jsoref) - [Josh Soref](https://check-spelling.dev/)
|
||||
Helping keep our spelling correct :)
|
||||
|
||||
@@ -69,6 +72,10 @@ PowerToys Awake is a tool to keep your computer awake.
|
||||
|
||||
Color Picker is from Martin.
|
||||
|
||||
### [@oldnewthing](https://github.com/oldnewthing) - Raymond Chen
|
||||
|
||||
Find My Mouse is based on Raymond Chen's SuperSonar.
|
||||
|
||||
### Microsoft InVEST team
|
||||
|
||||
This amazing team helped PowerToys develop PowerToys Run and Keyboard manager as well as update our Settings to v2. @alekhyareddy28, @arjunbalgovind, @jyuwono @laviusmotileng-ms, @ryanbodrug-microsoft, @saahmedm, @somil55, @traies, @udit3333
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
<!-- Global props -->
|
||||
<PropertyGroup Label="Globals" Condition="'$(OverrideWindowsTargetPlatformVersion)'!='True'">
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Props that are constant for both Debug and Release configurations -->
|
||||
@@ -84,7 +84,6 @@
|
||||
<PlatformToolset Condition="'$(OverridePlatformToolset)'!='True'">v142</PlatformToolset>
|
||||
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Debug/Release props -->
|
||||
|
||||
132
PowerToys.sln
@@ -5,7 +5,6 @@ MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner.vcxproj", "{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{217DF501-135C-4E38-BFC8-99D4821032EA} = {217DF501-135C-4E38-BFC8-99D4821032EA}
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
|
||||
{48804216-2A0E-4168-A6D8-9CD068D14227} = {48804216-2A0E-4168-A6D8-9CD068D14227}
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
|
||||
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} = {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}
|
||||
@@ -17,6 +16,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner
|
||||
{0B593A6C-4143-4337-860E-DB5710FB87DB} = {0B593A6C-4143-4337-860E-DB5710FB87DB}
|
||||
{E364F67B-BB12-4E91-B639-355866EBCD8B} = {E364F67B-BB12-4E91-B639-355866EBCD8B}
|
||||
{D940E07F-532C-4FF3-883F-790DA014F19A} = {D940E07F-532C-4FF3-883F-790DA014F19A}
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF} = {69E1EE8D-143A-4060-9129-4658ACF14AAF}
|
||||
{DA425894-6E13-404F-8DCB-78584EC0557A} = {DA425894-6E13-404F-8DCB-78584EC0557A}
|
||||
{2BE46397-4DFA-414C-9BD4-41E4BBF8CB34} = {2BE46397-4DFA-414C-9BD4-41E4BBF8CB34}
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915} = {A7D5099E-F0FD-4BF3-8522-5A682759F915}
|
||||
@@ -56,26 +56,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "powerrename", "powerrename"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameExt", "src\modules\powerrename\dll\PowerRenameExt.vcxproj", "{B25AC7A5-FB9F-4789-B392-D5C85E948670}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameLib", "src\modules\powerrename\lib\PowerRenameLib.vcxproj", "{51920F1F-C28C-4ADF-8660-4238766796C2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUI", "src\modules\powerrename\ui\PowerRenameUI.vcxproj", "{0E072714-D127-460B-AFAD-B4C40B412798}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameTest", "src\modules\powerrename\testapp\PowerRenameTest.vcxproj", "{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
|
||||
{B25AC7A5-FB9F-4789-B392-D5C85E948670} = {B25AC7A5-FB9F-4789-B392-D5C85E948670}
|
||||
EndProjectSection
|
||||
@@ -83,9 +75,6 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModuleTemplateCompileTest", "tools\project_template\ModuleTemplate\ModuleTemplateCompileTest.vcxproj", "{64A80062-4D8B-4229-8A38-DFA1D7497749}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUWPUI", "src\modules\powerrename\UWPui\PowerRenameUWPUI.vcxproj", "{0485F45C-EA7A-4BB5-804B-3E8D14699387}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager", "src\modules\keyboardmanager\dll\KeyboardManager.vcxproj", "{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}"
|
||||
EndProject
|
||||
@@ -152,6 +141,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerLauncher", "src\module
|
||||
{5043CECE-E6A7-4867-9CBE-02D27D83747A} = {5043CECE-E6A7-4867-9CBE-02D27D83747A}
|
||||
{F8B870EB-D5F5-45BA-9CF7-A5C459818820} = {F8B870EB-D5F5-45BA-9CF7-A5C459818820}
|
||||
{74F1B9ED-F59C-4FE7-B473-7B453E30837E} = {74F1B9ED-F59C-4FE7-B473-7B453E30837E}
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}
|
||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF} = {4BABF3FE-3451-42FD-873F-3C332E18DCEF}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
@@ -166,7 +156,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PreviewHandlerCommon", "src
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MarkdownPreviewHandler", "src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj", "{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-MarkdownPreviewHandler", "src\modules\previewpane\PreviewPaneUnitTests\UnitTests-MarkdownPreviewHandler.csproj", "{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-MarkdownPreviewHandler", "src\modules\previewpane\UnitTests-MarkdownPreviewHandler\UnitTests-MarkdownPreviewHandler.csproj", "{A2B51B8B-8F90-424E-BC97-F9AB7D76CA1A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgPreviewHandler", "src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj", "{DA425894-6E13-404F-8DCB-78584EC0557A}"
|
||||
EndProject
|
||||
@@ -179,11 +169,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "powerpreview", "src\modules
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF} = {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "powerpreviewTest", "src\modules\previewpane\powerpreviewTest\powerpreviewTest.vcxproj", "{47310AB4-9034-4BD1-8D8B-E88AD21A171B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{217DF501-135C-4E38-BFC8-99D4821032EA} = {217DF501-135C-4E38-BFC8-99D4821032EA}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "settings-ui", "settings-ui", "{C3081D9A-1586-441A-B5F4-ED815B3719C1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.PowerToys.Settings.UI", "src\settings-ui\Microsoft.PowerToys.Settings.UI\Microsoft.PowerToys.Settings.UI.csproj", "{A7D5099E-F0FD-4BF3-8522-5A682759F915}"
|
||||
@@ -192,6 +177,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\.editorconfig = src\.editorconfig
|
||||
src\tests\win-app-driver\packages.config = src\tests\win-app-driver\packages.config
|
||||
Solution.props = Solution.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Settings.UI.Library", "src\settings-ui\Microsoft.PowerToys.Settings.UI.Library\Microsoft.PowerToys.Settings.UI.Library.csproj", "{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}"
|
||||
@@ -281,13 +267,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643
|
||||
src\common\utils\EventLocker.h = src\common\utils\EventLocker.h
|
||||
src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.h
|
||||
src\common\utils\exec.h = src\common\utils\exec.h
|
||||
src\common\utils\game_mode.h = src\common\utils\game_mode.h
|
||||
src\common\utils\HDropIterator.h = src\common\utils\HDropIterator.h
|
||||
src\common\utils\HttpClient.h = src\common\utils\HttpClient.h
|
||||
src\common\utils\json.h = src\common\utils\json.h
|
||||
src\common\utils\logger_helper.h = src\common\utils\logger_helper.h
|
||||
src\common\utils\modulesRegistry.h = src\common\utils\modulesRegistry.h
|
||||
src\common\utils\MsiUtils.h = src\common\utils\MsiUtils.h
|
||||
src\common\utils\os-detect.h = src\common\utils\os-detect.h
|
||||
src\common\utils\process_path.h = src\common\utils\process_path.h
|
||||
src\common\utils\ProcessWaiter.h = src\common\utils\ProcessWaiter.h
|
||||
src\common\utils\registry.h = src\common\utils\registry.h
|
||||
src\common\utils\resources.h = src\common\utils\resources.h
|
||||
src\common\utils\string_utils.h = src\common\utils\string_utils.h
|
||||
src\common\utils\timeutil.h = src\common\utils\timeutil.h
|
||||
@@ -305,6 +295,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Telemetry", "Telemetry", "{
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Common.UI", "src\common\Microsoft.PowerToys.Common.UI\Microsoft.PowerToys.Common.UI.csproj", "{C3A17DCA-217B-462C-BB0C-BE086AF80081}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfPreviewHandler", "src\modules\previewpane\PdfPreviewHandler\PdfPreviewHandler.csproj", "{69E1EE8D-143A-4060-9129-4658ACF14AAF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PdfPreviewHandler", "src\modules\previewpane\UnitTests-PdfPreviewHandler\UnitTests-PdfPreviewHandler.csproj", "{ECC20689-002A-4354-95A6-B58DF089C6FF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Registry", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Microsoft.PowerToys.Run.Plugin.Registry.csproj", "{4BABF3FE-3451-42FD-873F-3C332E18DCEF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.Registry.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry.UnitTest\Microsoft.PowerToys.Run.Plugin.Registry.UnitTests.csproj", "{0648DF05-5DDA-4BE1-B5F2-584926EBDB65}"
|
||||
@@ -358,6 +352,25 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceProxyFilter"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VideoConference", "VideoConference", "{470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfThumbnailProvider", "src\modules\previewpane\PdfThumbnailProvider\PdfThumbnailProvider.csproj", "{11491FD8-F921-48BF-880C-7FEA185B80A1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PdfThumbnailProvider", "src\modules\previewpane\UnitTests-PdfThumbnailProvider\UnitTests-PdfThumbnailProvider.csproj", "{F40C3397-1834-4530-B2D9-8F8B8456BCDF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsTerminal", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.csproj", "{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests.csproj", "{4ED320BC-BA04-4D42-8D15-CBE62151F08B}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUIHost", "src\modules\powerrename\PowerRenameUIHost\PowerRenameUIHost.vcxproj", "{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A} = {4642D596-723F-4BFC-894C-46811219AC4A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUILib", "src\modules\powerrename\PowerRenameUILib\PowerRenameUILib.vcxproj", "{4642D596-723F-4BFC-894C-46811219AC4A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MouseUtils", "MouseUtils", "{322566EF-20DC-43A6-B9F8-616AF942579A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindMyMouse", "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj", "{E94FD11C-0591-456F-899F-EFC0CA548336}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@@ -408,12 +421,6 @@ Global
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.ActiveCfg = Release|x64
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.Build.0 = Release|x64
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x86.ActiveCfg = Release|x64
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.Build.0 = Debug|x64
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.ActiveCfg = Release|x64
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.Build.0 = Release|x64
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x86.ActiveCfg = Release|x64
|
||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.Build.0 = Debug|x64
|
||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x86.ActiveCfg = Debug|x64
|
||||
@@ -588,17 +595,9 @@ Global
|
||||
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.ActiveCfg = Release|x64
|
||||
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x64.Build.0 = Release|x64
|
||||
{217DF501-135C-4E38-BFC8-99D4821032EA}.Release|x86.ActiveCfg = Release|x64
|
||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x64.Build.0 = Debug|x64
|
||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x64.ActiveCfg = Release|x64
|
||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x64.Build.0 = Release|x64
|
||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B}.Release|x86.ActiveCfg = Release|x64
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x64.Build.0 = Debug|x64
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x64.ActiveCfg = Release|x64
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x64.Build.0 = Release|x64
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915}.Release|x86.ActiveCfg = Release|Win32
|
||||
@@ -796,6 +795,18 @@ Global
|
||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.ActiveCfg = Release|x64
|
||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x64.Build.0 = Release|x64
|
||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081}.Release|x86.ActiveCfg = Release|x64
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x64.Build.0 = Debug|x64
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x64.ActiveCfg = Release|x64
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x64.Build.0 = Release|x64
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF}.Release|x86.ActiveCfg = Release|x64
|
||||
{ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x64.Build.0 = Debug|x64
|
||||
{ECC20689-002A-4354-95A6-B58DF089C6FF}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x64.ActiveCfg = Release|x64
|
||||
{ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x64.Build.0 = Release|x64
|
||||
{ECC20689-002A-4354-95A6-B58DF089C6FF}.Release|x86.ActiveCfg = Release|x64
|
||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x64.Build.0 = Debug|x64
|
||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF}.Debug|x86.ActiveCfg = Debug|x64
|
||||
@@ -932,6 +943,49 @@ Global
|
||||
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.Build.0 = Release|x64
|
||||
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.ActiveCfg = Release|Win32
|
||||
{AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.Build.0 = Release|Win32
|
||||
{11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x64.Build.0 = Debug|x64
|
||||
{11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x64.ActiveCfg = Release|x64
|
||||
{11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x64.Build.0 = Release|x64
|
||||
{11491FD8-F921-48BF-880C-7FEA185B80A1}.Release|x86.ActiveCfg = Release|x64
|
||||
{F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x64.Build.0 = Debug|x64
|
||||
{F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x64.ActiveCfg = Release|x64
|
||||
{F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x64.Build.0 = Release|x64
|
||||
{F40C3397-1834-4530-B2D9-8F8B8456BCDF}.Release|x86.ActiveCfg = Release|x64
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Debug|x64.Build.0 = Debug|x64
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Release|x64.ActiveCfg = Release|x64
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Release|x64.Build.0 = Release|x64
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85}.Release|x86.ActiveCfg = Release|x64
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Debug|x64.Build.0 = Debug|x64
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x64.ActiveCfg = Release|x64
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x64.Build.0 = Release|x64
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Debug|x64.Build.0 = Debug|x64
|
||||
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Release|x64.ActiveCfg = Release|x64
|
||||
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Release|x64.Build.0 = Release|x64
|
||||
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Release|x86.ActiveCfg = Release|x64
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A}.Debug|x64.Build.0 = Debug|x64
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A}.Release|x64.ActiveCfg = Release|x64
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A}.Release|x64.Build.0 = Release|x64
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A}.Release|x86.ActiveCfg = Release|x64
|
||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.Build.0 = Debug|x64
|
||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.ActiveCfg = Release|x64
|
||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.Build.0 = Release|x64
|
||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x86.ActiveCfg = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -946,7 +1000,6 @@ Global
|
||||
{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{B25AC7A5-FB9F-4789-B392-D5C85E948670} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{0E072714-D127-460B-AFAD-B4C40B412798} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{2151F984-E006-4A9F-92EF-C6DDE3DC8413} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{0485F45C-EA7A-4BB5-804B-3E8D14699387} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
@@ -979,7 +1032,6 @@ Global
|
||||
{060D75DA-2D1C-48E6-A4A1-6F0718B64661} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{748417CA-F17E-487F-9411-CAFB6D3F4877} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{217DF501-135C-4E38-BFC8-99D4821032EA} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{47310AB4-9034-4BD1-8D8B-E88AD21A171B} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{A7D5099E-F0FD-4BF3-8522-5A682759F915} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
|
||||
{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033} = {5A7818A8-109C-4E1C-850D-1A654E234B0E}
|
||||
@@ -1019,6 +1071,8 @@ Global
|
||||
{B39DC643-4663-475E-B329-03F0C9918D48} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
{8F62026A-294B-41C6-8839-87463613F216} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
{C3A17DCA-217B-462C-BB0C-BE086AF80081} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
{69E1EE8D-143A-4060-9129-4658ACF14AAF} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{ECC20689-002A-4354-95A6-B58DF089C6FF} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{4BABF3FE-3451-42FD-873F-3C332E18DCEF} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||
{0648DF05-5DDA-4BE1-B5F2-584926EBDB65} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||
{6ED2F4FC-E122-4CEE-90F1-97E4CCC8BC7A} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
|
||||
@@ -1043,6 +1097,14 @@ Global
|
||||
{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}
|
||||
{AC2857B4-103D-4D6D-9740-926EBF785042} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}
|
||||
{470FBAF9-E1F8-4F3E-8786-198A1C81C8A8} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{11491FD8-F921-48BF-880C-7FEA185B80A1} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {2F305555-C296-497E-AC20-5FA1B237996A}
|
||||
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||
{4ED320BC-BA04-4D42-8D15-CBE62151F08B} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{4642D596-723F-4BFC-894C-46811219AC4A} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
||||
126
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
<img src="./doc/images/overview/PT%20hero%20image.png"/>
|
||||
|
||||
[Downloads & Release notes][github-release-link] | [Contributing to PowerToys](#contributing) | [What's Happening](#whats-happening) | [Roadmap](#powertoys-roadmap)
|
||||
[How to use PowerToys][usingPowerToys-docs-link] | [Downloads & Release notes][github-release-link] | [Contributing to PowerToys](#contributing) | [What's Happening](#whats-happening) | [Roadmap](#powertoys-roadmap)
|
||||
|
||||
## Build status
|
||||
|
||||
@@ -12,39 +12,42 @@
|
||||
|
||||
## About
|
||||
|
||||
Microsoft PowerToys is a set of utilities for power users to tune and streamline their Windows 10 experience for greater productivity. For more info on [PowerToys overviews and guides][usingPowerToys-docs-link], or any other tools and resources for [Windows development environments](https://docs.microsoft.com/windows/dev-environment/overview), head over to [docs.microsoft.com][usingPowerToys-docs-link]!
|
||||
Microsoft PowerToys is a set of utilities for power users to tune and streamline their Windows experience for greater productivity. For more info on [PowerToys overviews and how to use the utilities][usingPowerToys-docs-link], or any other tools and resources for [Windows development environments](https://docs.microsoft.com/windows/dev-environment/overview), head over to [docs.microsoft.com][usingPowerToys-docs-link]!
|
||||
|
||||
| | Current utilities: | |
|
||||
|--------------|--------------------|--------------|
|
||||
| [Awake](https://aka.ms/PowerToysOverview_Awake) | [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) | [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) |
|
||||
| [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) |
|
||||
| [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
|
||||
| [Video Conference Mute (Experimental)](https://aka.ms/PowerToysOverview_VideoConference) | | |
|
||||
| [Video Conference Mute (Experimental)](https://aka.ms/PowerToysOverview_VideoConference) | [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | |
|
||||
|
||||
## Installing and running Microsoft PowerToys
|
||||
|
||||
### Requirements
|
||||
|
||||
- Windows 10 v1903 (build 18362) or newer.
|
||||
- ⚠️ PowerToys (v0.37.0 and newer) requires Windows 10 v1903 (18362) or newer.
|
||||
- ⚠️ PowerToys (v0.37.0 and newer) requires Windows 10 v1903 (18362) or newer.
|
||||
|
||||
- Have [.NET Core 3.1.15 Desktop Runtime](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-desktop-3.1.15-windows-x64-installer). The installer should handle this but we want to directly make people aware.
|
||||
|
||||
### Via GitHub with EXE [Recommended]
|
||||
|
||||
#### Stable version
|
||||
|
||||
Install from the [Microsoft PowerToys GitHub releases page][github-release-link]. Click on `Assets` to show the files available in the release and then click on `PowerToysSetup-0.41.2-x64.exe` to download the PowerToys installer.
|
||||
Install from the [Microsoft Store's PowerToys page][microsoft-store-link] or use [Microsoft PowerToys GitHub releases page][github-release-link].
|
||||
|
||||
- For GitHub, click on `Assets` to show the files available in the release and then click on `PowerToysSetup-0.47.1-x64.exe` to download the PowerToys installer.
|
||||
- For Microsoft Store, you must be using the [new Microsoft Store](https://blogs.windows.com/windowsExperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/) which will be available for both Windows 11 and Windows 10.
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
#### Experimental version
|
||||
To install the Video Conference mute, please use the [v0.36 experimental version of PowerToys][github-prerelease-link] to try out this version. It includes all improvements from v0.35 in addition to the Video conference utility. Click on `Assets` to show the files available in the release and then download the .exe installer.
|
||||
To install the Video Conference mute, please use the [v0.46 experimental version of PowerToys][github-prerelease-link] to try out this version. It includes all improvements from v0.45 in addition to the Video conference utility. Click on `Assets` to show the files available in the release and then download the .exe installer.
|
||||
|
||||
### Via WinGet (Preview)
|
||||
Download PowerToys from [WinGet](https://github.com/microsoft/winget-cli#installing-the-client). To install PowerToys, run the following command from the command line / PowerShell:
|
||||
|
||||
```powershell
|
||||
WinGet install powertoys
|
||||
winget install Microsoft.PowerToys -s winget
|
||||
```
|
||||
|
||||
### Other install methods
|
||||
@@ -75,77 +78,97 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
|
||||
|
||||
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
|
||||
|
||||
### 0.43 - July 2021 Update
|
||||
### 0.47 - September 2021 Update
|
||||
|
||||
Our goals for the [v0.43 release cycle](https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F22) primarily centered around stability updates and optimizations, installer updates, general bug fixes, and accessibility improvements.
|
||||
Our goals for the [v0.47 release cycle](https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F24) primarily centered around stability updates and optimizations, installer updates, general bug fixes, and accessibility improvements.
|
||||
|
||||
An experimental version of PowerToys (v0.44) will be released the 2nd week of August and will include an updated version of Video Conference Mute.
|
||||
Notably, based on the community feedback received, PowerToys has re-introduced the highly-requested ability to activate Shortcut Guide via holding the <kbd>Win</kbd> key. PowerToys also now allows various commands in PowerToys Run to be used in either the universal English phrasing or system-localized translation. The great feedback the community provides is invaluable in helping PowerToys continually grow and improve as a product.
|
||||
|
||||
#### Highlights from v0.43
|
||||
An experimental version of PowerToys ([v0.48.1](https://github.com/microsoft/PowerToys/releases/tag/v0.48.1)) is also available, introducing improvements to our Video Conference Mute utility! All updates from the v0.47.1 release apply in v0.48.1.
|
||||
|
||||
#### Highlights from v0.47
|
||||
|
||||
**General**
|
||||
|
||||
- New UI for sizes list view in Image Resizer settings. Thanks @niels9001!
|
||||
- Fixed FileInUse errors during install/update scenarios.
|
||||
- Fixed toggle switches on PowerToys run settings to display correctly.
|
||||
- Fixed header text not updating when theme color is changed. Thanks @niels9001!
|
||||
- Changed tooltip text for systray icon to be on a single line for Windows 11 compatibility.
|
||||
- Expanded the Report Bug tool to collect more robust diagnostic information.
|
||||
- Fixed screen reader functionality to stop announcing hidden text in settings.
|
||||
- Fixed issue with new updates changing the PowerToys install location.
|
||||
- Fixed settings with NumberBox elements overlapping the delete button.
|
||||
- Fixed issue with the bug report tool not generating .zip files.
|
||||
- Updated the shortcut configuration experience in Settings. Thanks @niels9001!
|
||||
- Fixed inconsistent width of sidebar icons. Thanks @niels9001!
|
||||
- Fixed sidebar UI not scaling for longer text strings in certain localizations. Thanks @niels9001!
|
||||
- Fixed issue with settings not displaying invalid keystroke assignments. Thanks @niels9001!
|
||||
- Added user defined shortcuts when set to the "Welcome to PowerToys" instead of the default shortcuts.
|
||||
|
||||
### Awake
|
||||
|
||||
- Fixed bug when right-clicking menu of Awake app icon. Thanks @dend!
|
||||
- Fixed high CPU usage for timed keep awake. Thanks @dend!
|
||||
- Fixed Awake icon spamming notification tray. Thanks @dend!
|
||||
- Added telemetry to collect Awake settings and logs.
|
||||
|
||||
### Color Picker
|
||||
|
||||
- Fixed escape behavior so that only the fly-out is closed if active.
|
||||
- Fixed several accessibility issues related to screen reader functionality and general usage of Color Picker.
|
||||
- Accessibility issues addressed. Thanks @niels9001!
|
||||
- Added CIELAB and CIEXYZ color formats. Thanks @RubenFricke!
|
||||
- Fixed bug where changing RGB values manually doesn't automatically update the color displayed. Thanks @martinchrzan!
|
||||
|
||||
### FancyZones
|
||||
|
||||
- Fixed bug causing multi-monitor spanning errors.
|
||||
- Added minimum zone size limit to the settings.
|
||||
- Fixed issue where re-opened windows don't appear in previously assigned zone.
|
||||
- Fixed excluded apps setting to save on text change instead of when leaving focus.
|
||||
- Fixed corrupt/outdated plugins load crash.
|
||||
- Fixed issue with FancyZones not working after computer goes to sleep.
|
||||
- Added screen reader confirmation to canvas editor when new zones are added.
|
||||
- Fixed regression where restarting computer resets user defined layouts to the default selection.
|
||||
- Fixed issues with Grid layout editor not showing the "Save" and "Cancel" buttons.
|
||||
- Fixed accessibility issue where users could not add or merge zones using the keyboard.
|
||||
- Added a flyout describe the prerequisites for the "Allow zones to span across monitors" option.
|
||||
- Fixed various crashing bugs.
|
||||
|
||||
### File Explorer add-ons
|
||||
|
||||
- Added PDF preview and thumbnail provider for Windows Explorer. Thanks @rdeveen!
|
||||
|
||||
### Image Resizer
|
||||
|
||||
- Added default values for newly added sizes. Thanks @htcfreek!
|
||||
- Fixed regression where spaces in the filename format settings couldn't be registered.
|
||||
- Corrected scaling issues with Image Resizer Window. Thanks @niels9001!
|
||||
- Fixed issue where PowerToys crashes when json settings are not formatted properly. Thanks @davidegiacometti!
|
||||
|
||||
### Keyboard Manager
|
||||
|
||||
- Fixed screen reader usage bugs to increase intuitiveness.
|
||||
- Fixed crash when adding a shortcut.
|
||||
- Fixed issue with Re-mappings window not displaying.
|
||||
- Fixed issue when remapping a shortcut to <kbd>Alt</kbd>+<kbd>Tab</kbd> breaks the <kbd>Alt</kbd>+<kbd>Tab</kbd> navigation with arrow keys.
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
- Fixed crashing bug due to missing image file app.dark.png.
|
||||
- Fixed URI plugin bug with handling numeric input. Thanks @davidegiacometti!
|
||||
- Improved launch performance of PowerToys run on first call. Thanks @davidegiacometti!
|
||||
- Changed URI plugin to launch HTTPS by default instead of HTTP. Thanks @chrisharris333!
|
||||
- Added confirmation dialog when system commands are executed from PowerToys Run. Thanks @chrisharris333!
|
||||
- Improvements on subtitle layout for Settings plugin. Thanks @htcfreek!
|
||||
- Added path filters for Settings plugin via `>` character. Thanks @htcfreek!
|
||||
- Translation improvements for Settings plugin. Thanks @htcfreek!
|
||||
- Enabled translation for Settings Plugin. Thanks @htcfreek!
|
||||
- Fixed issue with PowerToys Run not being in focus when launched.
|
||||
- Fixed crash on empty/deleted environment variables when updating variables after a change. Thanks @htcfreek!
|
||||
- Corrected Registry Plugin query results.
|
||||
- Fixed crash in Registry plugin queries.
|
||||
- Fixed crash when Windows shuts down.
|
||||
- Added better description in the global results settings for plugins. Thanks @niels9001!
|
||||
- Added a confirmation box before running system commands. Thanks @chrisharris333 and @davidegiacometti!
|
||||
- Added option to use system localization our universal terminology for system commands. Thanks @davidegiacometti!
|
||||
|
||||
### Shortcut Guide
|
||||
|
||||
- Re-added the long <kbd>Win</kbd> key press to activate utility.
|
||||
|
||||
### Video Conference Mute
|
||||
|
||||
- Fixed toolbar top right vertical offset to allow users to close other app windows.
|
||||
- Fixed compatibility issues for certain systems when compiling from source.
|
||||
- Fixed an issue with the first hotkey input in the settings being focused when the page loads. Prevents unintentionally shortcut reassignment. Thanks @niels9001!
|
||||
|
||||
## Community contributions
|
||||
|
||||
We'd like to directly mention certain contributors (in alphabetical order) for their continued community support this month and helping directly make PowerToys a better piece of software.
|
||||
|
||||
[@Aaron-Junker](https://github.com/Aaron-Junker), [@chrisharris333](https://github.com/chrisharris333), [@davidegiacometti](https://github.com/davidegiacometti), [@dend](https://github.com/dend), [@franky920920](https://github.com/franky920920) [@htcfreek](https://github.com/htcfreek), [@Jay-o-Way](https://github.com/Jay-o-Way), [@jsoref](https://github.com/jsoref), [@niels9001](https://github.com/niels9001), [@royvou](https://github.com/royvou), and [@tony-xia](https://github.com/tony-xia)
|
||||
[@Aaron-Junker](https://github.com/Aaron-Junker), [@chrisharris333](https://github.com/chrisharris333), [@davidegiacometti](https://github.com/davidegiacometti), [@dend](https://github.com/dend), [@franky920920](https://github.com/franky920920), [@htcfreek](https://github.com/htcfreek), [@Jay-o-Way](https://github.com/Jay-o-Way), [@jsoref](https://github.com/jsoref), [@martinchrzan](https://github.com/martinchrzan), [@niels9001](https://github.com/niels9001), [@rdeveen](https://github.com/rdeveen) and [@RubenFricke](https://github.com/RubenFricke)
|
||||
|
||||
#### What is being planned for v0.45
|
||||
#### What is being planned for v0.49
|
||||
|
||||
For [v0.45][github-next-release-work], we are planning to work on:
|
||||
For [v0.49][github-next-release-work], we are planning to work on:
|
||||
|
||||
- Execution on new utilities and enhancements
|
||||
- UI/UX investigations to adopt WinUI and improve accessibility
|
||||
- Stability and bug fixes
|
||||
- Installer improvements
|
||||
- Upgrading PowerToys Run to .NET 5
|
||||
- Preliminary UI/UX investigations to adopt WinUI and improve accessibility
|
||||
|
||||
|
||||
## PowerToys Community
|
||||
|
||||
@@ -162,13 +185,14 @@ The application logs basic telemetry. Our Telemetry Data page (Coming Soon) has
|
||||
[oss-CLA]: https://cla.opensource.microsoft.com
|
||||
[oss-conduct-code]: CODE_OF_CONDUCT.md
|
||||
[community-link]: COMMUNITY.md
|
||||
[github-release-link]: https://github.com/microsoft/PowerToys/releases/
|
||||
[github-release-link]: https://aka.ms/installPowerToys
|
||||
[microsoft-store-link]: https://aka.ms/getPowertoys
|
||||
[roadmap]: https://github.com/microsoft/PowerToys/wiki/Roadmap
|
||||
[privacy-link]: http://go.microsoft.com/fwlink/?LinkId=521839
|
||||
[vidConfOverview]: https://aka.ms/PowerToysOverview_VideoConference
|
||||
[loc-bug]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=&template=translation_issue.md&title=
|
||||
[usingPowerToys-docs-link]: https://docs.microsoft.com/windows/powertoys/
|
||||
[usingPowerToys-docs-link]: https://aka.ms/powertoys-docs
|
||||
|
||||
<!-- items that need to be updated release to release -->
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F21
|
||||
[github-prerelease-link]: https://github.com/microsoft/PowerToys/releases/tag/v0.36.0
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F25
|
||||
[github-prerelease-link]: https://github.com/microsoft/PowerToys/releases/tag/v0.46.0
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Support
|
||||
|
||||
|
||||
## How to use Microsoft PowerToys
|
||||
|
||||
For more info on [PowerToys overviews and how to use the utilities][usingPowerToys-docs-link], or any other tools and resources for [Windows development environments](https://docs.microsoft.com/windows/dev-environment/overview), head over to [docs.microsoft.com][usingPowerToys-docs-link]!
|
||||
|
||||
## How to file issues and get help
|
||||
|
||||
This project uses [GitHub Issues][gh-issue] to [track bugs][gh-bug] and [feature requests][gh-feature]. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or
|
||||
@@ -16,3 +21,4 @@ Support for PowerToys is limited to the resources listed above.
|
||||
[gh-feature]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=&template=feature_request.md&title=
|
||||
[wiki]: https://github.com/microsoft/PowerToys/wiki
|
||||
[contributor]: https://github.com/microsoft/PowerToys/blob/master/CONTRIBUTING.md
|
||||
[usingPowerToys-docs-link]: https://aka.ms/powertoys-docs
|
||||
|
||||
6
Solution.props
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<GeneratedFilesDir>$(IntDir)Generated Files\</GeneratedFilesDir>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
2
deps/cziplib
vendored
@@ -2,7 +2,9 @@
|
||||
|
||||
| ShortUrl | TargetUrl |
|
||||
|----------|----------|
|
||||
| getpowertoys | ms-windows-store://pdp/?productid=XP89DCGQ3K6VLD |
|
||||
| installpowertoys | https://github.com/microsoft/PowerToys/releases/latest |
|
||||
| powertoys-license | https://github.com/microsoft/PowerToys/blob/master/LICENSE |
|
||||
| powertoys | https://github.com/microsoft/PowerToys |
|
||||
| PowerToysAppCompat | https://github.com/microsoft/PowerToys/wiki/Application-Compatibility |
|
||||
| powerToysCannotRemapKeys | https://docs.microsoft.com/windows/powertoys/keyboard-manager#keys-that-cannot-be-remapped |
|
||||
@@ -23,6 +25,7 @@
|
||||
| PowerToysOverview_FileExplorerAddOns | https://docs.microsoft.com/windows/powertoys/file-explorer |
|
||||
| PowerToysOverview_ImageResizer | https://docs.microsoft.com/windows/powertoys/image-resizer |
|
||||
| PowerToysOverview_KeyboardManager | https://docs.microsoft.com/windows/powertoys/keyboard-manager |
|
||||
| PowerToysOverview_MouseUtilities | https://docs.microsoft.com/windows/powertoys/mouse-utilities |
|
||||
| PowerToysOverview_PowerRename | https://docs.microsoft.com/windows/powertoys/powerrename |
|
||||
| PowerToysOverview_PowerToysRun | https://docs.microsoft.com/windows/powertoys/run |
|
||||
| PowerToysOverview_ShortcutGuide | https://docs.microsoft.com/windows/powertoys/shortcut-guide |
|
||||
|
||||
30
doc/devdocs/embedded-msix.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# How to integrate new MSIX module with PowerToys Settings and WiX installer
|
||||
[`issue_11705_with_example` branch](https://github.com/microsoft/PowerToys/tree/issue_11705_with_example) contains HelloWorld UWP C# MSIX application which reads its module settings and is installed along PowerToys.
|
||||
|
||||
## Steps
|
||||
- uncomment everything near "TODO: Use to activate embedded MSIX" comments
|
||||
- build PowerToys solution
|
||||
- deploy HelloModule module and sign it with a self-signed certificate (don't forget to put it into a trusted store)
|
||||
- build PowerToysSetup solution and install it
|
||||
|
||||
Type HelloModule into start search and observe that it was installed:
|
||||
|
||||
<img src="../images/msix/hello-module-start.png">
|
||||
|
||||
Open PowerToys settings and change the stub setting to something:
|
||||
|
||||
<img src="../images/msix/hello-module-settings-page.png">
|
||||
|
||||
Open HelloModule:
|
||||
|
||||
<img src="../images/msix/hello-module-screen.png">
|
||||
|
||||
First time you press "Load Settings", it'll detect that it doesn't have permissions to access local file system and open its system settings window, toggle it there:
|
||||
|
||||
<img src="../images/msix/hello-module-app-permissions.png">
|
||||
|
||||
(it's a known uwp limitation, see https://stackoverflow.com/a/53533414/657390)
|
||||
|
||||
HelloModule will close then, restart it, press "Load Settings" and you should see that the application was able to load the setting string which was set by the settings app:
|
||||
|
||||
<img src="../images/msix/hello-module-loaded-settings.png">
|
||||
155
doc/devdocs/modules/launcher/plugins/windowssettings.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Windows Settings Plugin
|
||||
|
||||
The Windows settings Plugin allows users to search the Windows settings.
|
||||
|
||||
## Special functions (differ from the regular functions)
|
||||
|
||||
* Support modern Windows settings (Windows 10+)
|
||||
* Support legacy Windows settings (Windows 7, 8.1)
|
||||
* Support extra programs for setting (like ODBC)
|
||||
|
||||
* Support search by the area of the setting (like `Privacy`)
|
||||
* Support search for alternative names of a setting
|
||||
|
||||
## How to add a new Windows Setting or change one
|
||||
|
||||
All Windows settings are located in `WindowsSettings.json` in root folder of the project.
|
||||
The `WindowsSettings.json` use a JSON schema file that make it easier to edit it.
|
||||
|
||||
| Key | Optional | Value type | String prefix |
|
||||
| ------------------- | -------- | ----------------- | ------------- |
|
||||
| `Name` | **No** | String | |
|
||||
| `Type` | **No** | String | `App` |
|
||||
| `Command` | **No** | String | |
|
||||
| `Areas` | Yes | List with strings | `Area` |
|
||||
| `AltNames` | Yes | List with strings | |
|
||||
| `Note` | Yes | String | `Note` |
|
||||
| `IntroducedInBuild` | Yes | Integer | |
|
||||
| `DeprecatedInBuild` | Yes | Integer | |
|
||||
|
||||
A minimum entry for the `WindowsSettings.json` looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "mySetting",
|
||||
"Type": "AppSettingsApp",
|
||||
"Command": "ms-settings:mySetting"
|
||||
}
|
||||
```
|
||||
|
||||
A full entry for the `WindowsSettings.json` looks like:
|
||||
|
||||
```json
|
||||
{
|
||||
"Name": "mySetting",
|
||||
"Type": "AppSettingsApp",
|
||||
"Command": "ms-settings:mySetting",
|
||||
"Areas": [ "AreaMySettingArea" ],
|
||||
"AltNames": [ "NiceSetting" ],
|
||||
"Note": "NoteMySettingNote",
|
||||
"IntroducedInBuild" : 1903,
|
||||
"DeprecatedInBuild" : 2004
|
||||
}
|
||||
```
|
||||
|
||||
### Remarks
|
||||
|
||||
* The `Command` for modern Windows settings should start with `ms-settings:`
|
||||
* The `Command` for legacy Windows settings should start with `control`
|
||||
* The integer value for `IntroducedInBuild` and `DeprecatedInBuild` must be in range of `0` to `4294967295`
|
||||
* The strings for `Name`, `AltNames`, `Areas`, `Type` and `Note` must not contain whitespace(s) or special characters (#, €, $, etc.)
|
||||
* The strings for `Name`, `AltNames`, `Areas`, `Type` and `Note` are used as ids for the resource file under `Properties\Resources.resx`
|
||||
* When you add new strings make sure you have add add all translations for it.
|
||||
|
||||
## Scores
|
||||
|
||||
There are three different score types with different start values.
|
||||
|
||||
| Score type | Start value |
|
||||
| ------------ | ------------ |
|
||||
| High score | 10000 |
|
||||
| Medium score | 5000 |
|
||||
| Low score | 1000 |
|
||||
|
||||
Each score will decreased by one when a condition match.
|
||||
|
||||
| Priority | Condition | Score type |
|
||||
| -------- | ----------------------------------------------------------------- | ------------ |
|
||||
| 1. | Settings name starts with the search value | High score |
|
||||
| 2. | Settings name contain the search value | Medium score |
|
||||
| 3. | Setting has no area | Low score |
|
||||
| 4. | One area of the settings starts with the search value | Low score |
|
||||
| 5. | Setting has no alternative name | Low score |
|
||||
| 6. | One alternative name of the settings starts with the search value | Medium score |
|
||||
| x. | no condition match | Low score |
|
||||
|
||||
## Important for developers
|
||||
|
||||
### General
|
||||
|
||||
* The assembly name is cached into `_assemblyName` (to avoid to many calls of `Assembly.GetExecutingAssembly()`)
|
||||
|
||||
## Microsoft.PowerToys.Run.Plugin.WindowsSettings project
|
||||
|
||||
### Important plugin values (meta-data)
|
||||
|
||||
| Name | Value |
|
||||
| --------------- | ---------------------------------------------------- |
|
||||
| ActionKeyword | `$` |
|
||||
| ExecuteFileName | `Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll` |
|
||||
| ID | `5043CECEE6A748679CBE02D27D83747A` |
|
||||
|
||||
### Interfaces used by this plugin
|
||||
|
||||
The plugin use only these interfaces (all inside the `Main.cs`):
|
||||
|
||||
* `Wox.Plugin.IPlugin`
|
||||
* `Wox.Plugin.IContextMenu`
|
||||
* `Wox.Plugin.IPluginI18n`
|
||||
|
||||
### Program files
|
||||
|
||||
| File | Content |
|
||||
| ------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Classes\WindowsSetting.cs` | A class that represent one Windows setting |
|
||||
| `Classes\WindowsSettings.cs` | A wrapper class that only contains a list with Windows settings (see 1) |
|
||||
| `Helper\ContextMenuHelper.cs` | All functions to build the context menu (for each result entry) |
|
||||
| `Helper\JsonSettingsListHelper.cs` | All functions to load the windows settings from a JSON file |
|
||||
| `Helper\ResultHelper.cs` | All functions to convert internal results into WOX results |
|
||||
| `Helper\TranslationHelper.cs` | All functions to translate the result in the surface language |
|
||||
| `Helper\UnsupportedSettingsHelper.cs` | All functions to filter not supported Windows settings out |
|
||||
| `Helper\WindowsSettingsPathHelper.cs` | All functions to build the area paths |
|
||||
| `Images\WindowsSettings.dark.png` | Symbol for the results for the dark theme |
|
||||
| `Images\WindowsSettings.light.png` | Symbol for the results for the light theme |
|
||||
| `Properties\Resources.Designer.resx` | File that contain all translatable keys |
|
||||
| `Properties\Resources.resx` | File that contain all translatable strings in the neutral language |
|
||||
| `GlobalSuppressions.cs` | Code suppressions (no real file, linked via *.csproj) |
|
||||
| `Main.cs` | Main class, the only place that implement the WOX interfaces |
|
||||
| `plugin.json` | All meta-data for this plugin |
|
||||
| `StyleCop.json` | Code style (no real file, linked via *.csproj) |
|
||||
|
||||
1. We need this extra wrapper class to make it possible that the JSON file can have and use a JSON schema file.
|
||||
Because the JSON file must have a object as root type, instead of a array.
|
||||
|
||||
### Important project values (*.csproj)
|
||||
|
||||
| Name | Value |
|
||||
| --------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| TargetFramework | `netcoreapp3.1` (means .NET Core 3.1) |
|
||||
| Platforms | `x64` |
|
||||
| Output | `..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\` |
|
||||
| RootNamespace | `Microsoft.PowerToys.Run.Plugin.WindowsSettings` |
|
||||
| AssemblyName | `Microsoft.PowerToys.Run.Plugin.WindowsSettings` |
|
||||
|
||||
### Project dependencies
|
||||
|
||||
#### Packages
|
||||
|
||||
| Package | Version |
|
||||
| ------------------------------------------------------------------------------------- | ------- |
|
||||
| [`StyleCop.Analyzers`](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) | 1.1.118 |
|
||||
|
||||
#### Projects
|
||||
|
||||
* `Wox.Infrastructure`
|
||||
* `Wox.Plugin`
|
||||
@@ -21,6 +21,3 @@ TODO
|
||||
|
||||
#### [`trace.cpp`](/src/modules/powerrename/lib/trace.cpp)
|
||||
TODO
|
||||
|
||||
#### [`PowerRenameUI.cpp`](/src/modules/powerrename/ui/PowerRenameUI.cpp)
|
||||
TODO
|
||||
BIN
doc/images/SCOOBE/SCOOBE.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
doc/images/SCOOBE/Welcome_SCOOBE.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
doc/images/icons/MouseUtils.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
doc/images/icons/PowerToys icon/PNG/1440x2160.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
doc/images/icons/PowerToys icon/PNG/2160x2160.png
Normal file
|
After Width: | Height: | Size: 282 KiB |
BIN
doc/images/msix/hello-module-app-permissions.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
doc/images/msix/hello-module-loaded-settings.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
doc/images/msix/hello-module-screen.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
doc/images/msix/hello-module-settings-page.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
doc/images/msix/hello-module-start.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
doc/images/overview/MouseUtils_large.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
doc/images/overview/MouseUtils_small.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
doc/images/overview/Original/MouseUtils.png
Normal file
|
After Width: | Height: | Size: 114 KiB |
143
doc/specs/SCOOBE.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# PowerToys SCOOBE Dialog
|
||||
|
||||
- **What is it:** Post-upgrade prompted dialog that walks users through the latest additions to PowerToys utilities and functionalities
|
||||
- **Author:** Deondre Davis
|
||||
- **Spec Status:** Draft
|
||||
|
||||
## 1. Overview
|
||||
|
||||
### 1.1. Executive Summary
|
||||
|
||||
To expand on our end-user on-boarding efforts, we seek to resolve the critical issue of informing users of new additions and improvements to PowerToys during upgrade scenarios. We currently list release notes on the main repository, in addition to affiliated information on Microsoft Docs. However, neither of these mediums are internal to the application, and thus requires users to proactively seek out information on what's been updated, or merely notice by chance what's been changed from their regular usage. As these are not ideal experiences, this document describes the inclusion of a post-upgrade 'SCOOBE' prompt that launches the previously developed OOBE dialog loaded with new information related to upgrade improvements and additions.
|
||||
|
||||
### 1.2. Key-Definitions/Concepts
|
||||
|
||||
Here are definitions for words and acronyms found throughout this document to ensure clarity:
|
||||
|
||||
- **OOBE:** Out of box experience – The users' initial interactions with the product immediately after installing the product and/or launching the product for the first time.
|
||||
- **SCOOBE:** Second chance out of box experience - The users' initial interactions with the product immediately after upgrading the product and/or launching the product for the first time after upgrading.
|
||||
|
||||
### 1.3. Goals and Non-Goals
|
||||
|
||||
Goals:
|
||||
|
||||
- Create a guided prompt that exposes the user to a brief overview of the new features and/or improvements included with the latest version of PowerToys.
|
||||
|
||||
Non-Goals:
|
||||
|
||||
- Present a copy-and-paste replica of the repository release notes. This information needs to be readily consumable, often requiring visual demonstrations of the new behavior and/or functionality that's either not possible or not necessary to depict on the repository release notes.
|
||||
|
||||
## 2. Definition of Success
|
||||
|
||||
**2.1. Customers**
|
||||
|
||||
The PowerToys SCOOBE is for existing and new power users and developers who are looking to tune and streamline their Windows experience for greater productivity and enhanced user experience. As the PowerToys customer base tends to be particularly biased against SCOOBE prompts in general, we need to present the PowerToys SCOOBE dialog in such a way that it provides immediate value to end-users to improve the likelihood of users discovering all the additions to PowerToys by making their way through the prompt.
|
||||
|
||||
**2.2. Expected Impact: Customer, and Technology Outcomes**
|
||||
|
||||
- **High Reliability** : Less than 0.1% crash rate.
|
||||
- **Increased Activation** : 50% or more adoption rate of new feature/utilities among PowerToys users who already utilize associated tools.
|
||||
- **High User Retention:** 25% or more active PowerToys users after 28 days of upgrade.
|
||||
|
||||
## 3. Requirements
|
||||
|
||||
The SCOOBE dialog builds off the currently implemented OOBE dialog originally drafted by [Niels's mock-up.](https://github.com/microsoft/PowerToys/issues/1285)
|
||||
|
||||
**3.1. Functional Requirements**
|
||||
|
||||
**3.1.1. Functional Requirements** **Overview**
|
||||
|
||||
| **No.** | **Requirement** | **Pri** |
|
||||
| --- | --- | --- |
|
||||
|1. | The SCOOBE dialog should launch immediately when PowerToys runs after having been updated. | P0 |
|
||||
|2. | The SCOOBE dialog should be contained inside the existing OOBE Dialog under its own "What's New" page of the dialog window. See figure 5.1.1. | P0 |
|
||||
|3. | The content for the SCOOBE dialog should be stored externally from the PowerToys application on the PowerToys Github in distinct wiki pages on for each release. **\*** | P0 |
|
||||
|4. | When the "What's New" page is opened, the content displayed should be loaded from the information contained in the relevant wiki pages discussed in 3.1.1.3 above. Assumes the user's device is connected to the internet. | P0 |
|
||||
|6. | The SCOOBE dialog should display information on updates that have occurred on the version of PowerToys the user has installed/updated to. | P0 |
|
||||
|7. | If PowerToys was installed for the first time, the OOBE's "Welcome to PowerToys" page should display first, not the SCOOBE's "What's New" page. See figure 5.1.2. | P0 |
|
||||
|8. | The structure of the SCOOBE dialog page's content should follow the guidelines described in section 3.1.2. | P0 |
|
||||
|9. | After SCOOBE is initially viewed, the user should be able to re-access the SCOOBE dialog at any time by opening the OOBE window again and selecting the "What's New" page. | P1 |
|
||||
|
||||
**\*** - By storing the content for SCOOBE externally from the application, the PowerToys team can update/adjust information without being constrained to PowerToys' release cycles. This is critical in the event of errors or miscommunications that would otherwise be difficult, if not impossible, to correct if stored locally to the app and shipped with the version of PowerToys being released. The content will likely be stored in an archive maintained in the PowerToys Github Wiki.
|
||||
|
||||
**3.1.2. Page Content**
|
||||
|
||||
| **No.** | **Requirement** | **Pri** |
|
||||
| --- | --- | --- |
|
||||
|1. | The SCOOBE dialog should display the version of PowerToys the user has installed, as shown in figures 5.1.1. | P0 |
|
||||
|2. | The SCOOBE dialog information should be grouped into two sections: "New Features & Improvements" and "Bug fixes Highlights". | P0 |
|
||||
|3. | The "New Features & Improvements" section should contain information related to end user functionality that has been added or updated. | P0 |
|
||||
|4. | The "New Features & Improvements" section should be subdivided by the relevant utilities updated (i.e. Color Picker, FancyZones, etc.). See figure 5.1.1 and section 5.1.3 for examples. | P1 |
|
||||
|5. | The "Bug fixes Highlights" section should contain information related to noteworthy issues/errors that were corrected. | P0 |
|
||||
|6. | If there are relevant visuals, they should be included with the information text. See figure 5.1.1. | P1 |
|
||||
|8. | The SCOOBE dialog should be scrollable if needed to fit all the content. | P0 |
|
||||
|10. | The bottom of the SCOOBE dialog should include a link to the PowerToys releases page for a complete list of versions and their release notes ([Releases · microsoft/PowerToys (github.com)](https://github.com/microsoft/PowerToys/releases)). | P1 |
|
||||
|
||||
|
||||
## 4. Measure Requirements
|
||||
|
||||
| **No.** | **Requirement** | **Implication** | **Pri** |
|
||||
| --- | --- | --- | --- |
|
||||
|1. | Date/Time of first-run following upgrade | Helps to categorize usage and retention trends across users who've been exposed to SCOOBE. | P0 |
|
||||
|2. | SCOOBE section viewed | Used to measure activation of the SCOOBE dialog. Should be 100% for the current version of PowerToys following SCOOBE's inclusion. | P0 |
|
||||
|3. | Accesses to linked documentation | Used to gauge interest in user's desire to learn more about the PowerToys described. | P1 |
|
||||
|4. | Access to linked settings pages | Used to gauge whether the settings presented to users in the dialog are sufficient for user needs. | P1 |
|
||||
|5. | PowerToys launched while SCOOBE window is active | Used to track user engagement with the various PowerToys while exploring the content in the SCOOBE. | P1 |
|
||||
|6. | Screen size | Gives crucial information for considerations related to minimal/maximum window size needed for displaying content. | P2 |
|
||||
|
||||
## 5. Appendix
|
||||
|
||||
### 5.1. Mock-ups
|
||||
|
||||
**5.1.1. SCOOBE Dialog Layout**
|
||||
|
||||

|
||||
|
||||
**5.1.2. OOBE Welcome Page**
|
||||
|
||||

|
||||
|
||||
**5.1.3. Example Textual Descriptions for Updates**
|
||||
|
||||
**v0.29 -> v0.31:**
|
||||
|
||||
- New Features & Improvements
|
||||
- FancyZones
|
||||
- Dark mode for the editor
|
||||
- Certain settings (e.g. number of zones, spacing settings) can now be set on individual layouts.
|
||||
- PowerToys Run
|
||||
- Service management plugin (Start, stop, …)
|
||||
- Registry key plugin
|
||||
- System action plugin (Reboot, lock, ...)
|
||||
- Bug fixes Highlights
|
||||
- Fixed OneDrive SVG Bug (#9999)
|
||||
- SVG are scaled appropriately when view box is provided (#9999)
|
||||
|
||||
**v0.31 -> v0.33:**
|
||||
|
||||
- New Features & Improvements
|
||||
- General
|
||||
- Added a 'First time load' experience. The hope is a quick, light way to learn about basic functionality
|
||||
- FancyZones
|
||||
- New options to change zone activation algorithm
|
||||
- PowerToys Run
|
||||
- Plugin Manager now is in settings. You can directly turn on / off, include items in general search, and change the action key
|
||||
- Improved support for additional window managers by abstracting out shell process calls
|
||||
- ~ will now act as the user home directory in Folder plugin
|
||||
- Bug fixes Highlights
|
||||
- Fix for PT Run registering the hotkey on non-supported OS versions (#9999)
|
||||
|
||||
**v0.33 -> v0.35:**
|
||||
|
||||
- New Features & Improvements
|
||||
- Color Picker
|
||||
- Esc can now be used to exit the editor
|
||||
- FancyZones
|
||||
- Added hotkeys and quick swap functionality for custom layouts! Users can now assign a hotkey in the editor and use it to quickly set a desktop's zones with Ctrl + Win + Alt + NUMBER key binding, or by pressing the hotkey while dragging a window.
|
||||
- PowerToys Run
|
||||
- Users can specify where to show the launcher window
|
||||
- New plugin added to support opening previously used Visual Studio Code workspaces, remote machines (SSH or Codespaces), and containers! When enabled, use { to query for available workspaces. Please note, this plugin is off by default.
|
||||
- Shell history now saves the raw command instead of the resolved command. A command like %appdata% would now save in the Shell history as is instead of C:\Users\YourUserName\AppData\Roaming.
|
||||
- Bug fixes Highlights
|
||||
- PowerToys will start requiring Windows 10 v1903 or greater after 0.35.x release. (#9999)
|
||||
- Fixed FancyZones placement algorithm for when the Taskbar is vertical (#9999)
|
||||
@@ -79,11 +79,20 @@
|
||||
<desktop2:DesktopPreviewHandler Clsid="74619BDA-A66B-451D-864C-A7726F5FE650"/>
|
||||
</uap3:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap3:FileTypeAssociation Name="pdfpreviewhandler" desktop2:AllowSilentDefaultTakeOver="true">
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.pdf</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
<desktop2:DesktopPreviewHandler Clsid="4F6D533B-4185-43A6-AD75-9B20034B14CA"/>
|
||||
</uap3:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<com:SurrogateServer DisplayName="Preview Handler" AppId="E39A92FE-D89A-417B-9B9D-F0B6BD564B36" SystemSurrogate="PreviewHost">
|
||||
<com:Class Id="74619BDA-A66B-451D-864C-A7726F5FE650" Path="modules\powerpreview.dll" ThreadingModel="Both"/>
|
||||
<com:Class Id="E0907A95-6F9A-4D1B-A97A-7D9D2648881E" Path="modules\powerpreview.dll" ThreadingModel="Both"/>
|
||||
<com:Class Id="4F6D533B-4185-43A6-AD75-9B20034B14CA" Path="modules\powerpreview.dll" ThreadingModel="Both"/>
|
||||
</com:SurrogateServer>
|
||||
</com:ComServer>
|
||||
</com:Extension>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "RcResource.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
std::optional<RcResource> RcResource::create(int resource_id, const std::wstring_view resource_class)
|
||||
{
|
||||
const HRSRC resHandle = FindResourceW(nullptr, MAKEINTRESOURCEW(resource_id), resource_class.data());
|
||||
if (!resHandle)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const HGLOBAL memHandle = LoadResource(nullptr, resHandle);
|
||||
if (!memHandle)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const size_t resSize = SizeofResource(nullptr, resHandle);
|
||||
if (!resSize)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto res = static_cast<const std::byte*>(LockResource(memHandle));
|
||||
if (!res)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return RcResource{ res, resSize };
|
||||
}
|
||||
|
||||
bool RcResource::saveAsFile(const std::filesystem::path destination)
|
||||
{
|
||||
std::fstream installerFile{ destination, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc };
|
||||
if (!installerFile.is_open())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
installerFile.write(reinterpret_cast<const char*>(_memory), _size);
|
||||
return true;
|
||||
}
|
||||
@@ -3,6 +3,9 @@
|
||||
#include <string_view>
|
||||
#include <optional>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
class RcResource
|
||||
{
|
||||
@@ -10,8 +13,46 @@ public:
|
||||
const std::byte* _memory = nullptr;
|
||||
size_t _size = 0;
|
||||
|
||||
static std::optional<RcResource> create(int resource_id, const std::wstring_view resource_class);
|
||||
bool saveAsFile(const std::filesystem::path destination);
|
||||
static inline std::optional<RcResource> create(int resource_id, const std::wstring_view resource_class, const HINSTANCE handle = nullptr)
|
||||
{
|
||||
const HRSRC resHandle = FindResourceW(handle, MAKEINTRESOURCEW(resource_id), resource_class.data());
|
||||
if (!resHandle)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const HGLOBAL memHandle = LoadResource(handle, resHandle);
|
||||
if (!memHandle)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const size_t resSize = SizeofResource(handle, resHandle);
|
||||
if (!resSize)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto res = static_cast<const std::byte*>(LockResource(memHandle));
|
||||
if (!res)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return RcResource{ res, resSize };
|
||||
}
|
||||
|
||||
inline bool saveAsFile(const std::filesystem::path destination)
|
||||
{
|
||||
std::fstream installerFile{ destination, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc };
|
||||
if (!installerFile.is_open())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
installerFile.write(reinterpret_cast<const char*>(_memory), _size);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
RcResource() = delete;
|
||||
|
||||
@@ -42,7 +42,9 @@ std::optional<fs::path> ExtractEmbeddedInstaller(const fs::path extractPath)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto installerPath = extractPath / L"PowerToysBootstrappedInstaller-" PRODUCT_VERSION_STRING L".msi";
|
||||
std::wstring msiName(L"PowerToysSetup-" STRINGIZE(VERSION_MAJOR) "." STRINGIZE(VERSION_MINOR) "." STRINGIZE(VERSION_REVISION) L"-");
|
||||
msiName += get_architecture_string(get_current_architecture()) + std::wstring(L".msi");
|
||||
auto installerPath = extractPath / msiName;
|
||||
return executableRes->saveAsFile(installerPath) ? std::make_optional(std::move(installerPath)) : std::nullopt;
|
||||
}
|
||||
|
||||
@@ -121,17 +123,22 @@ bool uninstall_msi_version(const std::wstring& package_path)
|
||||
return ERROR_SUCCESS == uninstall_result;
|
||||
}
|
||||
|
||||
std::optional<VersionHelper> get_installed_powertoys_version()
|
||||
struct InstalledVersionInfo
|
||||
{
|
||||
VersionHelper version;
|
||||
std::wstring install_folder;
|
||||
};
|
||||
std::optional<InstalledVersionInfo> get_installed_powertoys_version()
|
||||
{
|
||||
auto installed_path = GetMsiPackageInstalledPath();
|
||||
if (!installed_path)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
*installed_path += L"\\PowerToys.exe";
|
||||
std::wstring executable_path = *installed_path + L"\\PowerToys.exe";
|
||||
|
||||
// Get the version information for the file requested
|
||||
const DWORD fvSize = GetFileVersionInfoSizeW(installed_path->c_str(), nullptr);
|
||||
const DWORD fvSize = GetFileVersionInfoSizeW(executable_path.c_str(), nullptr);
|
||||
if (!fvSize)
|
||||
{
|
||||
return std::nullopt;
|
||||
@@ -139,7 +146,7 @@ std::optional<VersionHelper> get_installed_powertoys_version()
|
||||
|
||||
auto pbVersionInfo = std::make_unique<BYTE[]>(fvSize);
|
||||
|
||||
if (!GetFileVersionInfoW(installed_path->c_str(), 0, fvSize, pbVersionInfo.get()))
|
||||
if (!GetFileVersionInfoW(executable_path.c_str(), 0, fvSize, pbVersionInfo.get()))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -150,23 +157,62 @@ std::optional<VersionHelper> get_installed_powertoys_version()
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
return VersionHelper{ (fileInfo->dwFileVersionMS >> 16) & 0xffff,
|
||||
(fileInfo->dwFileVersionMS >> 0) & 0xffff,
|
||||
(fileInfo->dwFileVersionLS >> 16) & 0xffff };
|
||||
return InstalledVersionInfo{
|
||||
.version = VersionHelper{ (fileInfo->dwFileVersionMS >> 16) & 0xffff,
|
||||
(fileInfo->dwFileVersionMS >> 0) & 0xffff,
|
||||
(fileInfo->dwFileVersionLS >> 16) & 0xffff },
|
||||
.install_folder = std::move(*installed_path)
|
||||
};
|
||||
}
|
||||
|
||||
void ReLaunchElevatedAndExit()
|
||||
{
|
||||
std::wstring params;
|
||||
int nCmdArgs = 0;
|
||||
LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nCmdArgs);
|
||||
for (int i = 1; i < nCmdArgs; ++i)
|
||||
{
|
||||
if (std::wstring_view{ argList[i] }.find(L' ') != std::wstring_view::npos)
|
||||
{
|
||||
params += L'"';
|
||||
params += argList[i];
|
||||
params += L'"';
|
||||
}
|
||||
else
|
||||
{
|
||||
params += argList[i];
|
||||
}
|
||||
|
||||
if (i != nCmdArgs - 1)
|
||||
{
|
||||
params += L' ';
|
||||
}
|
||||
}
|
||||
|
||||
const auto processHandle = run_elevated(argList[0], params.c_str());
|
||||
if (!processHandle)
|
||||
{
|
||||
spdlog::error("Couldn't restart elevated: ({})", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(processHandle, 3600000) == WAIT_OBJECT_0)
|
||||
{
|
||||
DWORD exitCode = 0;
|
||||
GetExitCodeProcess(processHandle, &exitCode);
|
||||
std::exit(exitCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::error("Elevated setup process timed out after 60m: ({})", GetLastError());
|
||||
TerminateProcess(processHandle, 0);
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int Bootstrapper(HINSTANCE hInstance)
|
||||
{
|
||||
winrt::init_apartment();
|
||||
char* programFilesDir = nullptr;
|
||||
size_t size = 0;
|
||||
std::string defaultInstallDir;
|
||||
|
||||
if (!_dupenv_s(&programFilesDir, &size, "PROGRAMFILES"))
|
||||
{
|
||||
defaultInstallDir += programFilesDir;
|
||||
defaultInstallDir += "\\PowerToys";
|
||||
}
|
||||
|
||||
fs::path logDir = PTSettingsHelper::get_root_save_folder_location();
|
||||
|
||||
@@ -182,7 +228,7 @@ int Bootstrapper(HINSTANCE hInstance)
|
||||
("skip_dotnet_install", "Skip dotnet 3.X installation even if it's not detected")
|
||||
("log_level", "Log level. Possible values: off|debug|error", cxxopts::value<std::string>()->default_value("off"))
|
||||
("log_dir", "Log directory", cxxopts::value<std::string>()->default_value(logDir.string()))
|
||||
("install_dir", "Installation directory", cxxopts::value<std::string>()->default_value(defaultInstallDir))
|
||||
("install_dir", "Installation directory", cxxopts::value<std::string>()->default_value(""))
|
||||
("extract_msi", "Extract MSI to the working directory and exit. Use only if you must access MSI directly.");
|
||||
// clang-format on
|
||||
|
||||
@@ -231,7 +277,7 @@ int Bootstrapper(HINSTANCE hInstance)
|
||||
|
||||
installFolderProp = std::wstring(installDir.length(), L' ');
|
||||
std::copy(installDir.begin(), installDir.end(), installFolderProp.begin());
|
||||
installFolderProp = L"INSTALLFOLDER=" + installFolderProp;
|
||||
installFolderProp = L"INSTALLFOLDER=\"" + installFolderProp + L"\"";
|
||||
}
|
||||
|
||||
try
|
||||
@@ -281,15 +327,31 @@ int Bootstrapper(HINSTANCE hInstance)
|
||||
}
|
||||
|
||||
// Check if there's a newer version installed
|
||||
const auto installedVersion = get_installed_powertoys_version();
|
||||
if (installedVersion && *installedVersion >= myVersion)
|
||||
const auto installedVersionInfo = get_installed_powertoys_version();
|
||||
if (installedVersionInfo)
|
||||
{
|
||||
spdlog::error(L"Detected a newer version {} vs {}", (*installedVersion).toWstring(), myVersion.toWstring());
|
||||
ShowMessageBoxError(IDS_NEWER_VERSION_ERROR);
|
||||
return 0;
|
||||
if (installedVersionInfo->version >= myVersion)
|
||||
{
|
||||
spdlog::error(L"Detected a newer version {} vs {}", installedVersionInfo->version.toWstring(), myVersion.toWstring());
|
||||
ShowMessageBoxError(IDS_NEWER_VERSION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
// If we are good to go and install folder wasn't specified via cmd line, make sure to retain the previous
|
||||
// installation path
|
||||
else if (installFolderProp.empty())
|
||||
{
|
||||
installFolderProp = L"INSTALLFOLDER=\"" + installedVersionInfo->install_folder + L"\"";
|
||||
}
|
||||
}
|
||||
|
||||
// Setup MSI UI visibility and restart as elevated if required
|
||||
// Always elevate bootstrapper process since it invokes msiexec multiple times,
|
||||
// so we can avoid multiple UAC confirmations
|
||||
if (!is_process_elevated())
|
||||
{
|
||||
ReLaunchElevatedAndExit();
|
||||
}
|
||||
|
||||
// Setup MSI UI visibility
|
||||
if (!noFullUI)
|
||||
{
|
||||
MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr);
|
||||
@@ -297,58 +359,7 @@ int Bootstrapper(HINSTANCE hInstance)
|
||||
|
||||
if (g_Silent)
|
||||
{
|
||||
if (is_process_elevated())
|
||||
{
|
||||
MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::debug("MSI doesn't support silent mode without elevation => restarting elevated");
|
||||
// MSI fails to run in silent mode due to a suppressed UAC w/o elevation,
|
||||
// so we restart ourselves elevated with the same args
|
||||
std::wstring params;
|
||||
int nCmdArgs = 0;
|
||||
LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nCmdArgs);
|
||||
for (int i = 1; i < nCmdArgs; ++i)
|
||||
{
|
||||
if (std::wstring_view{ argList[i] }.find(L' ') != std::wstring_view::npos)
|
||||
{
|
||||
params += L'"';
|
||||
params += argList[i];
|
||||
params += L'"';
|
||||
}
|
||||
else
|
||||
{
|
||||
params += argList[i];
|
||||
}
|
||||
|
||||
if (i != nCmdArgs - 1)
|
||||
{
|
||||
params += L' ';
|
||||
}
|
||||
}
|
||||
|
||||
const auto processHandle = run_elevated(argList[0], params.c_str());
|
||||
if (!processHandle)
|
||||
{
|
||||
spdlog::error("Couldn't restart elevated to enable silent mode! ({})", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(processHandle, 3600000) == WAIT_OBJECT_0)
|
||||
{
|
||||
DWORD exitCode = 0;
|
||||
GetExitCodeProcess(processHandle, &exitCode);
|
||||
return exitCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
spdlog::error("Elevated setup process timed out after 60m => using basic MSI UI ({})", GetLastError());
|
||||
// Couldn't install using the completely silent mode in an hour, use basic UI.
|
||||
TerminateProcess(processHandle, 0);
|
||||
MsiSetInternalUI(INSTALLUILEVEL_BASIC, nullptr);
|
||||
}
|
||||
}
|
||||
MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr);
|
||||
}
|
||||
|
||||
// Try killing PowerToys and prevent future processes launch by acquiring app mutex
|
||||
@@ -392,7 +403,7 @@ int Bootstrapper(HINSTANCE hInstance)
|
||||
|
||||
if (!package_path.empty() && !uninstall_msi_version(package_path))
|
||||
{
|
||||
spdlog::error("Couldn't install the existing MSI package ({})", GetLastError());
|
||||
spdlog::error("Couldn't uninstall the existing MSI package ({})", GetLastError());
|
||||
ShowMessageBoxError(IDS_UNINSTALL_PREVIOUS_VERSION_ERROR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -119,18 +119,15 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="progressbar_window.cpp" />
|
||||
<ClCompile Include="RcResource.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="DotnetInstallation.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="progressbar_window.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="bootstrapper.base.rc" />
|
||||
<None Include="packages.config" />
|
||||
<ResourceCompile Include="Generated Files/bootstrapper.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -149,12 +146,12 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.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.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200902.2" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -10,6 +10,7 @@
|
||||
<?define ColorPickerProjectName="ColorPicker"?>
|
||||
<?define VideoConferenceProjectName="VideoConference"?>
|
||||
<?define AwakeProjectName="Awake"?>
|
||||
<?define MouseUtilsProjectName="MouseUtils"?>
|
||||
|
||||
<?define RepoDir="$(var.ProjectDir)..\..\" ?>
|
||||
<?define BinX32Dir="$(var.RepoDir)x86\$(var.Configuration)\" ?>
|
||||
@@ -77,30 +78,39 @@
|
||||
<Property Id="CREATESCHEDULEDTASK" Value="1"/>
|
||||
<Property Id="WixShellExecTarget" Value="[#PowerToys_ActionRunner.exe]" />
|
||||
|
||||
<Property Id ="EXISTINGPOWERRENAMEEXTPATH">
|
||||
<RegistrySearch Id="ExistingExtPath" Root="HKCR" Key="CLSID\{0440049F-D1DC-4E46-B27B-98393D79486B}\InprocServer32" Type="raw"/>
|
||||
</Property>
|
||||
<Property Id ="EXISTINGIMAGERESIZERPATH">
|
||||
<RegistrySearch Id="ExistingImageResizerPath" Root="HKCR" Key="CLSID\{51B4D7E5-7568-4234-B4BB-47FB3C016A69}\InprocServer32" Type="raw"/>
|
||||
</Property>
|
||||
|
||||
<InstallUISequence>
|
||||
<Custom Action="DetectPrevInstallPath" After="CostFinalize" />
|
||||
</InstallUISequence>
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="SetRegisterPowerToysSchTaskParam" Before="RegisterPowerToysSchTask" />
|
||||
<Custom Action="SetApplyModulesRegistryChangeSetsParam" Before="ApplyModulesRegistryChangeSets" />
|
||||
<Custom Action="SetUnApplyModulesRegistryChangeSetsParam" Before="UnApplyModulesRegistryChangeSets" />
|
||||
<Custom Action="RegisterPowerToysSchTask" After="InstallFiles">
|
||||
NOT Installed and CREATESCHEDULEDTASK = 1
|
||||
</Custom>
|
||||
<Custom Action="ApplyModulesRegistryChangeSets" After="InstallFiles">
|
||||
NOT Installed
|
||||
</Custom>
|
||||
<Custom Action="WixCloseApplications" Before="RemoveFiles" />
|
||||
<Custom Action="RemovePowerToysSchTasks" After="RemoveFiles" />
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
<!--<Custom Action="InstallEmbeddedMSIXTask" After="InstallFinalize">
|
||||
NOT Installed
|
||||
</Custom>-->
|
||||
<Custom Action="TelemetryLogInstallSuccess" After="InstallFinalize">
|
||||
NOT Installed
|
||||
</Custom>
|
||||
<Custom Action="TelemetryLogUninstallSuccess" After="InstallFinalize">
|
||||
Installed and (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<Custom Action="UnApplyModulesRegistryChangeSets" Before="InstallFinalize">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
<!--<Custom Action="UninstallEmbeddedMSIXTask" After="InstallFinalize">
|
||||
Installed AND (REMOVE="ALL")
|
||||
</Custom>-->
|
||||
<Custom Action="TerminateProcesses" Before="InstallValidate" />
|
||||
|
||||
</InstallExecuteSequence>
|
||||
@@ -116,7 +126,15 @@
|
||||
Property="RegisterPowerToysSchTask"
|
||||
Value="[#PowerToys.exe]" />
|
||||
|
||||
<!-- Needs to Impersonate="no" and Execute="deferred" in order to run elevated. -->
|
||||
<CustomAction Id="SetApplyModulesRegistryChangeSetsParam"
|
||||
Property="ApplyModulesRegistryChangeSets"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<CustomAction Id="SetUnApplyModulesRegistryChangeSetsParam"
|
||||
Property="UnApplyModulesRegistryChangeSets"
|
||||
Value="[INSTALLFOLDER]" />
|
||||
|
||||
<!-- Needs to Impersonate="no" and Execute="deferred" in order to run elevated. -->
|
||||
<CustomAction Id="RegisterPowerToysSchTask"
|
||||
Return="ignore"
|
||||
Impersonate="no"
|
||||
@@ -133,7 +151,21 @@
|
||||
DllEntry="RemoveScheduledTasksCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="TelemetryLogInstallSuccess"
|
||||
<CustomAction Id="InstallEmbeddedMSIXTask"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="InstallEmbeddedMSIXCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="UninstallEmbeddedMSIXTask"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="UninstallEmbeddedMSIXCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="TelemetryLogInstallSuccess"
|
||||
Return="ignore"
|
||||
Impersonate="yes"
|
||||
BinaryKey="PTCustomActions"
|
||||
@@ -196,6 +228,23 @@
|
||||
DllEntry="DetectPrevInstallPathCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="ApplyModulesRegistryChangeSets"
|
||||
Return="check"
|
||||
Impersonate="no"
|
||||
Execute="deferred"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="ApplyModulesRegistryChangeSetsCA"
|
||||
/>
|
||||
|
||||
<CustomAction Id="UnApplyModulesRegistryChangeSets"
|
||||
Return="check"
|
||||
Impersonate="no"
|
||||
Execute="deferred"
|
||||
BinaryKey="PTCustomActions"
|
||||
DllEntry="UnApplyModulesRegistryChangeSetsCA"
|
||||
/>
|
||||
|
||||
|
||||
<!-- Close 'PowerToys.exe' before uninstall-->
|
||||
<Property Id="MSIRESTARTMANAGERCONTROL" Value="DisableShutdown" />
|
||||
<Property Id="MSIFASTINSTALL" Value="DisableShutdown" />
|
||||
@@ -214,14 +263,15 @@
|
||||
<Directory Id="ToolsFolder" Name="Tools"/>
|
||||
<Directory Id="ModulesInstallFolder" Name="modules">
|
||||
<Directory Id="ImageResizerInstallFolder" Name="$(var.ImageResizerProjectName)" />
|
||||
<Directory Id="PowerRenameInstallFolder" Name="$(var.PowerRenameProjectName)"/>
|
||||
<Directory Id="PowerRenameInstallFolder" Name="$(var.PowerRenameProjectName)">
|
||||
<Directory Id="PowerRenameAssetsFolder" Name="Assets" />
|
||||
</Directory>
|
||||
<Directory Id="ShortcutGuideInstallFolder" Name="ShortcutGuide">
|
||||
<Directory Id="ShortcutGuideExecutableInstallFolder" Name="ShortcutGuide">
|
||||
<Directory Id="ShortcutGuideSvgsInstallFolder" Name="svgs"/>
|
||||
</Directory>
|
||||
<Directory Id="ShortcutGuideModuleInterfaceInstallFolder" Name="ShortcutGuideModuleInterface"/>
|
||||
</Directory>
|
||||
<!-- TODO(yuyoyuppe): uncomment when VCM should be enabled -->
|
||||
<Directory Id="VideoConferenceInstallFolder" Name="$(var.VideoConferenceProjectName)">
|
||||
<Directory Id="VideoConferenceIconsFolder" Name="Icons" />
|
||||
</Directory>
|
||||
@@ -239,7 +289,6 @@
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
|
||||
<!-- KBM -->
|
||||
<Directory Id="KeyboardManagerInstallFolder" Name="$(var.KeyboardManagerProjectName)">
|
||||
<Directory Id="KeyboardManagerEditorInstallFolder" Name="KeyboardManagerEditor" />
|
||||
@@ -251,6 +300,10 @@
|
||||
<Directory Id="ColorPickerResourcesFolder" Name="Resources"/>
|
||||
</Directory>
|
||||
|
||||
<!-- Mouse Utils -->
|
||||
<Directory Id="MouseUtilsInstallFolder" Name="$(var.MouseUtilsProjectName)">
|
||||
</Directory>
|
||||
|
||||
<!-- Launcher -->
|
||||
<Directory Id="LauncherInstallFolder" Name="launcher">
|
||||
<Directory Id="AssetsFolder" Name="Assets" />
|
||||
@@ -302,6 +355,9 @@
|
||||
<Directory Id="ServicePluginFolder" Name="Service">
|
||||
<Directory Id="ServiceImagesFolder" Name="Images" />
|
||||
</Directory>
|
||||
<Directory Id="WindowsTerminalPluginFolder" Name="WindowsTerminal">
|
||||
<Directory Id="WindowsTerminalImagesFolder" Name="Images" />
|
||||
</Directory>
|
||||
<Directory Id="SystemPluginFolder" Name="System">
|
||||
<Directory Id="SystemImagesFolder" Name="Images" />
|
||||
</Directory>
|
||||
@@ -458,71 +514,7 @@
|
||||
|
||||
<DirectoryRef Id="ModulesInstallFolder" FileSource="$(var.BinX64Dir)modules\">
|
||||
|
||||
<Component Id="Module_PowerPreview_PerUserRegistry" Guid="CD90ADC0-7CD5-4A62-B0AF-23545C1E6DD3" Win64="yes">
|
||||
<!-- Added a separate component for Per-User registry changes -->
|
||||
<!-- Registry Key for Class Registration of Svg Preview Handler -->
|
||||
<RegistryKey Root="HKCR" Key="CLSID\{ddee2b8a-6807-48a6-bb20-2338174ff779}">
|
||||
<RegistryValue Type="string" Value="Microsoft.PowerToys.PreviewHandler.Svg.SvgPreviewHandler" />
|
||||
<RegistryValue Type="string" Name="DisplayName" Value="Svg Preview Handler" />
|
||||
<RegistryValue Type="string" Name="AppID" Value="{CF142243-F059-45AF-8842-DBBE9783DB14}" />
|
||||
<RegistryValue Type="string" Key="Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value=""/>
|
||||
<RegistryValue Type="string" Key="InprocServer32" Value="[FileExplorerPreviewInstallFolder]SvgPreviewHandler.comhost.dll" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Assembly" Value="SvgPreviewHandler, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Class" Value="Microsoft.PowerToys.PreviewHandler.Svg.SvgPreviewHandler" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="ThreadingModel" Value="Both" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Assembly" Value="SvgPreviewHandler, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Class" Value="Microsoft.PowerToys.PreviewHandler.Svg.SvgPreviewHandler" />
|
||||
</RegistryKey>
|
||||
<!-- Registry Key for Class Registration of Svg Thumbnail Provider -->
|
||||
<RegistryKey Root="HKCR" Key="CLSID\{36B27788-A8BB-4698-A756-DF9F11F64F84}">
|
||||
<RegistryValue Type="string" Value="Microsoft.PowerToys.ThumbnailHandler.Svg.SvgThumbnailProvider" />
|
||||
<RegistryValue Type="string" Name="DisplayName" Value="Svg Thumbnail Provider" />
|
||||
<RegistryValue Type="string" Name="AppID" Value="{CF142243-F059-45AF-8842-DBBE9783DB14}" />
|
||||
<RegistryValue Type="string" Key="Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value=""/>
|
||||
<RegistryValue Type="string" Key="InprocServer32" Value="[FileExplorerPreviewInstallFolder]SvgThumbnailProvider.comhost.dll" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Assembly" Value="SvgThumbnailProvider, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Class" Value="Microsoft.PowerToys.ThumbnailHandler.Svg.SvgThumbnailProvider" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="ThreadingModel" Value="Both" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Assembly" Value="SvgThumbnailProvider, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Class" Value="Microsoft.PowerToys.ThumbnailHandler.Svg.SvgThumbnailProvider" />
|
||||
</RegistryKey>
|
||||
<!-- Registry Key for Class Registration of Markdown Preview Handler -->
|
||||
<RegistryKey Root="HKCR" Key="CLSID\{45769bcc-e8fd-42d0-947e-02beef77a1f5}">
|
||||
<RegistryValue Type="string" Value="Microsoft.PowerToys.PreviewHandler.Markdown.MarkdownPreviewHandler" />
|
||||
<RegistryValue Type="string" Name="DisplayName" Value="Markdown Preview Handler" />
|
||||
<RegistryValue Type="string" Name="AppID" Value="{CF142243-F059-45AF-8842-DBBE9783DB14}" />
|
||||
<RegistryValue Type="string" Key="Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value="" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Value="[FileExplorerPreviewInstallFolder]MarkdownPreviewHandler.comhost.dll" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Assembly" Value="MarkdownPreviewHandler, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="Class" Value="Microsoft.PowerToys.PreviewHandler.Markdown.MarkdownPreviewHandler" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="ThreadingModel" Value="Both" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Assembly" Value="MarkdownPreviewHandler, Version=$(var.Version).0, Culture=neutral" />
|
||||
<RegistryValue Type="string" Key="InprocServer32\$(var.Version).0" Name="Class" Value="Microsoft.PowerToys.PreviewHandler.Markdown.MarkdownPreviewHandler" />
|
||||
</RegistryKey>
|
||||
<!-- Registry Key for AppID registration -->
|
||||
<RegistryKey Root="HKCR" Key="AppID\{CF142243-F059-45AF-8842-DBBE9783DB14}">
|
||||
<RegistryValue Type="expandable" Name="DllSurrogate" Value="%SystemRoot%\system32\prevhost.exe" />
|
||||
</RegistryKey>
|
||||
<!-- Add Svg preview handler to preview handlers list -->
|
||||
<RegistryKey Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\PreviewHandlers">
|
||||
<RegistryValue Type="string" Name="{ddee2b8a-6807-48a6-bb20-2338174ff779}" Value="Svg Preview Handler" />
|
||||
</RegistryKey>
|
||||
<!-- Add Markdown preview handler to preview handlers list -->
|
||||
<RegistryKey Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\PreviewHandlers">
|
||||
<RegistryValue Type="string" Name="{45769bcc-e8fd-42d0-947e-02beef77a1f5}" Value="Markdown Preview Handler" />
|
||||
</RegistryKey>
|
||||
<!-- Add file type association for Svg Preview Handler -->
|
||||
<RegistryKey Root="HKCR" Key=".svg\shellex">
|
||||
<RegistryValue Type="string" Key="{8895b1c6-b41f-4c1c-a562-0d564250836f}" Value="{ddee2b8a-6807-48a6-bb20-2338174ff779}" />
|
||||
</RegistryKey>
|
||||
<!-- Add file type association for Svg Thumbnail Provider -->
|
||||
<RegistryKey Root="HKCR" Key=".svg\shellex">
|
||||
<RegistryValue Type="string" Key="{E357FCCD-A995-4576-B01F-234630154E96}" Value="{36B27788-A8BB-4698-A756-DF9F11F64F84}" />
|
||||
</RegistryKey>
|
||||
<!-- Add file type association for Markdown Preview Handler -->
|
||||
<RegistryKey Root="HKCR" Key=".md\shellex">
|
||||
<RegistryValue Type="string" Key="{8895b1c6-b41f-4c1c-a562-0d564250836f}" Value="{45769bcc-e8fd-42d0-947e-02beef77a1f5}" />
|
||||
</RegistryKey>
|
||||
<Component Id="Module_PowerPreview_Registry" Guid="CD90ADC0-7CD5-4A62-B0AF-23545C1E6DD3" Win64="yes">
|
||||
<!-- Update Key to use IE11 for prevhost.exe -->
|
||||
<RegistryKey Root="HKLM" Key="Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION">
|
||||
<RegistryValue Type="integer" Name="prevhost.exe" Value="11000" />
|
||||
@@ -629,7 +621,15 @@
|
||||
<!-- PowerRename -->
|
||||
<DirectoryRef Id="PowerRenameInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)">
|
||||
<Component Id="Module_PowerRename" Guid="E4401D08-27FE-4F96-BA17-0C61FD79E684" Win64="yes">
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRenameExt.dll" KeyPath="yes" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Microsoft.Toolkit.Win32.UI.XamlHost.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Microsoft.UI.Xaml.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\msvcp140_app.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRenameUILib.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRename.exe" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\resources.pri" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\vcruntime140_1_app.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\vcruntime140_app.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRenameExt.dll" KeyPath="yes" />
|
||||
<RegistryKey Root="HKCR" Key="CLSID\{0440049F-D1DC-4E46-B27B-98393D79486B}">
|
||||
<RegistryValue Type="string" Value="PowerRename Shell Extension" />
|
||||
<RegistryValue Type="string" Name="ContextMenuOptIn" Value="" />
|
||||
@@ -642,6 +642,19 @@
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="PowerRenameAssetsFolder" FileSource="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)">
|
||||
<Component Id="Module_PowerRename_Assets" Guid="5976BEDF-64F5-4836-8674-EE7577C77508" Win64="yes">
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Assets\file.png" />
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Assets\folder.png" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<!-- MouseUtils -->
|
||||
<DirectoryRef Id="MouseUtilsInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)">
|
||||
<Component Id="Module_FindMyMouse" Guid="60D0E4AE-188F-4403-BF06-1465AACC1BC5" Win64="yes">
|
||||
<File Source="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)\FindMyMouse.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- Shortcut guide -->
|
||||
<DirectoryRef Id="ShortcutGuideModuleInterfaceInstallFolder" FileSource="$(var.ShortcutGuideModuleInterface)">
|
||||
<Component Id="Module_ShortcutGuideModuleInterface" Guid="CBD0AC09-91D3-428E-B2B3-05745ADF3473" Win64="yes">
|
||||
@@ -649,7 +662,6 @@
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- TODO(yuyoyuppe): uncomment when VCM should be enabled -->
|
||||
<DirectoryRef Id="VideoConferenceInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.VideoConferenceProjectName)\">
|
||||
<Component Id="Module_VideoConference" Guid="5996527a-40fc-432e-b3ac-abc0b4bd3887" Win64="yes">
|
||||
<Condition>WINDOWSBUILDNUMBER >= 18362</Condition>
|
||||
@@ -771,7 +783,7 @@
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\SvgPreviewHandler.comhost.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\SvgPreviewHandler.runtimeconfig.json" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\SvgPreviewHandler.deps.json" />
|
||||
<!-- File to include dll for Svg Preview Handler -->
|
||||
<!-- File to include dll for Svg Thumbnail Provider -->
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\SvgThumbnailProvider.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\SvgThumbnailProvider.comhost.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\SvgThumbnailProvider.runtimeconfig.json" />
|
||||
@@ -784,6 +796,16 @@
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\Markdig.Signed.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\HtmlAgilityPack.dll" />
|
||||
<File Id="FileExplorerPreview_System.IO.Abstractions.dll" Source="$(var.BinX64Dir)modules\FileExplorerPreview\System.IO.Abstractions.dll" />
|
||||
<!-- File to include dll for Pdf Preview Handler -->
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfPreviewHandler.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfPreviewHandler.comhost.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfPreviewHandler.runtimeconfig.json" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfPreviewHandler.deps.json" />
|
||||
<!-- File to include dll for Pdf Thumbnail Provider -->
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfThumbnailProvider.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfThumbnailProvider.comhost.dll" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfThumbnailProvider.runtimeconfig.json" />
|
||||
<File Source="$(var.BinX64Dir)modules\FileExplorerPreview\PdfThumbnailProvider.deps.json" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
@@ -834,29 +856,29 @@
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SettingsV2AssetsModulesInstallFolder" FileSource="$(var.BinX64Dir)Settings\Assets\Modules">
|
||||
<Component Id="SettingsV2AssetsModules" Guid="A0B961A9-77D0-4223-88A9-E3B41BD9C329" Win64="yes">
|
||||
<?foreach File in ColorPicker.png;FancyZones.png;Awake.png;ImageResizer.png;KBM.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ShortcutGuide.png;VideoConference.png?>
|
||||
<?foreach File in ColorPicker.png;FancyZones.png;Awake.png;ImageResizer.png;KBM.png;MouseUtils.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ShortcutGuide.png;VideoConference.png?>
|
||||
<File Id="SettingsV2AssetsModules_$(var.File)" Source="$(var.BinX64Dir)Settings\Assets\Modules\$(var.File)" />
|
||||
<?endforeach?>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SettingsV2OOBEAssetsModulesInstallFolder" FileSource="$(var.BinX64Dir)Settings\Assets\Modules\OOBE">
|
||||
<Component Id="SettingsV2OOBEAssetsModules" Guid="E2360A83-6694-4B33-B5F6-641A906359EE" Win64="yes">
|
||||
<?foreach File in ColorPicker.gif;Awake.png;FancyZones.gif;FileExplorer.png;ImageResizer.gif;KBM.gif;PowerRename.gif;Run.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png?>
|
||||
<?foreach File in ColorPicker.gif;Awake.png;FancyZones.gif;FileExplorer.png;ImageResizer.gif;KBM.gif;MouseUtils.gif;PowerRename.gif;Run.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png?>
|
||||
<File Id="SettingsV2OOBEAssetsModules_$(var.File)" Source="$(var.BinX64Dir)Settings\Assets\Modules\OOBE\$(var.File)" />
|
||||
<?endforeach?>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SettingsV2OOBEAssetsFluentIconsInstallFolder" FileSource="$(var.BinX64Dir)Settings\Assets\FluentIcons">
|
||||
<Component Id="SettingsV2OOBEAssetsFluentIcons" Guid="6A380D5A-DA63-45B5-B68F-06D57CDD1B9C" Win64="yes">
|
||||
<?foreach File in ColorPicker.png;FancyZones.png;Awake.png;FileExplorerPreview.png;ImageResizer.png;KeyboardManager.png;PowerRename.png;PowerToys.png;PowerToysRun.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png ?>
|
||||
<?foreach File in ColorPicker.png;FancyZones.png;Awake.png;FileExplorerPreview.png;ImageResizer.png;KeyboardManager.png;MouseUtils.png;PowerRename.png;PowerToys.png;PowerToysRun.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png ?>
|
||||
<File Id="SettingsV2OOBEAssetsFluentIcons_$(var.File)" Source="$(var.BinX64Dir)Settings\Assets\FluentIcons\FluentIcons$(var.File)" />
|
||||
<?endforeach?>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SettingsV2ControlsInstallFolder" FileSource="$(var.BinX64Dir)Settings\Controls">
|
||||
<DirectoryRef Id="SettingsV2ControlsInstallFolder" FileSource="$(var.BinX64Dir)Settings\Controls\ShortcutControl">
|
||||
<Component Id="SettingsV2Controls" Guid="05C55C88-B59A-4450-A07C-EB7626E0781A" Win64="yes">
|
||||
<?foreach File in HotkeySettingsControl.xbf?>
|
||||
<File Id="SettingsV2_Controls_$(var.File)" Source="$(var.BinX64Dir)Settings\Controls\$(var.File)" />
|
||||
<?foreach File in ShortcutControl.xbf?>
|
||||
<File Id="SettingsV2_Controls_$(var.File)" Source="$(var.BinX64Dir)Settings\Controls\ShortcutControl\$(var.File)" />
|
||||
<?endforeach?>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
@@ -925,16 +947,16 @@
|
||||
<ComponentRef Id="ShortcutGuideSvgs" />
|
||||
<ComponentRef Id="Module_ShortcutGuideModuleInterface" />
|
||||
<ComponentRef Id="Module_ShortcutGuideExecutable" />
|
||||
<!-- TODO(yuyoyuppe): uncomment when VCM should be enabled -->
|
||||
<ComponentRef Id="Module_VideoConference" />
|
||||
<ComponentRef Id="Module_VideoConference" />
|
||||
<ComponentRef Id="Module_VideoConferenceIcons" />
|
||||
<ComponentRef Id="Module_FancyZones" />
|
||||
<ComponentRef Id="DesktopShortcut" />
|
||||
<ComponentRef Id="Module_PowerRename" />
|
||||
<ComponentRef Id="Module_PowerRename_Assets" />
|
||||
<ComponentRef Id="Module_ImageResizer" />
|
||||
<ComponentRef Id="Module_ImageResizer_Registry" />
|
||||
<ComponentRef Id="Module_PowerPreview" />
|
||||
<ComponentRef Id="Module_PowerPreview_PerUserRegistry" />
|
||||
<ComponentRef Id="Module_PowerPreview_Registry" />
|
||||
<ComponentRef Id="Module_KeyboardManager" />
|
||||
<ComponentRef Id="Module_KeyboardManager_Editor" />
|
||||
<ComponentRef Id="Module_KeyboardManager_Engine" />
|
||||
@@ -944,6 +966,7 @@
|
||||
<ComponentRef Id="Module_Awake_runtime_netstandard20"/>
|
||||
<ComponentRef Id="Module_Awake_runtime_netcoreapp30"/>
|
||||
<ComponentRef Id="Module_Awake_runtime_netcoreapp21"/>
|
||||
<ComponentRef Id="Module_FindMyMouse"/>
|
||||
<ComponentRef Id="SettingsV2" />
|
||||
<ComponentRef Id="SettingsV2Assets" />
|
||||
<ComponentRef Id="SettingsV2AssetsModules" />
|
||||
@@ -967,7 +990,7 @@
|
||||
<Fragment>
|
||||
<!-- Resource directories should be added only if the installer is built on the build farm -->
|
||||
<?ifdef env.IsPipeline?>
|
||||
<?foreach ParentDirectory in LauncherInstallFolder;FancyZonesInstallFolder;ImageResizerInstallFolder;ColorPickerInstallFolder;FileExplorerPreviewInstallFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;WindowsSettingsPluginFolder?>
|
||||
<?foreach ParentDirectory in LauncherInstallFolder;FancyZonesInstallFolder;ImageResizerInstallFolder;ColorPickerInstallFolder;FileExplorerPreviewInstallFolder;CalculatorPluginFolder;FolderPluginFolder;ProgramPluginFolder;ShellPluginFolder;IndexerPluginFolder;UnitConverterPluginFolder;UriPluginFolder;WindowWalkerPluginFolder;RegistryPluginFolder;VSCodeWorkspacesPluginFolder;ServicePluginFolder;SystemPluginFolder;WindowsSettingsPluginFolder;WindowsTerminalPluginFolder?>
|
||||
<DirectoryRef Id="$(var.ParentDirectory)">
|
||||
<!-- Resource file directories -->
|
||||
<?foreach Language in $(var.LocLanguageList)?>
|
||||
@@ -1022,7 +1045,10 @@
|
||||
<File Id="MarkdownPreviewHandler_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\FileExplorerPreview\$(var.Language)\MarkdownPreviewHandler.resources.dll" />
|
||||
</Component>
|
||||
<Component Id="SVGPreviewHandler_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)FileExplorerPreviewInstallFolder">
|
||||
<File Id="SVGPreviewHandler_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\FileExplorerPreview\$(var.Language)\SvgPreviewHandler.resources.dll" />
|
||||
<File Id="SVGPreviewHandler_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\FileExplorerPreview\$(var.Language)\SvgPreviewHandler.resources.dll" />
|
||||
</Component>
|
||||
<Component Id="PDFPreviewHandler_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)FileExplorerPreviewInstallFolder">
|
||||
<File Id="PDFPreviewHandler_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\FileExplorerPreview\$(var.Language)\PdfPreviewHandler.resources.dll" />
|
||||
</Component>
|
||||
<!-- PowerToys Run aka Launcher plugin resources -->
|
||||
<Component Id="Launcher_Calculator_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)CalculatorPluginFolder">
|
||||
@@ -1058,9 +1084,14 @@
|
||||
<Component Id="Launcher_System_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)SystemPluginFolder">
|
||||
<File Id="Launcher_System_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\System\$(var.Language)\Microsoft.PowerToys.Run.Plugin.System.resources.dll" />
|
||||
</Component>
|
||||
<!--<Component Id="Launcher_WindowsSettings_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WindowsSettingsPluginFolder">
|
||||
<Component Id="Launcher_WindowsSettings_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WindowsSettingsPluginFolder">
|
||||
<File Id="Launcher_WindowsSettings_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\$(var.Language)\Microsoft.PowerToys.Run.Plugin.WindowsSettings.resources.dll" />
|
||||
</Component>-->
|
||||
</Component>
|
||||
<!-- Uncomment after Plugin receives the localization files.
|
||||
<Component Id="Launcher_WindowsTerminal_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WindowsTerminalFolder">
|
||||
<File Id="Launcher_WindowsTerminal_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsTerminal\$(var.Language)\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.resources.dll" />
|
||||
</Component>
|
||||
-->
|
||||
<?undef IdSafeLanguage?>
|
||||
<?endforeach?>
|
||||
<?endif?>
|
||||
@@ -1254,6 +1285,17 @@
|
||||
<File Id="WindowsSettingsLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Images\WindowsSettings.light.png" />
|
||||
</Component>
|
||||
|
||||
<!-- WindowsTerminal Plugin -->
|
||||
<Component Id="WindowsTerminalComponent" Directory="WindowsTerminalPluginFolder" Guid="5392FD11-9A69-4409-A711-748C225F1A18">
|
||||
<?foreach File in plugin.json;Microsoft.PowerToys.Run.Plugin.WindowsTerminal.deps.json;Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll;ManagedTelemetry.dll?>
|
||||
<File Id="WindowsTerminal_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsTerminal\$(var.File)" />
|
||||
<?endforeach?>
|
||||
</Component>
|
||||
<Component Id="WindowsTerminalImagesComponent" Directory="WindowsTerminalImagesFolder" Guid="CDD21BEB-E2F3-4138-A1F8-72FD3B52706A">
|
||||
<File Id="WindowsTerminalDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsTerminal\Images\WindowsTerminal.dark.png" />
|
||||
<File Id="WindowsTerminalLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsTerminal\Images\WindowsTerminal.light.png" />
|
||||
</Component>
|
||||
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "resource.h"
|
||||
#include <ProjectTelemetry.h>
|
||||
|
||||
#include "../../src/common/utils/MsiUtils.h"
|
||||
#include "../../src/common/utils/modulesRegistry.h"
|
||||
#include "../../src/common/updating/installer.h"
|
||||
#include "../../src/common/version/version.h"
|
||||
|
||||
#include "../../installer/PowerToysBootstrapper/bootstrapper/RcResource.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
HINSTANCE DLL_HANDLE = nullptr;
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hProvider,
|
||||
"Microsoft.PowerToysInstaller",
|
||||
@@ -21,6 +26,141 @@ const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
|
||||
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
|
||||
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
||||
|
||||
HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
|
||||
{
|
||||
DWORD len = 0;
|
||||
wchar_t _[1];
|
||||
MsiGetPropertyW(hInstall, L"CustomActionData", _, &len);
|
||||
len += 1;
|
||||
installationDir.resize(len);
|
||||
HRESULT hr = MsiGetPropertyW(hInstall, L"CustomActionData", installationDir.data(), &len);
|
||||
if(installationDir.length())
|
||||
{
|
||||
installationDir.resize(installationDir.length() - 1);
|
||||
}
|
||||
ExitOnFailure(hr, "Failed to get INSTALLFOLDER property.");
|
||||
LExit:
|
||||
return hr;
|
||||
}
|
||||
UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder;
|
||||
|
||||
hr = WcaInitialize(hInstall, "ApplyModulesRegistryChangeSets");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installFolder.");
|
||||
for (const auto& changeSet : getAllModulesChangeSets(installationFolder, false))
|
||||
{
|
||||
if (!changeSet.apply())
|
||||
{
|
||||
WcaLog(LOGMSG_STANDARD, "Couldn't apply registry changeSet");
|
||||
}
|
||||
}
|
||||
|
||||
ExitOnFailure(hr, "Failed to extract msix");
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
std::wstring installationFolder;
|
||||
|
||||
hr = WcaInitialize(hInstall, "UndoModulesRegistryChangeSets"); // original func name is too long
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
hr = getInstallFolder(hInstall, installationFolder);
|
||||
ExitOnFailure(hr, "Failed to get installFolder.");
|
||||
for (const auto& changeSet : getAllModulesChangeSets(installationFolder, false))
|
||||
{
|
||||
changeSet.unApply();
|
||||
}
|
||||
|
||||
ExitOnFailure(hr, "Failed to extract msix");
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall InstallEmbeddedMSIXCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
hr = WcaInitialize(hInstall, "InstallEmbeddedMSIXCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
if (auto msix = RcResource::create(IDR_BIN_MSIX_HELLO_PACKAGE, L"BIN", DLL_HANDLE))
|
||||
{
|
||||
WcaLog(LOGMSG_STANDARD, "Extracted MSIX");
|
||||
// TODO: Use to activate embedded MSIX
|
||||
const auto msix_path = std::filesystem::temp_directory_path() / "hello_package.msix";
|
||||
if (!msix->saveAsFile(msix_path))
|
||||
{
|
||||
ExitOnFailure(hr, "Failed to save msix");
|
||||
}
|
||||
WcaLog(LOGMSG_STANDARD, "Saved MSIX");
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
Uri msix_uri{ msix_path.wstring() };
|
||||
PackageManager pm;
|
||||
auto result = pm.AddPackageAsync(msix_uri, nullptr, DeploymentOptions::None).get();
|
||||
if (!result)
|
||||
{
|
||||
ExitOnFailure(hr, "Failed to AddPackage");
|
||||
}
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "MSIX[s] were installed!");
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitOnFailure(hr, "Failed to extract msix");
|
||||
}
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
UINT __stdcall UninstallEmbeddedMSIXCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
UINT er = ERROR_SUCCESS;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
// TODO: This must be replaced with the actual publisher and package name
|
||||
const wchar_t package_name[] = L"46b35c25-b593-48d5-aeb1-d3e9c3b796e9";
|
||||
const wchar_t publisher[] = L"CN=yuyoyuppe";
|
||||
PackageManager pm;
|
||||
|
||||
hr = WcaInitialize(hInstall, "UninstallEmbeddedMSIXCA");
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
for (const auto& p : pm.FindPackagesForUser({}, package_name, publisher))
|
||||
{
|
||||
auto result = pm.RemovePackageAsync(p.Id().FullName()).get();
|
||||
if (result)
|
||||
{
|
||||
WcaLog(LOGMSG_STANDARD, "MSIX was uninstalled!");
|
||||
}
|
||||
else
|
||||
{
|
||||
WcaLog(LOGMSG_STANDARD, "Couldn't uninstall MSIX!");
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
// Creates a Scheduled Task to run at logon for the current user.
|
||||
// The path of the executable to run should be passed as the CustomActionData (Value).
|
||||
// Based on the Task Scheduler Logon Trigger Example:
|
||||
@@ -42,12 +182,12 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
|
||||
ITaskSettings* pSettings = nullptr;
|
||||
ITriggerCollection* pTriggerCollection = nullptr;
|
||||
IRegisteredTask* pRegisteredTask = nullptr;
|
||||
IPrincipal * pPrincipal = nullptr;
|
||||
ITrigger * pTrigger = nullptr;
|
||||
ILogonTrigger * pLogonTrigger = nullptr;
|
||||
IAction * pAction = nullptr;
|
||||
IActionCollection * pActionCollection = nullptr;
|
||||
IExecAction * pExecAction = nullptr;
|
||||
IPrincipal* pPrincipal = nullptr;
|
||||
ITrigger* pTrigger = nullptr;
|
||||
ILogonTrigger* pLogonTrigger = nullptr;
|
||||
IAction* pAction = nullptr;
|
||||
IActionCollection* pActionCollection = nullptr;
|
||||
IExecAction* pExecAction = nullptr;
|
||||
|
||||
LPWSTR wszExecutablePath = nullptr;
|
||||
|
||||
@@ -190,7 +330,6 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
|
||||
pActionCollection->Release();
|
||||
ExitOnFailure(hr, "Cannot create the action: %x", hr);
|
||||
|
||||
|
||||
// QI for the executable task pointer.
|
||||
hr = pAction->QueryInterface(
|
||||
IID_IExecAction, (void**)&pExecAction);
|
||||
@@ -302,7 +441,7 @@ UINT __stdcall RemoveScheduledTasksCA(MSIHANDLE hInstall)
|
||||
ITaskService* pService = nullptr;
|
||||
ITaskFolder* pTaskFolder = nullptr;
|
||||
IRegisteredTaskCollection* pTaskCollection = nullptr;
|
||||
ITaskFolder * pRootFolder = nullptr;
|
||||
ITaskFolder* pRootFolder = nullptr;
|
||||
LONG numTasks = 0;
|
||||
|
||||
hr = WcaInitialize(hInstall, "RemoveScheduledTasksCA");
|
||||
@@ -589,9 +728,8 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
|
||||
MsiSetPropertyW(hInstall, L"INSTALLFOLDER", install_path->data());
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
catch (...)
|
||||
{
|
||||
|
||||
}
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
@@ -609,7 +747,7 @@ UINT __stdcall CertifyVirtualCameraDriverCA(MSIHANDLE hInstall)
|
||||
HCERTSTORE hCertStore = nullptr;
|
||||
HANDLE hfile = nullptr;
|
||||
DWORD size = INVALID_FILE_SIZE;
|
||||
char * pFileContent = nullptr;
|
||||
char* pFileContent = nullptr;
|
||||
|
||||
hr = WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA");
|
||||
ExitOnFailure(hr, "Failed to initialize", hr);
|
||||
@@ -648,11 +786,11 @@ UINT __stdcall CertifyVirtualCameraDriverCA(MSIHANDLE hInstall)
|
||||
}
|
||||
|
||||
if (!CertAddEncodedCertificateToStore(hCertStore,
|
||||
X509_ASN_ENCODING,
|
||||
(const BYTE*)pFileContent,
|
||||
size,
|
||||
CERT_STORE_ADD_ALWAYS,
|
||||
nullptr))
|
||||
X509_ASN_ENCODING,
|
||||
(const BYTE*)pFileContent,
|
||||
size,
|
||||
CERT_STORE_ADD_ALWAYS,
|
||||
nullptr))
|
||||
{
|
||||
hr = GetLastError();
|
||||
ExitOnFailure(hr, "Adding certificate failed", hr);
|
||||
@@ -678,13 +816,11 @@ LExit:
|
||||
MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord);
|
||||
}
|
||||
|
||||
|
||||
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(er);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
UINT __stdcall InstallVirtualCameraDriverCA(MSIHANDLE hInstall)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
@@ -793,7 +929,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
}
|
||||
wchar_t processName[MAX_PATH] = L"<unknown>";
|
||||
|
||||
HANDLE hProcess{OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, procID)};
|
||||
HANDLE hProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, procID) };
|
||||
if (!hProcess)
|
||||
{
|
||||
continue;
|
||||
@@ -819,7 +955,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
GetWindowThreadProcessId(hwnd, &windowProcID);
|
||||
if (windowProcID == targetProcID)
|
||||
{
|
||||
DWORD_PTR _ {};
|
||||
DWORD_PTR _{};
|
||||
SendMessageTimeoutA(hwnd, WM_CLOSE, 0, 0, SMTO_BLOCK, timeout, &_);
|
||||
}
|
||||
return TRUE;
|
||||
@@ -837,7 +973,6 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
return WcaFinalize(er);
|
||||
}
|
||||
|
||||
|
||||
// DllMain - Initialize and cleanup WiX custom action utils.
|
||||
extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID)
|
||||
{
|
||||
@@ -846,6 +981,7 @@ extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in L
|
||||
case DLL_PROCESS_ATTACH:
|
||||
WcaGlobalInitialize(hInst);
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
DLL_HANDLE = hInst;
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
LIBRARY "PowerToysSetupCustomActions"
|
||||
|
||||
EXPORTS
|
||||
ApplyModulesRegistryChangeSetsCA
|
||||
CreateScheduledTaskCA
|
||||
DetectPrevInstallPathCA
|
||||
RemoveScheduledTasksCA
|
||||
@@ -16,4 +17,7 @@ EXPORTS
|
||||
TerminateProcessesCA
|
||||
CertifyVirtualCameraDriverCA
|
||||
InstallVirtualCameraDriverCA
|
||||
InstallEmbeddedMSIXCA
|
||||
UnApplyModulesRegistryChangeSetsCA
|
||||
UninstallVirtualCameraDriverCA
|
||||
UninstallEmbeddedMSIXCA
|
||||
@@ -15,7 +15,7 @@
|
||||
<ProjectGuid>{32f3882b-f2d6-4586-b5ed-11e39e522bd3}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>PowerToysSetupCustomActions</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
@@ -53,10 +53,11 @@
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>inc;..\..\src\;telemetry;$(WIX)sdk\$(WixPlatformToolset)\inc;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/await /Zc:twoPhase- /Wv:18 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;..\..\$(PlatformShortName)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>Newdev.lib;Crypt32.lib;msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;ApplicationUpdate.lib;Notifications.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>WindowsApp.lib;Newdev.lib;Crypt32.lib;msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;ApplicationUpdate.lib;Notifications.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@@ -112,10 +113,15 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\PowerToysBootstrapper\bootstrapper\RcResource.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="Telemetry\ProjectTelemetry.h" />
|
||||
<ClInclude Include="Telemetry\TraceLoggingDefines.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Resource.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
@@ -124,4 +130,4 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\WiX.3.11.2\build\wix.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WiX.3.11.2\build\wix.props'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -12,6 +12,8 @@
|
||||
<ClInclude Include="Telemetry\TraceLoggingDefines.h">
|
||||
<Filter>Telemetry</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="..\PowerToysBootstrapper\bootstrapper\RcResource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CustomAction.def" />
|
||||
@@ -22,4 +24,7 @@
|
||||
<UniqueIdentifier>{6e73ce5d-e715-4e7e-b796-c5d180b07ff2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Resource.rc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
61
installer/PowerToysSetupCustomActions/Resource.rc
Normal file
@@ -0,0 +1,61 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
|
||||
LANGUAGE 25, 1
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: Use to activate embedded MSIX
|
||||
//IDR_BIN_MSIX_HELLO_PACKAGE BIN "..\\..\..\\src\\modules\\HelloModule\\AppPackages\\HelloModule_1.0.0.0_x64_Test\\HelloModule_1.0.0.0_x64.msix"
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
16
installer/PowerToysSetupCustomActions/resource.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Resource.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 102
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define IDR_BIN_MSIX_HELLO_PACKAGE 101
|
||||
@@ -27,3 +27,9 @@
|
||||
#include <psapi.h>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
#include <winrt/Windows.System.h>
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.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.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200902.2" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
||||
80
src/common/Microsoft.PowerToys.Common.UI/SettingsDeepLink.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.PowerToys.Common.UI
|
||||
{
|
||||
public static class SettingsDeepLink
|
||||
{
|
||||
public enum SettingsWindow
|
||||
{
|
||||
Overview = 0,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
FancyZones,
|
||||
Run,
|
||||
ImageResizer,
|
||||
KBM,
|
||||
MouseUtils,
|
||||
PowerRename,
|
||||
FileExplorer,
|
||||
ShortcutGuide,
|
||||
VideoConference,
|
||||
}
|
||||
|
||||
private static string SettingsWindowNameToString(SettingsWindow value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case SettingsWindow.Overview:
|
||||
return "Overview";
|
||||
case SettingsWindow.Awake:
|
||||
return "Awake";
|
||||
case SettingsWindow.ColorPicker:
|
||||
return "ColorPicker";
|
||||
case SettingsWindow.FancyZones:
|
||||
return "FancyZones";
|
||||
case SettingsWindow.Run:
|
||||
return "Run";
|
||||
case SettingsWindow.ImageResizer:
|
||||
return "ImageResizer";
|
||||
case SettingsWindow.KBM:
|
||||
return "KBM";
|
||||
case SettingsWindow.MouseUtils:
|
||||
return "MouseUtils";
|
||||
case SettingsWindow.PowerRename:
|
||||
return "PowerRename";
|
||||
case SettingsWindow.FileExplorer:
|
||||
return "FileExplorer";
|
||||
case SettingsWindow.ShortcutGuide:
|
||||
return "ShortcutGuide";
|
||||
case SettingsWindow.VideoConference:
|
||||
return "VideoConference";
|
||||
default:
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenSettings(SettingsWindow window)
|
||||
{
|
||||
try
|
||||
{
|
||||
var assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
||||
var fullPath = Directory.GetParent(assemblyPath).FullName;
|
||||
Process.Start(new ProcessStartInfo(fullPath + "\\..\\PowerToys.exe") { Arguments = "--open-settings=" + SettingsWindowNameToString(window) });
|
||||
}
|
||||
#pragma warning disable CA1031 // Do not catch general exception types
|
||||
catch
|
||||
#pragma warning restore CA1031 // Do not catch general exception types
|
||||
{
|
||||
// TODO(stefan): Log exception once unified logging is implemented
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,7 +313,7 @@ namespace PowerToysSettings
|
||||
return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type);
|
||||
}
|
||||
|
||||
std::optional<bool> PowerToyValues::get_bool_value(std::wstring_view property_name)
|
||||
std::optional<bool> PowerToyValues::get_bool_value(std::wstring_view property_name) const
|
||||
{
|
||||
if (!has_property(m_json, property_name, json::JsonValueType::Boolean))
|
||||
{
|
||||
@@ -322,7 +322,7 @@ namespace PowerToysSettings
|
||||
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value");
|
||||
}
|
||||
|
||||
std::optional<int> PowerToyValues::get_int_value(std::wstring_view property_name)
|
||||
std::optional<int> PowerToyValues::get_int_value(std::wstring_view property_name) const
|
||||
{
|
||||
if (!has_property(m_json, property_name, json::JsonValueType::Number))
|
||||
{
|
||||
@@ -331,7 +331,7 @@ namespace PowerToysSettings
|
||||
return static_cast<int>(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value"));
|
||||
}
|
||||
|
||||
std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name)
|
||||
std::optional<std::wstring> PowerToyValues::get_string_value(std::wstring_view property_name) const
|
||||
{
|
||||
if (!has_property(m_json, property_name, json::JsonValueType::String))
|
||||
{
|
||||
@@ -340,7 +340,7 @@ namespace PowerToysSettings
|
||||
return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str();
|
||||
}
|
||||
|
||||
std::optional<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name)
|
||||
std::optional<json::JsonObject> PowerToyValues::get_json(std::wstring_view property_name) const
|
||||
{
|
||||
if (!has_property(m_json, property_name, json::JsonValueType::Object))
|
||||
{
|
||||
|
||||
@@ -79,10 +79,10 @@ namespace PowerToysSettings
|
||||
m_json.GetNamedObject(L"properties").SetNamedValue(name, prop_value);
|
||||
}
|
||||
|
||||
std::optional<bool> get_bool_value(std::wstring_view property_name);
|
||||
std::optional<int> get_int_value(std::wstring_view property_name);
|
||||
std::optional<std::wstring> get_string_value(std::wstring_view property_name);
|
||||
std::optional<json::JsonObject> get_json(std::wstring_view property_name);
|
||||
std::optional<bool> get_bool_value(std::wstring_view property_name) const;
|
||||
std::optional<int> get_int_value(std::wstring_view property_name) const;
|
||||
std::optional<std::wstring> get_string_value(std::wstring_view property_name) const;
|
||||
std::optional<json::JsonObject> get_json(std::wstring_view property_name) const;
|
||||
json::JsonObject get_raw_json();
|
||||
|
||||
std::wstring serialize();
|
||||
|
||||
@@ -95,10 +95,10 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\MicrophoneDevice.cpp">
|
||||
<CompileAsManaged>false</CompileAsManaged>
|
||||
</ClCompile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.cpp">
|
||||
<CompileAsManaged>false</CompileAsManaged>
|
||||
</ClCompile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Generated Files\AssemblyInfo.cpp" />
|
||||
<ClCompile Include="HotkeyManager.cpp" />
|
||||
<ClCompile Include="interop.cpp" />
|
||||
@@ -121,10 +121,15 @@
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.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.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -32,8 +32,8 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\videoconference\VideoConferenceShared\VideoCaptureDeviceList.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shared_constants.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="shared_constants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
@@ -68,4 +68,7 @@
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -171,6 +171,10 @@ public
|
||||
return gcnew String(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ PowerLauncherCentralizedHookSharedEvent() {
|
||||
return gcnew String(CommonSharedConstants::POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT);
|
||||
}
|
||||
|
||||
static String ^ RunSendSettingsTelemetryEvent() {
|
||||
return gcnew String(CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200902.2" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -10,5 +10,6 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
// add headers that you want to pre-compile here
|
||||
#include <Windows.h>
|
||||
#include <Endpointvolume.h>
|
||||
|
||||
#endif //PCH_H
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace CommonSharedConstants
|
||||
// Path to the event used by PowerLauncher
|
||||
const wchar_t POWER_LAUNCHER_SHARED_EVENT[] = L"Local\\PowerToysRunInvokeEvent-30f26ad7-d36d-4c0e-ab02-68bb5ff3c4ab";
|
||||
|
||||
const wchar_t POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT[] = L"Local\\PowerToysRunCentralizedHookInvokeEvent-30f26ad7-d36d-4c0e-ab02-68bb5ff3c4ab";
|
||||
|
||||
const wchar_t RUN_SEND_SETTINGS_TELEMETRY_EVENT[] = L"Local\\PowerToysRunInvokeEvent-638ec522-0018-4b96-837d-6bd88e06f0d6";
|
||||
|
||||
const wchar_t RUN_EXIT_EVENT[] = L"Local\\PowerToysRunExitEvent-3e38e49d-a762-4ef1-88f2-fd4bc7481516";
|
||||
|
||||
@@ -23,6 +23,7 @@ struct LogSettings
|
||||
inline const static std::wstring shortcutGuideLogPath = L"ShortcutGuideLogs\\shortcut-guide-log.txt";
|
||||
inline const static std::string keyboardManagerLoggerName = "keyboard-manager";
|
||||
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt";
|
||||
inline const static std::string findMyMouseLoggerName = "find-my-mouse";
|
||||
inline const static int retention = 30;
|
||||
std::wstring logLevel;
|
||||
LogSettings();
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
@@ -50,6 +50,6 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200902.2" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.200902.2" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210204.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -27,7 +27,7 @@ namespace updating
|
||||
|
||||
std::future<std::optional<std::filesystem::path>> download_new_version(const new_version_download_info& new_version);
|
||||
std::filesystem::path get_pending_updates_path();
|
||||
std::future<nonstd::expected<github_version_info, std::wstring>> get_github_version_info_async(const bool prerelease = true);
|
||||
std::future<nonstd::expected<github_version_info, std::wstring>> get_github_version_info_async(const bool prerelease = false);
|
||||
|
||||
// non-localized
|
||||
constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN = L"powertoyssetup";
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
@@ -70,6 +70,6 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.200902.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210204.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -24,9 +24,6 @@
|
||||
<ClInclude Include="installer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="winstore.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="updateState.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
||||
58
src/common/utils/HDropIterator.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include <shellapi.h>
|
||||
|
||||
class HDropIterator
|
||||
{
|
||||
public:
|
||||
HDropIterator(IDataObject* pDataObject)
|
||||
{
|
||||
_current = 0;
|
||||
|
||||
FORMATETC formatetc = {
|
||||
CF_HDROP,
|
||||
NULL,
|
||||
DVASPECT_CONTENT,
|
||||
-1,
|
||||
TYMED_HGLOBAL
|
||||
};
|
||||
|
||||
pDataObject->GetData(&formatetc, &m_medium);
|
||||
|
||||
_listCount = DragQueryFile((HDROP)m_medium.hGlobal, 0xFFFFFFFF, NULL, 0);
|
||||
}
|
||||
|
||||
~HDropIterator()
|
||||
{
|
||||
ReleaseStgMedium(&m_medium);
|
||||
}
|
||||
|
||||
void First()
|
||||
{
|
||||
_current = 0;
|
||||
}
|
||||
|
||||
void Next()
|
||||
{
|
||||
_current++;
|
||||
}
|
||||
|
||||
bool IsDone() const
|
||||
{
|
||||
return _current >= _listCount;
|
||||
}
|
||||
|
||||
LPTSTR CurrentItem() const
|
||||
{
|
||||
UINT cch = DragQueryFile((HDROP)m_medium.hGlobal, _current, NULL, 0) + 1;
|
||||
LPTSTR pszPath = (LPTSTR)malloc(sizeof(TCHAR) * cch);
|
||||
|
||||
DragQueryFile((HDROP)m_medium.hGlobal, _current, pszPath, cch);
|
||||
|
||||
return pszPath;
|
||||
}
|
||||
|
||||
private:
|
||||
UINT _listCount;
|
||||
STGMEDIUM m_medium;
|
||||
UINT _current;
|
||||
};
|
||||
12
src/common/utils/game_mode.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <shellapi.h>
|
||||
|
||||
inline bool detect_game_mode()
|
||||
{
|
||||
QUERY_USER_NOTIFICATION_STATE notification_state;
|
||||
if (SHQueryUserNotificationState(¬ification_state) != S_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (notification_state == QUNS_RUNNING_D3D_FULL_SCREEN);
|
||||
}
|
||||
88
src/common/utils/modulesRegistry.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "registry.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
inline registry::ChangeSet getSvgPreviewHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
return generatePreviewHandler(PreviewHandlerType::preview,
|
||||
perUser,
|
||||
L"{ddee2b8a-6807-48a6-bb20-2338174ff779}",
|
||||
get_std_product_version(),
|
||||
(fs::path{ installationDir } /
|
||||
LR"d(modules\FileExplorerPreview\SvgPreviewHandler.comhost.dll)d")
|
||||
.wstring(),
|
||||
registry::DOTNET_COMPONENT_CATEGORY_CLSID,
|
||||
L"Microsoft.PowerToys.PreviewHandler.Svg.SvgPreviewHandler",
|
||||
L"Svg Preview Handler",
|
||||
L".svg");
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getMdPreviewHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
return generatePreviewHandler(PreviewHandlerType::preview,
|
||||
perUser,
|
||||
L"{45769bcc-e8fd-42d0-947e-02beef77a1f5}",
|
||||
get_std_product_version(),
|
||||
(fs::path{ installationDir } / LR"d(modules\FileExplorerPreview\MarkdownPreviewHandler.comhost.dll)d").wstring(),
|
||||
registry::DOTNET_COMPONENT_CATEGORY_CLSID,
|
||||
L"Microsoft.PowerToys.PreviewHandler.Markdown.MarkdownPreviewHandler",
|
||||
L"Markdown Preview Handler",
|
||||
L".md");
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getPdfPreviewHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
return generatePreviewHandler(PreviewHandlerType::preview,
|
||||
perUser,
|
||||
L"{07665729-6243-4746-95b7-79579308d1b2}",
|
||||
get_std_product_version(),
|
||||
(fs::path{ installationDir } / LR"d(modules\FileExplorerPreview\PdfPreviewHandler.comhost.dll)d").wstring(),
|
||||
registry::DOTNET_COMPONENT_CATEGORY_CLSID,
|
||||
L"Microsoft.PowerToys.PreviewHandler.Pdf.PdfPreviewHandler",
|
||||
L"Pdf Preview Handler",
|
||||
L".pdf");
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getSvgThumbnailHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
return generatePreviewHandler(PreviewHandlerType::thumbnail,
|
||||
perUser,
|
||||
L"{36B27788-A8BB-4698-A756-DF9F11F64F84}",
|
||||
get_std_product_version(),
|
||||
(fs::path{ installationDir } / LR"d(modules\FileExplorerPreview\SvgThumbnailProvider.comhost.dll)d").wstring(),
|
||||
registry::DOTNET_COMPONENT_CATEGORY_CLSID,
|
||||
L"Microsoft.PowerToys.ThumbnailHandler.Svg.SvgThumbnailProvider",
|
||||
L"Svg Thumbnail Provider",
|
||||
L".svg");
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getPdfThumbnailHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
return generatePreviewHandler(PreviewHandlerType::thumbnail,
|
||||
perUser,
|
||||
L"{BCC13D15-9720-4CC4-8371-EA74A274741E}",
|
||||
get_std_product_version(),
|
||||
(fs::path{ installationDir } / LR"d(modules\FileExplorerPreview\PdfThumbnailProvider.comhost.dll)d").wstring(),
|
||||
registry::DOTNET_COMPONENT_CATEGORY_CLSID,
|
||||
L"Microsoft.PowerToys.ThumbnailHandler.Pdf.PdfThumbnailProvider",
|
||||
L"Pdf Thumbnail Provider",
|
||||
L".pdf");
|
||||
}
|
||||
|
||||
inline std::vector<registry::ChangeSet> getAllModulesChangeSets(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
return { getSvgPreviewHandlerChangeSet(installationDir, perUser),
|
||||
getMdPreviewHandlerChangeSet(installationDir, perUser),
|
||||
getPdfPreviewHandlerChangeSet(installationDir, perUser),
|
||||
getSvgThumbnailHandlerChangeSet(installationDir, perUser),
|
||||
getPdfThumbnailHandlerChangeSet(installationDir, perUser) };
|
||||
}
|
||||
@@ -39,7 +39,6 @@ inline std::wstring get_process_path(HWND window) noexcept
|
||||
{
|
||||
// It is a UWP app. We will enumerate the windows and look for one created
|
||||
// by something with a different PID
|
||||
// It might take a time to connect the process. That's the reason for the retry loop here
|
||||
DWORD new_pid = pid;
|
||||
|
||||
EnumChildWindows(
|
||||
@@ -103,4 +102,4 @@ inline std::wstring get_module_folderpath(HMODULE mod = nullptr, const bool remo
|
||||
PathRemoveFileSpecW(buffer);
|
||||
}
|
||||
return { buffer, (UINT)lstrlenW(buffer) };
|
||||
}
|
||||
}
|
||||
|
||||
329
src/common/utils/registry.h
Normal file
@@ -0,0 +1,329 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <cassert>
|
||||
|
||||
#include "../version/version.h"
|
||||
|
||||
namespace registry
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct on_exit
|
||||
{
|
||||
std::function<void()> f;
|
||||
|
||||
on_exit(std::function<void()> f) :
|
||||
f{ std::move(f) } {}
|
||||
~on_exit() { f(); }
|
||||
};
|
||||
|
||||
template<class>
|
||||
inline constexpr bool always_false_v = false;
|
||||
|
||||
template<class... Ts>
|
||||
struct overloaded : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
template<class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
}
|
||||
struct ValueChange
|
||||
{
|
||||
using value_t = std::variant<DWORD, std::wstring>;
|
||||
static constexpr size_t VALUE_BUFFER_SIZE = 512;
|
||||
|
||||
HKEY scope{};
|
||||
std::wstring path;
|
||||
std::optional<std::wstring> name; // none == default
|
||||
value_t value;
|
||||
|
||||
ValueChange(const HKEY scope, std::wstring path, std::optional<std::wstring> name, value_t value) :
|
||||
scope{ scope }, path{ std::move(path) }, name{ std::move(name) }, value{ std::move(value) }
|
||||
{
|
||||
}
|
||||
|
||||
bool isApplied() const
|
||||
{
|
||||
HKEY key{};
|
||||
if (RegOpenKeyExW(scope, path.c_str(), 0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
detail::on_exit closeKey{ [key] { RegCloseKey(key); } };
|
||||
|
||||
const DWORD expectedType = valueTypeToWinapiType(value);
|
||||
|
||||
DWORD retrievedType{};
|
||||
wchar_t buffer[VALUE_BUFFER_SIZE];
|
||||
DWORD valueSize = sizeof(buffer);
|
||||
if (RegQueryValueExW(key,
|
||||
name.has_value() ? name->c_str() : nullptr,
|
||||
0,
|
||||
&retrievedType,
|
||||
reinterpret_cast<LPBYTE>(&buffer),
|
||||
&valueSize) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expectedType != retrievedType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const auto retrievedValue = bufferToValue(buffer, valueSize, retrievedType))
|
||||
{
|
||||
return value == retrievedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool apply() const
|
||||
{
|
||||
HKEY key{};
|
||||
|
||||
if (RegCreateKeyExW(scope, path.c_str(), 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &key, nullptr) !=
|
||||
ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
detail::on_exit closeKey{ [key] { RegCloseKey(key); } };
|
||||
|
||||
wchar_t buffer[VALUE_BUFFER_SIZE];
|
||||
DWORD valueSize;
|
||||
DWORD valueType;
|
||||
|
||||
valueToBuffer(value, buffer, valueSize, valueType);
|
||||
return RegSetValueExW(key,
|
||||
name.has_value() ? name->c_str() : nullptr,
|
||||
0,
|
||||
valueType,
|
||||
reinterpret_cast<BYTE*>(buffer),
|
||||
valueSize) == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
bool unApply() const
|
||||
{
|
||||
HKEY key{};
|
||||
if (RegOpenKeyExW(scope, path.c_str(), 0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
detail::on_exit closeKey{ [key] { RegCloseKey(key); } };
|
||||
|
||||
// delete the value itself
|
||||
if (RegDeleteKeyValueW(scope, path.c_str(), name.has_value() ? name->c_str() : nullptr) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the path doesn't contain anything and delete it if so
|
||||
DWORD nValues = 0;
|
||||
DWORD maxValueLen = 0;
|
||||
const auto ok =
|
||||
RegQueryInfoKeyW(
|
||||
key, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &nValues, nullptr, &maxValueLen, nullptr, nullptr) ==
|
||||
ERROR_SUCCESS;
|
||||
|
||||
if (ok && (!nValues || !maxValueLen))
|
||||
{
|
||||
RegDeleteTreeW(scope, path.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool requiresElevation() const { return scope == HKEY_LOCAL_MACHINE; }
|
||||
|
||||
private:
|
||||
static DWORD valueTypeToWinapiType(const value_t& v)
|
||||
{
|
||||
return std::visit(
|
||||
[](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, DWORD>)
|
||||
return REG_DWORD;
|
||||
else if constexpr (std::is_same_v<T, std::wstring>)
|
||||
return REG_SZ;
|
||||
else
|
||||
static_assert(always_false_v<T>, "support for this registry type is not implemented");
|
||||
},
|
||||
v);
|
||||
}
|
||||
|
||||
static void valueToBuffer(const value_t& value, wchar_t buffer[VALUE_BUFFER_SIZE], DWORD& valueSize, DWORD& type)
|
||||
{
|
||||
using detail::overloaded;
|
||||
|
||||
std::visit(overloaded{ [&](DWORD value) {
|
||||
*reinterpret_cast<DWORD*>(buffer) = value;
|
||||
type = REG_DWORD;
|
||||
valueSize = sizeof(value);
|
||||
},
|
||||
[&](const std::wstring& value) {
|
||||
assert(value.size() < VALUE_BUFFER_SIZE);
|
||||
value.copy(buffer, value.size());
|
||||
type = REG_SZ;
|
||||
valueSize = static_cast<DWORD>(sizeof(wchar_t) * value.size());
|
||||
} },
|
||||
value);
|
||||
}
|
||||
|
||||
static std::optional<value_t> bufferToValue(const wchar_t buffer[VALUE_BUFFER_SIZE],
|
||||
const DWORD valueSize,
|
||||
const DWORD type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case REG_DWORD:
|
||||
return *(DWORD*)buffer;
|
||||
case REG_SZ:
|
||||
{
|
||||
if (!valueSize)
|
||||
{
|
||||
return std::wstring{};
|
||||
}
|
||||
std::wstring result{ buffer, valueSize / sizeof(wchar_t) };
|
||||
while (result[result.size() - 1] == L'\0')
|
||||
{
|
||||
result.resize(result.size() - 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ChangeSet
|
||||
{
|
||||
std::vector<ValueChange> changes;
|
||||
|
||||
bool isApplied() const
|
||||
{
|
||||
for (const auto& c : changes)
|
||||
{
|
||||
if (!c.isApplied())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool apply() const
|
||||
{
|
||||
bool ok = true;
|
||||
for (const auto& c : changes)
|
||||
{
|
||||
ok = c.apply() && ok;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool unApply() const
|
||||
{
|
||||
bool ok = true;
|
||||
for (const auto& c : changes)
|
||||
{
|
||||
ok = c.unApply() && ok;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
};
|
||||
|
||||
const inline std::wstring DOTNET_COMPONENT_CATEGORY_CLSID = L"{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}";
|
||||
const inline std::wstring ITHUMBNAIL_PROVIDER_CLSID = L"{E357FCCD-A995-4576-B01F-234630154E96}";
|
||||
const inline std::wstring IPREVIEW_HANDLER_CLSID = L"{8895b1c6-b41f-4c1c-a562-0d564250836f}";
|
||||
|
||||
namespace shellex
|
||||
{
|
||||
enum PreviewHandlerType
|
||||
{
|
||||
preview,
|
||||
thumbnail
|
||||
};
|
||||
|
||||
inline registry::ChangeSet generatePreviewHandler(const PreviewHandlerType handlerType,
|
||||
const bool perUser,
|
||||
std::wstring handlerClsid,
|
||||
std::wstring powertoysVersion,
|
||||
std::wstring fullPathToHandler,
|
||||
std::wstring handlerCategory,
|
||||
std::wstring className,
|
||||
std::wstring displayName,
|
||||
std::wstring fileType)
|
||||
{
|
||||
const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
|
||||
|
||||
std::wstring clsidPath = L"Software\\Classes\\CLSID";
|
||||
clsidPath += L'\\';
|
||||
clsidPath += handlerClsid;
|
||||
|
||||
std::wstring inprocServerPath = clsidPath;
|
||||
inprocServerPath += L'\\';
|
||||
inprocServerPath += L"InprocServer32";
|
||||
|
||||
std::wstring implementedCategoriesPath = clsidPath + LR"d(\Implemented Categories\)d";
|
||||
implementedCategoriesPath += handlerCategory;
|
||||
|
||||
std::wstring assemblyKeyValue;
|
||||
if (const auto lastDotPos = className.rfind(L'.'); lastDotPos != std::wstring::npos)
|
||||
{
|
||||
assemblyKeyValue = className.substr(lastDotPos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
assemblyKeyValue = className;
|
||||
}
|
||||
|
||||
assemblyKeyValue += L", Version=";
|
||||
assemblyKeyValue += powertoysVersion;
|
||||
assemblyKeyValue += L", Culture=neutral";
|
||||
|
||||
std::wstring versionPath = inprocServerPath;
|
||||
versionPath += L'\\';
|
||||
versionPath += powertoysVersion;
|
||||
|
||||
std::wstring fileAssociationPath = L"Software\\Classes\\";
|
||||
fileAssociationPath += fileType;
|
||||
fileAssociationPath += L"\\shellex\\";
|
||||
fileAssociationPath += handlerType == PreviewHandlerType::preview ? IPREVIEW_HANDLER_CLSID : ITHUMBNAIL_PROVIDER_CLSID;
|
||||
|
||||
using vec_t = std::vector<registry::ValueChange>;
|
||||
// TODO: verify that we actually need all of those
|
||||
vec_t changes = { { scope, clsidPath, L"DisplayName", displayName },
|
||||
{ scope, clsidPath, std::nullopt, className },
|
||||
{ scope, implementedCategoriesPath, std::nullopt, L"" },
|
||||
{ scope, inprocServerPath, std::nullopt, fullPathToHandler },
|
||||
{ scope, inprocServerPath, L"Assembly", assemblyKeyValue },
|
||||
{ scope, inprocServerPath, L"Class", className },
|
||||
{ scope, inprocServerPath, L"ThreadingModel", L"Both" },
|
||||
{ scope, versionPath, L"Assembly", assemblyKeyValue },
|
||||
{ scope, versionPath, L"Class", className },
|
||||
{ scope, fileAssociationPath, std::nullopt, handlerClsid } };
|
||||
if (handlerType == PreviewHandlerType::preview)
|
||||
{
|
||||
const std::wstring previewHostClsid = L"{6d2b5079-2f0b-48dd-ab7f-97cec514d30b}";
|
||||
const std::wstring previewHandlerListPath = LR"(Software\Microsoft\Windows\CurrentVersion\PreviewHandlers)";
|
||||
|
||||
changes.push_back({ scope, clsidPath, L"AppID", previewHostClsid });
|
||||
changes.push_back({ scope, previewHandlerListPath, handlerClsid, displayName });
|
||||
}
|
||||
|
||||
return registry::ChangeSet{ .changes = std::move(changes) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,5 +33,14 @@ inline std::wstring get_product_version()
|
||||
L"." + std::to_wstring(VERSION_MINOR) +
|
||||
L"." + std::to_wstring(VERSION_REVISION);
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
inline std::wstring get_std_product_version()
|
||||
{
|
||||
static std::wstring version = L"v" + std::to_wstring(VERSION_MAJOR) +
|
||||
L"." + std::to_wstring(VERSION_MINOR) +
|
||||
L"." + std::to_wstring(VERSION_REVISION) + L".0";
|
||||
|
||||
return version;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 .\ resource.base.h resource.h FindMyMouse.base.rc FindMyMouse.rc" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,6 +1,10 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../../common/version/version.h"
|
||||
#include "../../../../common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
@@ -13,7 +17,7 @@ FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
847
src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp
Normal file
@@ -0,0 +1,847 @@
|
||||
// FindMyMouse.cpp : Based on Raymond Chen's SuperSonar.cpp
|
||||
//
|
||||
#include "pch.h"
|
||||
#include "FindMyMouse.h"
|
||||
#include "trace.h"
|
||||
#include "common/utils/game_mode.h"
|
||||
|
||||
#ifdef COMPOSITION
|
||||
namespace winrt
|
||||
{
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::UI::Composition;
|
||||
}
|
||||
|
||||
namespace ABI
|
||||
{
|
||||
using namespace ABI::Windows::System;
|
||||
using namespace ABI::Windows::UI::Composition::Desktop;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool m_doNotActivateOnGameMode = true;
|
||||
|
||||
#pragma region Super_Sonar_Base_Code
|
||||
|
||||
template<typename D>
|
||||
struct SuperSonar
|
||||
{
|
||||
bool Initialize(HINSTANCE hinst);
|
||||
void Terminate();
|
||||
|
||||
protected:
|
||||
// You are expected to override these, as appropriate.
|
||||
|
||||
DWORD GetExtendedStyle()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT WndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept
|
||||
{
|
||||
return BaseWndProc(message, wParam, lParam);
|
||||
}
|
||||
|
||||
void BeforeMoveSonar() {}
|
||||
void AfterMoveSonar() {}
|
||||
void SetSonarVisibility(bool visible) = delete;
|
||||
|
||||
protected:
|
||||
// Base class members you can access.
|
||||
D* Shim() { return static_cast<D*>(this); }
|
||||
LRESULT BaseWndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept;
|
||||
|
||||
HWND m_hwnd;
|
||||
POINT m_sonarPos = ptNowhere;
|
||||
|
||||
// Only consider double left control click if at least 100ms passed between the clicks, to avoid keyboards that might be sending rapid clicks.
|
||||
static const int MIN_DOUBLE_CLICK_TIME = 100;
|
||||
|
||||
static constexpr int SonarRadius = 100;
|
||||
static constexpr int SonarZoomFactor = 9;
|
||||
static constexpr DWORD FadeDuration = 500;
|
||||
static constexpr int FinalAlphaNumerator = 1;
|
||||
static constexpr int FinalAlphaDenominator = 2;
|
||||
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
|
||||
|
||||
private:
|
||||
static bool IsEqual(POINT const& p1, POINT const& p2)
|
||||
{
|
||||
return p1.x == p2.x && p1.y == p2.y;
|
||||
}
|
||||
|
||||
static constexpr POINT ptNowhere = { -1, -1 };
|
||||
|
||||
static constexpr DWORD TIMER_ID_TRACK = 100;
|
||||
static constexpr DWORD IdlePeriod = 1000;
|
||||
|
||||
// Activate sonar: Hit LeftControl twice.
|
||||
enum class SonarState
|
||||
{
|
||||
Idle,
|
||||
ControlDown1,
|
||||
ControlUp1,
|
||||
ControlDown2,
|
||||
ControlUp2,
|
||||
};
|
||||
|
||||
HWND m_hwndOwner;
|
||||
SonarState m_sonarState = SonarState::Idle;
|
||||
POINT m_lastKeyPos{};
|
||||
DWORD m_lastKeyTime{};
|
||||
|
||||
static constexpr DWORD NoSonar = 0;
|
||||
static constexpr DWORD SonarWaitingForMouseMove = 1;
|
||||
DWORD m_sonarStart = NoSonar;
|
||||
bool m_isSnoopingMouse = false;
|
||||
|
||||
private:
|
||||
static constexpr auto className = L"FindMyMouse";
|
||||
|
||||
// Use the runner name for the Window title. Otherwise, since Find My Mouse has an actual visual, its Window name will be the one shown in Task Manager after being shown.
|
||||
static constexpr auto windowTitle = L"PowerToys Runner";
|
||||
|
||||
static LRESULT CALLBACK s_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
BOOL OnSonarCreate();
|
||||
void OnSonarDestroy();
|
||||
void OnSonarInput(WPARAM flags, HRAWINPUT hInput);
|
||||
void OnSonarKeyboardInput(RAWINPUT const& input);
|
||||
void OnSonarMouseInput(RAWINPUT const& input);
|
||||
void OnMouseTimer();
|
||||
|
||||
void StartSonar();
|
||||
void StopSonar();
|
||||
|
||||
void UpdateMouseSnooping();
|
||||
};
|
||||
|
||||
template<typename D>
|
||||
bool SuperSonar<D>::Initialize(HINSTANCE hinst)
|
||||
{
|
||||
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
|
||||
WNDCLASS wc{};
|
||||
|
||||
if (!GetClassInfoW(hinst, className, &wc))
|
||||
{
|
||||
wc.lpfnWndProc = s_WndProc;
|
||||
wc.hInstance = hinst;
|
||||
wc.hIcon = LoadIcon(hinst, IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
|
||||
wc.lpszClassName = className;
|
||||
|
||||
if (!RegisterClassW(&wc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_hwndOwner = CreateWindow(L"static", nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hinst, nullptr);
|
||||
|
||||
DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | Shim()->GetExtendedStyle();
|
||||
return CreateWindowExW(exStyle, className, windowTitle, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hinst, this) != nullptr;
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::Terminate()
|
||||
{
|
||||
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
|
||||
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
|
||||
DestroyWindow(m_hwndOwner);
|
||||
});
|
||||
if (!enqueueSucceeded)
|
||||
{
|
||||
Logger::error("Couldn't enqueue message to destroy the sonar Window.");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
LRESULT SuperSonar<D>::s_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
SuperSonar* self;
|
||||
if (message == WM_NCCREATE)
|
||||
{
|
||||
auto info = (LPCREATESTRUCT)lParam;
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)info->lpCreateParams);
|
||||
self = (SuperSonar*)info->lpCreateParams;
|
||||
self->m_hwnd = hwnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
self = (SuperSonar*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
}
|
||||
if (self)
|
||||
{
|
||||
return self->Shim()->WndProc(message, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
return DefWindowProc(hwnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
LRESULT SuperSonar<D>::BaseWndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_CREATE:
|
||||
return OnSonarCreate() ? 0 : -1;
|
||||
|
||||
case WM_DESTROY:
|
||||
OnSonarDestroy();
|
||||
break;
|
||||
|
||||
case WM_INPUT:
|
||||
OnSonarInput(wParam, (HRAWINPUT)lParam);
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
switch (wParam)
|
||||
{
|
||||
case TIMER_ID_TRACK:
|
||||
OnMouseTimer();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NCHITTEST:
|
||||
return HTTRANSPARENT;
|
||||
}
|
||||
|
||||
return DefWindowProc(m_hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
BOOL SuperSonar<D>::OnSonarCreate()
|
||||
{
|
||||
RAWINPUTDEVICE keyboard{};
|
||||
keyboard.usUsagePage = HID_USAGE_PAGE_GENERIC;
|
||||
keyboard.usUsage = HID_USAGE_GENERIC_KEYBOARD;
|
||||
keyboard.dwFlags = RIDEV_INPUTSINK;
|
||||
keyboard.hwndTarget = m_hwnd;
|
||||
return RegisterRawInputDevices(&keyboard, 1, sizeof(keyboard));
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::OnSonarDestroy()
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::OnSonarInput(WPARAM flags, HRAWINPUT hInput)
|
||||
{
|
||||
RAWINPUT input;
|
||||
UINT size = sizeof(input);
|
||||
auto result = GetRawInputData(hInput, RID_INPUT, &input, &size, sizeof(RAWINPUTHEADER));
|
||||
if ((int)result < sizeof(RAWINPUTHEADER))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (input.header.dwType)
|
||||
{
|
||||
case RIM_TYPEKEYBOARD:
|
||||
OnSonarKeyboardInput(input);
|
||||
break;
|
||||
case RIM_TYPEMOUSE:
|
||||
OnSonarMouseInput(input);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::OnSonarKeyboardInput(RAWINPUT const& input)
|
||||
{
|
||||
// Don't activate if game mode is on.
|
||||
if (m_doNotActivateOnGameMode && detect_game_mode())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.data.keyboard.VKey != VK_CONTROL)
|
||||
{
|
||||
StopSonar();
|
||||
return;
|
||||
}
|
||||
|
||||
bool pressed = (input.data.keyboard.Flags & RI_KEY_BREAK) == 0;
|
||||
bool rightCtrl = (input.data.keyboard.Flags & RI_KEY_E0) != 0;
|
||||
|
||||
// Deal with rightCtrl first.
|
||||
if (rightCtrl)
|
||||
{
|
||||
/*
|
||||
* SuperSonar originally exited when pressing right control after pressing left control twice.
|
||||
* We take care of exiting FindMyMouse through module disabling in PowerToys settings instead.
|
||||
if (m_sonarState == SonarState::ControlUp2)
|
||||
{
|
||||
Terminate();
|
||||
}
|
||||
*/
|
||||
StopSonar();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m_sonarState)
|
||||
{
|
||||
case SonarState::Idle:
|
||||
if (pressed)
|
||||
{
|
||||
m_sonarState = SonarState::ControlDown1;
|
||||
m_lastKeyTime = GetTickCount();
|
||||
m_lastKeyPos = {};
|
||||
GetCursorPos(&m_lastKeyPos);
|
||||
UpdateMouseSnooping();
|
||||
}
|
||||
break;
|
||||
|
||||
case SonarState::ControlDown1:
|
||||
if (!pressed)
|
||||
{
|
||||
m_sonarState = SonarState::ControlUp1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SonarState::ControlUp1:
|
||||
if (pressed)
|
||||
{
|
||||
auto now = GetTickCount();
|
||||
auto doubleClickInterval = now - m_lastKeyTime;
|
||||
POINT ptCursor{};
|
||||
if (GetCursorPos(&ptCursor) &&
|
||||
doubleClickInterval >= MIN_DOUBLE_CLICK_TIME &&
|
||||
doubleClickInterval <= GetDoubleClickTime() &&
|
||||
IsEqual(m_lastKeyPos, ptCursor))
|
||||
{
|
||||
m_sonarState = SonarState::ControlDown2;
|
||||
StartSonar();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sonarState = SonarState::ControlDown1;
|
||||
m_lastKeyTime = GetTickCount();
|
||||
m_lastKeyPos = {};
|
||||
GetCursorPos(&m_lastKeyPos);
|
||||
UpdateMouseSnooping();
|
||||
}
|
||||
Logger::info("Detecting double left control click with {} ms interval.", doubleClickInterval);
|
||||
m_lastKeyTime = now;
|
||||
m_lastKeyPos = ptCursor;
|
||||
}
|
||||
break;
|
||||
case SonarState::ControlUp2:
|
||||
// Also deactivate sonar with left control.
|
||||
if (pressed)
|
||||
{
|
||||
StopSonar();
|
||||
}
|
||||
break;
|
||||
case SonarState::ControlDown2:
|
||||
if (!pressed)
|
||||
{
|
||||
m_sonarState = SonarState::ControlUp2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::OnSonarMouseInput(RAWINPUT const& input)
|
||||
{
|
||||
if (input.data.mouse.usButtonFlags)
|
||||
{
|
||||
StopSonar();
|
||||
}
|
||||
else if (m_sonarStart != NoSonar)
|
||||
{
|
||||
OnMouseTimer();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::StartSonar()
|
||||
{
|
||||
Logger::info("Focusing the sonar on the mouse cursor.");
|
||||
Trace::MousePointerFocused();
|
||||
// Cover the entire virtual screen.
|
||||
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0);
|
||||
m_sonarPos = ptNowhere;
|
||||
OnMouseTimer();
|
||||
UpdateMouseSnooping();
|
||||
Shim()->SetSonarVisibility(true);
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::StopSonar()
|
||||
{
|
||||
if (m_sonarStart != NoSonar)
|
||||
{
|
||||
m_sonarStart = NoSonar;
|
||||
Shim()->SetSonarVisibility(false);
|
||||
KillTimer(m_hwnd, TIMER_ID_TRACK);
|
||||
}
|
||||
m_sonarState = SonarState::Idle;
|
||||
UpdateMouseSnooping();
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::OnMouseTimer()
|
||||
{
|
||||
auto now = GetTickCount();
|
||||
|
||||
// If mouse has moved, then reset the sonar timer.
|
||||
POINT ptCursor{};
|
||||
if (!GetCursorPos(&ptCursor))
|
||||
{
|
||||
// We are no longer the active desktop - done.
|
||||
StopSonar();
|
||||
return;
|
||||
}
|
||||
ScreenToClient(m_hwnd, &ptCursor);
|
||||
|
||||
if (IsEqual(m_sonarPos, ptCursor))
|
||||
{
|
||||
// Mouse is stationary.
|
||||
if (m_sonarStart != SonarWaitingForMouseMove && now - m_sonarStart >= IdlePeriod)
|
||||
{
|
||||
StopSonar();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mouse has moved.
|
||||
if (IsEqual(m_sonarPos, ptNowhere))
|
||||
{
|
||||
// Initial call, mark sonar as active but waiting for first mouse-move.
|
||||
now = SonarWaitingForMouseMove;
|
||||
}
|
||||
SetTimer(m_hwnd, TIMER_ID_TRACK, IdlePeriod, nullptr);
|
||||
Shim()->BeforeMoveSonar();
|
||||
m_sonarPos = ptCursor;
|
||||
m_sonarStart = now;
|
||||
Shim()->AfterMoveSonar();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D>
|
||||
void SuperSonar<D>::UpdateMouseSnooping()
|
||||
{
|
||||
bool wantSnoopingMouse = m_sonarStart != NoSonar || m_sonarState != SonarState::Idle;
|
||||
if (m_isSnoopingMouse != wantSnoopingMouse)
|
||||
{
|
||||
m_isSnoopingMouse = wantSnoopingMouse;
|
||||
RAWINPUTDEVICE mouse{};
|
||||
mouse.usUsagePage = HID_USAGE_PAGE_GENERIC;
|
||||
mouse.usUsage = HID_USAGE_GENERIC_MOUSE;
|
||||
if (wantSnoopingMouse)
|
||||
{
|
||||
mouse.dwFlags = RIDEV_INPUTSINK;
|
||||
mouse.hwndTarget = m_hwnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
mouse.dwFlags = RIDEV_REMOVE;
|
||||
mouse.hwndTarget = nullptr;
|
||||
}
|
||||
RegisterRawInputDevices(&mouse, 1, sizeof(mouse));
|
||||
}
|
||||
}
|
||||
|
||||
struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
|
||||
{
|
||||
static constexpr UINT WM_OPACITY_ANIMATION_COMPLETED = WM_APP;
|
||||
static constexpr float SonarRadiusFloat = static_cast<float>(SonarRadius);
|
||||
|
||||
DWORD GetExtendedStyle()
|
||||
{
|
||||
return WS_EX_NOREDIRECTIONBITMAP;
|
||||
}
|
||||
|
||||
void AfterMoveSonar()
|
||||
{
|
||||
m_spotlight.Offset({ (float)m_sonarPos.x, (float)m_sonarPos.y, 0.0f });
|
||||
}
|
||||
|
||||
LRESULT WndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_CREATE:
|
||||
return OnCompositionCreate() && BaseWndProc(message, wParam, lParam);
|
||||
|
||||
case WM_OPACITY_ANIMATION_COMPLETED:
|
||||
OnOpacityAnimationCompleted();
|
||||
break;
|
||||
}
|
||||
return BaseWndProc(message, wParam, lParam);
|
||||
}
|
||||
|
||||
void SetSonarVisibility(bool visible)
|
||||
{
|
||||
m_batch = m_compositor.GetCommitBatch(winrt::CompositionBatchTypes::Animation);
|
||||
m_batch.Completed([hwnd = m_hwnd](auto&&, auto&&) {
|
||||
PostMessage(hwnd, WM_OPACITY_ANIMATION_COMPLETED, 0, 0);
|
||||
});
|
||||
m_root.Opacity(visible ? static_cast<float>(FinalAlphaNumerator) / FinalAlphaDenominator : 0.0f);
|
||||
if (visible)
|
||||
{
|
||||
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool OnCompositionCreate()
|
||||
try
|
||||
{
|
||||
// We need a dispatcher queue.
|
||||
DispatcherQueueOptions options = {
|
||||
sizeof(options),
|
||||
DQTYPE_THREAD_CURRENT,
|
||||
DQTAT_COM_ASTA,
|
||||
};
|
||||
ABI::IDispatcherQueueController* controller;
|
||||
winrt::check_hresult(CreateDispatcherQueueController(options, &controller));
|
||||
*winrt::put_abi(m_dispatcherQueueController) = controller;
|
||||
|
||||
// Create the compositor for our window.
|
||||
m_compositor = winrt::Compositor();
|
||||
ABI::IDesktopWindowTarget* target;
|
||||
winrt::check_hresult(m_compositor.as<ABI::ICompositorDesktopInterop>()->CreateDesktopWindowTarget(m_hwnd, false, &target));
|
||||
*winrt::put_abi(m_target) = target;
|
||||
|
||||
// Our composition tree:
|
||||
//
|
||||
// [root] ContainerVisual
|
||||
// \ LayerVisual
|
||||
// \[gray backdrop]
|
||||
// [spotlight]
|
||||
m_root = m_compositor.CreateContainerVisual();
|
||||
m_root.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
|
||||
m_root.Opacity(0.0f);
|
||||
m_target.Root(m_root);
|
||||
|
||||
auto layer = m_compositor.CreateLayerVisual();
|
||||
layer.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
|
||||
m_root.Children().InsertAtTop(layer);
|
||||
|
||||
auto backdrop = m_compositor.CreateSpriteVisual();
|
||||
backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
|
||||
backdrop.Brush(m_compositor.CreateColorBrush({ 255, 0, 0, 0 }));
|
||||
layer.Children().InsertAtTop(backdrop);
|
||||
|
||||
m_circleGeometry = m_compositor.CreateEllipseGeometry(); // radius set via expression animation
|
||||
auto circleShape = m_compositor.CreateSpriteShape(m_circleGeometry);
|
||||
circleShape.FillBrush(m_compositor.CreateColorBrush({ 255, 255, 255, 255 }));
|
||||
circleShape.Offset({ SonarRadiusFloat * SonarZoomFactor, SonarRadiusFloat * SonarZoomFactor });
|
||||
m_spotlight = m_compositor.CreateShapeVisual();
|
||||
m_spotlight.Size({ SonarRadiusFloat * 2 * SonarZoomFactor, SonarRadiusFloat * 2 * SonarZoomFactor });
|
||||
m_spotlight.AnchorPoint({ 0.5f, 0.5f });
|
||||
m_spotlight.Shapes().Append(circleShape);
|
||||
|
||||
layer.Children().InsertAtTop(m_spotlight);
|
||||
|
||||
// Implicitly animate the alpha.
|
||||
auto animation = m_compositor.CreateScalarKeyFrameAnimation();
|
||||
animation.Target(L"Opacity");
|
||||
animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
|
||||
animation.Duration(std::chrono::milliseconds{ FadeDuration });
|
||||
auto collection = m_compositor.CreateImplicitAnimationCollection();
|
||||
collection.Insert(L"Opacity", animation);
|
||||
m_root.ImplicitAnimations(collection);
|
||||
|
||||
// Radius of spotlight shrinks as opacity increases.
|
||||
// At opacity zero, it is SonarRadius * SonarZoomFactor.
|
||||
// At maximum opacity, it is SonarRadius.
|
||||
auto radiusExpression = m_compositor.CreateExpressionAnimation();
|
||||
radiusExpression.SetReferenceParameter(L"Root", m_root);
|
||||
wchar_t expressionText[256];
|
||||
winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity * %d / %d)", SonarRadius * SonarZoomFactor, SonarRadius * SonarZoomFactor, SonarRadius, SonarRadius, FinalAlphaDenominator, FinalAlphaNumerator));
|
||||
radiusExpression.Expression(expressionText);
|
||||
m_circleGeometry.StartAnimation(L"Radius", radiusExpression);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnOpacityAnimationCompleted()
|
||||
{
|
||||
if (m_root.Opacity() < 0.01f)
|
||||
{
|
||||
ShowWindow(m_hwnd, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::Compositor m_compositor{ nullptr };
|
||||
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
|
||||
winrt::ContainerVisual m_root{ nullptr };
|
||||
winrt::CompositionEllipseGeometry m_circleGeometry{ nullptr };
|
||||
winrt::ShapeVisual m_spotlight{ nullptr };
|
||||
winrt::CompositionCommitBatch m_batch{ nullptr };
|
||||
};
|
||||
|
||||
template<typename D>
|
||||
struct GdiSonar : SuperSonar<D>
|
||||
{
|
||||
LRESULT WndProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_CREATE:
|
||||
SetLayeredWindowAttributes(this->m_hwnd, 0, 0, LWA_ALPHA);
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
switch (wParam)
|
||||
{
|
||||
case TIMER_ID_FADE:
|
||||
OnFadeTimer();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
this->Shim()->OnPaint();
|
||||
break;
|
||||
}
|
||||
return this->BaseWndProc(message, wParam, lParam);
|
||||
}
|
||||
|
||||
void BeforeMoveSonar() { this->Shim()->InvalidateSonar(); }
|
||||
void AfterMoveSonar() { this->Shim()->InvalidateSonar(); }
|
||||
|
||||
void SetSonarVisibility(bool visible)
|
||||
{
|
||||
m_alphaTarget = visible ? MaxAlpha : 0;
|
||||
m_fadeStart = GetTickCount() - FadeFramePeriod;
|
||||
SetTimer(this->m_hwnd, TIMER_ID_FADE, FadeFramePeriod, nullptr);
|
||||
OnFadeTimer();
|
||||
}
|
||||
|
||||
void OnFadeTimer()
|
||||
{
|
||||
auto now = GetTickCount();
|
||||
auto step = (int)((now - m_fadeStart) * MaxAlpha / this->FadeDuration);
|
||||
|
||||
this->Shim()->InvalidateSonar();
|
||||
if (m_alpha < m_alphaTarget)
|
||||
{
|
||||
m_alpha += step;
|
||||
if (m_alpha > m_alphaTarget)
|
||||
m_alpha = m_alphaTarget;
|
||||
}
|
||||
else if (m_alpha > m_alphaTarget)
|
||||
{
|
||||
m_alpha -= step;
|
||||
if (m_alpha < m_alphaTarget)
|
||||
m_alpha = m_alphaTarget;
|
||||
}
|
||||
SetLayeredWindowAttributes(this->m_hwnd, 0, (BYTE)m_alpha, LWA_ALPHA);
|
||||
this->Shim()->InvalidateSonar();
|
||||
if (m_alpha == m_alphaTarget)
|
||||
{
|
||||
KillTimer(this->m_hwnd, TIMER_ID_FADE);
|
||||
if (m_alpha == 0)
|
||||
{
|
||||
ShowWindow(this->m_hwnd, SW_HIDE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowWindow(this->m_hwnd, SW_SHOWNOACTIVATE);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int CurrentSonarRadius()
|
||||
{
|
||||
int range = MaxAlpha - m_alpha;
|
||||
int radius = this->SonarRadius + this->SonarRadius * range * (this->SonarZoomFactor - 1) / MaxAlpha;
|
||||
return radius;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr DWORD FadeFramePeriod = 10;
|
||||
static constexpr int MaxAlpha = SuperSonar<D>::FinalAlphaNumerator * 255 / SuperSonar<D>::FinalAlphaDenominator;
|
||||
static constexpr DWORD TIMER_ID_FADE = 101;
|
||||
|
||||
private:
|
||||
int m_alpha = 0;
|
||||
int m_alphaTarget = 0;
|
||||
DWORD m_fadeStart = 0;
|
||||
};
|
||||
|
||||
struct GdiSpotlight : GdiSonar<GdiSpotlight>
|
||||
{
|
||||
void InvalidateSonar()
|
||||
{
|
||||
RECT rc;
|
||||
auto radius = CurrentSonarRadius();
|
||||
rc.left = this->m_sonarPos.x - radius;
|
||||
rc.top = this->m_sonarPos.y - radius;
|
||||
rc.right = this->m_sonarPos.x + radius;
|
||||
rc.bottom = this->m_sonarPos.y + radius;
|
||||
InvalidateRect(this->m_hwnd, &rc, FALSE);
|
||||
}
|
||||
|
||||
void OnPaint()
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(this->m_hwnd, &ps);
|
||||
|
||||
auto radius = CurrentSonarRadius();
|
||||
auto spotlight = CreateRoundRectRgn(
|
||||
this->m_sonarPos.x - radius, this->m_sonarPos.y - radius, this->m_sonarPos.x + radius, this->m_sonarPos.y + radius, radius * 2, radius * 2);
|
||||
|
||||
FillRgn(ps.hdc, spotlight, (HBRUSH)GetStockObject(WHITE_BRUSH));
|
||||
Sleep(1000 / 60);
|
||||
ExtSelectClipRgn(ps.hdc, spotlight, RGN_DIFF);
|
||||
FillRect(ps.hdc, &ps.rcPaint, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
||||
DeleteObject(spotlight);
|
||||
|
||||
EndPaint(this->m_hwnd, &ps);
|
||||
}
|
||||
};
|
||||
|
||||
struct GdiCrosshairs : GdiSonar<GdiCrosshairs>
|
||||
{
|
||||
void InvalidateSonar()
|
||||
{
|
||||
RECT rc;
|
||||
auto radius = CurrentSonarRadius();
|
||||
GetClientRect(m_hwnd, &rc);
|
||||
rc.left = m_sonarPos.x - radius;
|
||||
rc.right = m_sonarPos.x + radius;
|
||||
InvalidateRect(m_hwnd, &rc, FALSE);
|
||||
|
||||
GetClientRect(m_hwnd, &rc);
|
||||
rc.top = m_sonarPos.y - radius;
|
||||
rc.bottom = m_sonarPos.y + radius;
|
||||
InvalidateRect(m_hwnd, &rc, FALSE);
|
||||
}
|
||||
|
||||
void OnPaint()
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(this->m_hwnd, &ps);
|
||||
|
||||
auto radius = CurrentSonarRadius();
|
||||
RECT rc;
|
||||
|
||||
HBRUSH white = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
||||
|
||||
rc.left = m_sonarPos.x - radius;
|
||||
rc.top = ps.rcPaint.top;
|
||||
rc.right = m_sonarPos.x + radius;
|
||||
rc.bottom = ps.rcPaint.bottom;
|
||||
FillRect(ps.hdc, &rc, white);
|
||||
|
||||
rc.left = ps.rcPaint.left;
|
||||
rc.top = m_sonarPos.y - radius;
|
||||
rc.right = ps.rcPaint.right;
|
||||
rc.bottom = m_sonarPos.y + radius;
|
||||
FillRect(ps.hdc, &rc, white);
|
||||
|
||||
HBRUSH black = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
|
||||
// Top left
|
||||
rc.left = ps.rcPaint.left;
|
||||
rc.top = ps.rcPaint.top;
|
||||
rc.right = m_sonarPos.x - radius;
|
||||
rc.bottom = m_sonarPos.y - radius;
|
||||
FillRect(ps.hdc, &rc, black);
|
||||
|
||||
// Top right
|
||||
rc.left = m_sonarPos.x + radius;
|
||||
rc.top = ps.rcPaint.top;
|
||||
rc.right = ps.rcPaint.right;
|
||||
rc.bottom = m_sonarPos.y - radius;
|
||||
FillRect(ps.hdc, &rc, black);
|
||||
|
||||
// Bottom left
|
||||
rc.left = ps.rcPaint.left;
|
||||
rc.top = m_sonarPos.y + radius;
|
||||
rc.right = m_sonarPos.x - radius;
|
||||
rc.bottom = ps.rcPaint.bottom;
|
||||
FillRect(ps.hdc, &rc, black);
|
||||
|
||||
// Bottom right
|
||||
rc.left = m_sonarPos.x + radius;
|
||||
rc.top = m_sonarPos.y + radius;
|
||||
rc.right = ps.rcPaint.right;
|
||||
rc.bottom = ps.rcPaint.bottom;
|
||||
FillRect(ps.hdc, &rc, black);
|
||||
|
||||
EndPaint(this->m_hwnd, &ps);
|
||||
}
|
||||
};
|
||||
|
||||
#pragma endregion Super_Sonar_Base_Code
|
||||
|
||||
|
||||
#pragma region Super_Sonar_API
|
||||
|
||||
CompositionSpotlight* m_sonar = nullptr;
|
||||
|
||||
void FindMyMouseDisable()
|
||||
{
|
||||
if (m_sonar != nullptr)
|
||||
{
|
||||
Logger::info("Terminating a sonar instance.");
|
||||
m_sonar->Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
bool FindMyMouseIsEnabled()
|
||||
{
|
||||
return (m_sonar != nullptr);
|
||||
}
|
||||
|
||||
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate)
|
||||
{
|
||||
m_doNotActivateOnGameMode = doNotActivate;
|
||||
}
|
||||
|
||||
// Based on SuperSonar's original wWinMain.
|
||||
int FindMyMouseMain(HINSTANCE hinst)
|
||||
{
|
||||
Logger::info("Starting a sonar instance.");
|
||||
if (m_sonar != nullptr)
|
||||
{
|
||||
Logger::error("A sonar instance was still working when trying to start a new one.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
CompositionSpotlight sonar;
|
||||
if (!sonar.Initialize(hinst))
|
||||
{
|
||||
Logger::error("Couldn't initialize a sonar instance.");
|
||||
return 0;
|
||||
}
|
||||
m_sonar = &sonar;
|
||||
Logger::info("Initialized the sonar instance.");
|
||||
|
||||
MSG msg;
|
||||
|
||||
// Main message loop:
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
Logger::info("Sonar message loop ended.");
|
||||
m_sonar = nullptr;
|
||||
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
|
||||
#pragma endregion Super_Sonar_API
|
||||
6
src/modules/MouseUtils/FindMyMouse/FindMyMouse.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "pch.h"
|
||||
int FindMyMouseMain(HINSTANCE hinst);
|
||||
void FindMyMouseDisable();
|
||||
bool FindMyMouseIsEnabled();
|
||||
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate);
|
||||
146
src/modules/MouseUtils/FindMyMouse/FindMyMouse.vcxproj
Normal file
@@ -0,0 +1,146 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{e94fd11c-0591-456f-899f-efc0ca548336}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>FindMyMouse</RootNamespace>
|
||||
<OverrideWindowsTargetPlatformVersion>true</OverrideWindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>FindMyMouse</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(CIBuild)'!='true'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="FindMyMouse.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="Generated Files\resource.h" />
|
||||
<None Include="resource.base.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="FindMyMouse.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp" />
|
||||
<None Include="FindMyMouse.base.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files\FindMyMouse.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -3,22 +3,31 @@
|
||||
<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>
|
||||
<Extensions>cpp;c;cc;cxx;c++;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;ipp;xsd</Extensions>
|
||||
<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>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{875a08c6-f610-4667-bd0f-80171ed96072}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileExplorerPreviewSettingsTest.cpp">
|
||||
<ClCompile Include="FindMyMouse.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
@@ -26,16 +35,28 @@
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FindMyMouse.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Generated Files\resource.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="powerpreviewTest.rc">
|
||||
<None Include="packages.config" />
|
||||
<None Include="resource.base.h">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</None>
|
||||
<None Include="FindMyMouse.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<ResourceCompile Include="Generated Files\FindMyMouse.rc">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
186
src/modules/MouseUtils/FindMyMouse/dllmain.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#include "pch.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include "trace.h"
|
||||
#include "FindMyMouse.h"
|
||||
#include <thread>
|
||||
#include <common/utils/logger_helper.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
|
||||
const wchar_t JSON_KEY_VALUE[] = L"value";
|
||||
const wchar_t JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE[] = L"do_not_activate_on_game_mode";
|
||||
}
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
HMODULE m_hModule;
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
m_hModule = hModule;
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Trace::RegisterProvider();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// The PowerToy name that will be shown in the settings.
|
||||
const static wchar_t* MODULE_NAME = L"FindMyMouse";
|
||||
// Add a description that will we shown in the module settings page.
|
||||
const static wchar_t* MODULE_DESC = L"Focus the mouse pointer";
|
||||
|
||||
// Implement the PowerToy Module Interface and all the required methods.
|
||||
class FindMyMouse : public PowertoyModuleIface
|
||||
{
|
||||
private:
|
||||
// The PowerToy state.
|
||||
bool m_enabled = false;
|
||||
|
||||
// Load initial settings from the persisted values.
|
||||
void init_settings();
|
||||
|
||||
// Helper function to extract the settings
|
||||
void parse_settings(PowerToysSettings::PowerToyValues& settings);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
FindMyMouse()
|
||||
{
|
||||
LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::findMyMouseLoggerName);
|
||||
init_settings();
|
||||
};
|
||||
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
// Return the localized display name of the powertoy
|
||||
virtual const wchar_t* get_name() override
|
||||
{
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
// Return the non localized key of the powertoy, this will be cached by the runner
|
||||
virtual const wchar_t* get_key() override
|
||||
{
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
{
|
||||
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||
|
||||
// Create a Settings object.
|
||||
PowerToysSettings::Settings settings(hinstance, get_name());
|
||||
settings.set_description(MODULE_DESC);
|
||||
|
||||
return settings.serialize_to_buffer(buffer, buffer_size);
|
||||
}
|
||||
|
||||
// Signal from the Settings editor to call a custom action.
|
||||
// This can be used to spawn more complex editors.
|
||||
virtual void call_custom_action(const wchar_t* action) override
|
||||
{
|
||||
}
|
||||
|
||||
// Called by the runner to pass the updated settings values as a serialized JSON.
|
||||
virtual void set_config(const wchar_t* config) override
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the input JSON string.
|
||||
PowerToysSettings::PowerToyValues values =
|
||||
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||
|
||||
parse_settings(values);
|
||||
|
||||
values.save_to_settings_file();
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
// Improper JSON.
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the powertoy
|
||||
virtual void enable()
|
||||
{
|
||||
m_enabled = true;
|
||||
Trace::EnableFindMyMouse(true);
|
||||
std::thread([]() { FindMyMouseMain(m_hModule); }).detach();
|
||||
}
|
||||
|
||||
// Disable the powertoy
|
||||
virtual void disable()
|
||||
{
|
||||
m_enabled = false;
|
||||
Trace::EnableFindMyMouse(false);
|
||||
FindMyMouseDisable();
|
||||
}
|
||||
|
||||
// Returns if the powertoys is enabled
|
||||
virtual bool is_enabled() override
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
};
|
||||
|
||||
// Load the settings file.
|
||||
void FindMyMouse::init_settings()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load and parse the settings file for this PowerToy.
|
||||
PowerToysSettings::PowerToyValues settings =
|
||||
PowerToysSettings::PowerToyValues::load_from_settings_file(FindMyMouse::get_key());
|
||||
parse_settings(settings);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
// Error while loading from the settings file. Let default values stay as they are.
|
||||
}
|
||||
}
|
||||
|
||||
void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
|
||||
{
|
||||
FindMyMouseSetDoNotActivateOnGameMode(true);
|
||||
|
||||
auto settingsObject = settings.get_raw_json();
|
||||
if (settingsObject.GetView().Size())
|
||||
{
|
||||
try
|
||||
{
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE);
|
||||
FindMyMouseSetDoNotActivateOnGameMode((bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::warn("Failed to get 'do not activate on game mode' setting");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info("Find My Mouse settings are empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new FindMyMouse();
|
||||
}
|
||||
20
src/modules/MouseUtils/FindMyMouse/pch.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#define COMPOSITION
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <hIdUsage.h>
|
||||
|
||||
#ifdef COMPOSITION
|
||||
#include <windows.ui.composition.interop.h>
|
||||
#include <DispatcherQueue.h>
|
||||
#include <winrt/Windows.System.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.UI.Composition.Desktop.h>
|
||||
#endif
|
||||
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <ProjectTelemetry.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/logger/logger.h>
|
||||
14
src/modules/MouseUtils/FindMyMouse/resource.base.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by FindMyMouse.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys FindMyMouse"
|
||||
#define INTERNAL_NAME "FindMyMouse"
|
||||
#define ORIGINAL_FILENAME "FindMyMouse.dll"
|
||||
#define IDS_KEYBOARDMANAGER_ICON 1001
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
||||
40
src/modules/MouseUtils/FindMyMouse/trace.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "pch.h"
|
||||
#include "trace.h"
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hProvider,
|
||||
"Microsoft.PowerToys",
|
||||
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||
TraceLoggingOptionProjectTelemetry());
|
||||
|
||||
void Trace::RegisterProvider() noexcept
|
||||
{
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
}
|
||||
|
||||
void Trace::UnregisterProvider() noexcept
|
||||
{
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
}
|
||||
|
||||
// Log if the user has FindMyMouse enabled or disabled
|
||||
void Trace::EnableFindMyMouse(const bool enabled) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"FindMyMouse_EnableFindMyMouse",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingBoolean(enabled, "Enabled"));
|
||||
}
|
||||
|
||||
// Log that the user activated the module by focusing the mouse pointer
|
||||
void Trace::MousePointerFocused() noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"FindMyMouse_MousePointerFocused",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
14
src/modules/MouseUtils/FindMyMouse/trace.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
static void RegisterProvider() noexcept;
|
||||
static void UnregisterProvider() noexcept;
|
||||
|
||||
// Log if the user has FindMyMouse enabled or disabled
|
||||
static void EnableFindMyMouse(const bool enabled) noexcept;
|
||||
|
||||
// Log that the user activated the module by focusing the mouse pointer
|
||||
static void MousePointerFocused() noexcept;
|
||||
};
|
||||
@@ -7,4 +7,6 @@ struct ShortcutGuideSettings
|
||||
int overlayOpacity = 90;
|
||||
std::wstring theme = L"system";
|
||||
std::wstring disabledApps = L"";
|
||||
bool shouldReactToPressedWinKey = false;
|
||||
int windowsKeyPressTime = 900;
|
||||
};
|
||||
|
||||
@@ -221,6 +221,15 @@ void OverlayWindow::CloseWindow(HideWindowType type, int mainThreadId)
|
||||
|
||||
if (this->winkey_popup)
|
||||
{
|
||||
if (shouldReactToPressedWinKey.value)
|
||||
{
|
||||
// Send a dummy key to prevent Start Menu from activating
|
||||
INPUT dummyEvent[1] = {};
|
||||
dummyEvent[0].type = INPUT_KEYBOARD;
|
||||
dummyEvent[0].ki.wVk = 0xFF;
|
||||
dummyEvent[0].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
SendInput(1, dummyEvent, sizeof(INPUT));
|
||||
}
|
||||
this->winkey_popup->SetWindowCloseType(ToWstring(type));
|
||||
Logger::trace(L"Terminating process");
|
||||
PostThreadMessage(mainThreadId, WM_QUIT, 0, 0);
|
||||
@@ -300,6 +309,7 @@ void OverlayWindow::init_settings()
|
||||
overlayOpacity.value = settings.overlayOpacity;
|
||||
theme.value = settings.theme;
|
||||
disabledApps.value = settings.disabledApps;
|
||||
shouldReactToPressedWinKey.value = settings.shouldReactToPressedWinKey;
|
||||
update_disabled_apps();
|
||||
}
|
||||
|
||||
@@ -399,6 +409,22 @@ ShortcutGuideSettings OverlayWindow::GetSettings() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
settings.shouldReactToPressedWinKey = properties.GetNamedObject(ShouldReactToPressedWinKey::name).GetNamedBoolean(L"value");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
settings.windowsKeyPressTime = (int)properties.GetNamedObject(WindowsKeyPressTime::name).GetNamedNumber(L"value");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
settings.theme = (std::wstring)properties.GetNamedObject(Theme::name).GetNamedString(L"value");
|
||||
|
||||
@@ -78,6 +78,17 @@ private:
|
||||
std::wstring value;
|
||||
} disabledApps;
|
||||
|
||||
struct ShouldReactToPressedWinKey
|
||||
{
|
||||
static inline PCWSTR name = L"use_legacy_press_win_key_behavior";
|
||||
bool value;
|
||||
} shouldReactToPressedWinKey;
|
||||
|
||||
struct WindowsKeyPressTime
|
||||
{
|
||||
static inline PCWSTR name = L"press_time";
|
||||
} windowsKeyPressTime;
|
||||
|
||||
struct OpenShortcut
|
||||
{
|
||||
static inline PCWSTR name = L"open_shortcutguide";
|
||||
|
||||
@@ -39,6 +39,8 @@ void Trace::SendSettings(ShortcutGuideSettings settings) noexcept
|
||||
TraceLoggingInt32(settings.overlayOpacity, "OverlayOpacity"),
|
||||
TraceLoggingWideString(settings.theme.c_str(), "Theme"),
|
||||
TraceLoggingWideString(settings.disabledApps.c_str(), "DisabledApps"),
|
||||
TraceLoggingBoolean(settings.shouldReactToPressedWinKey, "ShouldReactToPressedWinKey"),
|
||||
TraceLoggingInt32(settings.windowsKeyPressTime, "WindowsKeyPressTime"),
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
PowerToysSettings::PowerToyValues values =
|
||||
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||
|
||||
ParseHotkey(values);
|
||||
ParseSettings(values);
|
||||
}
|
||||
catch (std::exception ex)
|
||||
{
|
||||
@@ -119,6 +119,10 @@ public:
|
||||
virtual std::optional<HotkeyEx> GetHotkeyEx() override
|
||||
{
|
||||
Logger::trace("GetHotkeyEx()");
|
||||
if (m_shouldReactToPressedWinKey)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
return m_hotkey;
|
||||
}
|
||||
|
||||
@@ -154,6 +158,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool keep_track_of_pressed_win_key() override
|
||||
{
|
||||
return m_shouldReactToPressedWinKey;
|
||||
}
|
||||
|
||||
virtual UINT milliseconds_win_key_must_be_pressed() override
|
||||
{
|
||||
return m_millisecondsWinKeyShouldBePressed;
|
||||
}
|
||||
|
||||
private:
|
||||
std::wstring app_name;
|
||||
//contains the non localized key of the powertoy
|
||||
@@ -163,6 +177,12 @@ private:
|
||||
|
||||
// Hotkey to invoke the module
|
||||
HotkeyEx m_hotkey;
|
||||
|
||||
// If the module should be activated through the legacy pressing windows key behavior.
|
||||
const UINT DEFAULT_MILLISECONDS_WIN_KEY_SHOULD_BE_PRESSED = 900;
|
||||
bool m_shouldReactToPressedWinKey = false;
|
||||
UINT m_millisecondsWinKeyShouldBePressed = DEFAULT_MILLISECONDS_WIN_KEY_SHOULD_BE_PRESSED;
|
||||
|
||||
HANDLE exitEvent;
|
||||
|
||||
bool StartProcess(std::wstring args = L"")
|
||||
@@ -239,7 +259,7 @@ private:
|
||||
PowerToysSettings::PowerToyValues settings =
|
||||
PowerToysSettings::PowerToyValues::load_from_settings_file(app_key);
|
||||
|
||||
ParseHotkey(settings);
|
||||
ParseSettings(settings);
|
||||
}
|
||||
catch (std::exception ex)
|
||||
{
|
||||
@@ -251,13 +271,17 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void ParseHotkey(PowerToysSettings::PowerToyValues& settings)
|
||||
void ParseSettings(PowerToysSettings::PowerToyValues& settings)
|
||||
{
|
||||
m_shouldReactToPressedWinKey = false;
|
||||
m_millisecondsWinKeyShouldBePressed = DEFAULT_MILLISECONDS_WIN_KEY_SHOULD_BE_PRESSED;
|
||||
|
||||
auto settingsObject = settings.get_raw_json();
|
||||
if (settingsObject.GetView().Size())
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse HotKey
|
||||
auto jsonHotkeyObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"open_shortcutguide");
|
||||
auto hotkey = PowerToysSettings::HotkeyObject::from_json(jsonHotkeyObject);
|
||||
m_hotkey = HotkeyEx();
|
||||
@@ -287,6 +311,18 @@ private:
|
||||
{
|
||||
Logger::warn("Failed to initialize Shortcut Guide start shortcut");
|
||||
}
|
||||
try
|
||||
{
|
||||
// Parse Legacy windows key press behavior settings
|
||||
auto jsonUseLegacyWinKeyBehaviorObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"use_legacy_press_win_key_behavior");
|
||||
m_shouldReactToPressedWinKey = (bool)jsonUseLegacyWinKeyBehaviorObject.GetNamedBoolean(L"value");
|
||||
auto jsonPressTimeObject = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"press_time");
|
||||
m_millisecondsWinKeyShouldBePressed = (UINT)jsonPressTimeObject.GetNamedNumber(L"value");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::warn("Failed to get legacy win key behavior settings");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace Awake.Core
|
||||
};
|
||||
|
||||
// No keep-awake menu item.
|
||||
ToolStripMenuItem? passiveMenuItem = new ToolStripMenuItem
|
||||
CheckButtonToolStripMenuItem? passiveMenuItem = new CheckButtonToolStripMenuItem
|
||||
{
|
||||
Text = "Off (Passive)",
|
||||
};
|
||||
@@ -189,7 +189,7 @@ namespace Awake.Core
|
||||
};
|
||||
|
||||
// Indefinite keep-awake menu item.
|
||||
ToolStripMenuItem? indefiniteMenuItem = new ToolStripMenuItem
|
||||
CheckButtonToolStripMenuItem? indefiniteMenuItem = new CheckButtonToolStripMenuItem
|
||||
{
|
||||
Text = "Keep awake indefinitely",
|
||||
};
|
||||
@@ -202,7 +202,7 @@ namespace Awake.Core
|
||||
indefiniteKeepAwakeCallback();
|
||||
};
|
||||
|
||||
ToolStripMenuItem? displayOnMenuItem = new ToolStripMenuItem
|
||||
CheckButtonToolStripMenuItem? displayOnMenuItem = new CheckButtonToolStripMenuItem
|
||||
{
|
||||
Text = "Keep screen on",
|
||||
};
|
||||
@@ -222,6 +222,7 @@ namespace Awake.Core
|
||||
};
|
||||
|
||||
timedMenuItem.Checked = mode == AwakeMode.TIMED;
|
||||
timedMenuItem.AccessibleName = timedMenuItem.Text + (timedMenuItem.Checked ? ". Checked. " : ". UnChecked. ");
|
||||
|
||||
ToolStripMenuItem? halfHourMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
@@ -284,5 +285,38 @@ namespace Awake.Core
|
||||
TrayIcon.Text = text;
|
||||
TrayIcon.ContextMenuStrip = contextMenuStrip;
|
||||
}
|
||||
|
||||
private class CheckButtonToolStripMenuItemAccessibleObject : ToolStripItem.ToolStripItemAccessibleObject
|
||||
{
|
||||
private CheckButtonToolStripMenuItem _menuItem;
|
||||
|
||||
public CheckButtonToolStripMenuItemAccessibleObject(CheckButtonToolStripMenuItem menuItem)
|
||||
: base(menuItem)
|
||||
{
|
||||
_menuItem = menuItem;
|
||||
}
|
||||
|
||||
public override AccessibleRole Role
|
||||
{
|
||||
get
|
||||
{
|
||||
return AccessibleRole.CheckButton;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name => _menuItem.Text + ", " + Role + ", " + (_menuItem.Checked ? "Checked" : "Unchecked");
|
||||
}
|
||||
|
||||
private class CheckButtonToolStripMenuItem : ToolStripMenuItem
|
||||
{
|
||||
public CheckButtonToolStripMenuItem()
|
||||
{
|
||||
}
|
||||
|
||||
protected override AccessibleObject CreateAccessibilityInstance()
|
||||
{
|
||||
return new CheckButtonToolStripMenuItemAccessibleObject(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
BorderThickness="1"
|
||||
Title="Color Picker"
|
||||
Height="380"
|
||||
Width="400"
|
||||
Width="440"
|
||||
ResizeMode="NoResize"
|
||||
Topmost="True"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// 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.Windows;
|
||||
using ColorPicker.Helpers;
|
||||
|
||||
@@ -26,5 +27,11 @@ namespace ColorPicker
|
||||
e.Cancel = true;
|
||||
_appStateHandler.EndUserSession();
|
||||
}
|
||||
|
||||
protected override void OnSourceInitialized(EventArgs e)
|
||||
{
|
||||
base.OnSourceInitialized(e);
|
||||
NativeMethods.SetPopupStyle(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<UserControl x:Class="ColorPicker.Controls.ColorFormatControl"
|
||||
xmlns:local="clr-namespace:ColorPicker"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -8,7 +9,7 @@
|
||||
|
||||
<Border x:Name="MainBorder"
|
||||
Margin="12,16,12,0"
|
||||
Width="308"
|
||||
Width="348"
|
||||
Height="36"
|
||||
CornerRadius="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
@@ -20,7 +21,7 @@
|
||||
<ColumnDefinition Width="36"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="FormatNameTextBlock"
|
||||
Opacity="0.4"
|
||||
Opacity="0.6"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Margin="8"
|
||||
FontWeight="SemiBold"
|
||||
@@ -44,12 +45,14 @@
|
||||
<Button x:Name="CopyToClipboardButton"
|
||||
ToolTipService.ToolTip="{x:Static p:Resources.Copy_to_clipboard}"
|
||||
Background="{DynamicResource ColorControlBackgroundBrush}"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Opacity="0.6"
|
||||
Height="36"
|
||||
Width="36"
|
||||
Grid.Column="2"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Copy_to_clipboard}"
|
||||
AutomationProperties.HelpText="{Binding ElementName=ColorTextRepresentationTextBlock, Path=Text}"
|
||||
AutomationProperties.HelpText="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Controls.ColorFormatControl}}, Path=SelectedColorCopyHelperText}"
|
||||
|
||||
FontSize="12"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
FontFamily="Segoe MDL2 Assets">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Automation.Peers;
|
||||
using System.Windows.Controls;
|
||||
@@ -23,6 +24,8 @@ namespace ColorPicker.Controls
|
||||
|
||||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorFormatControl), new PropertyMetadata(SelectedColorPropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty SelectedColorCopyHelperTextProperty = DependencyProperty.Register("SelectedColorCopyHelperText", typeof(string), typeof(ColorFormatControl));
|
||||
|
||||
public static readonly DependencyProperty ColorCopiedNotificationBorderProperty = DependencyProperty.Register("ColorCopiedNotificationBorder", typeof(FrameworkElement), typeof(ColorFormatControl), new PropertyMetadata(ColorCopiedBorderPropertyChanged));
|
||||
|
||||
private const int CopyIndicatorStayTimeInMs = 3000;
|
||||
@@ -47,6 +50,12 @@ namespace ColorPicker.Controls
|
||||
set { SetValue(ColorCopiedNotificationBorderProperty, value); }
|
||||
}
|
||||
|
||||
public string SelectedColorCopyHelperText
|
||||
{
|
||||
get { return (string)GetValue(SelectedColorCopyHelperTextProperty); }
|
||||
set { SetValue(SelectedColorCopyHelperTextProperty, value); }
|
||||
}
|
||||
|
||||
public ColorFormatControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -68,7 +77,10 @@ namespace ColorPicker.Controls
|
||||
|
||||
private static void SelectedColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((ColorFormatControl)d).ColorTextRepresentationTextBlock.Text = ((ColorFormatControl)d).ColorFormatModel.Convert((Color)e.NewValue);
|
||||
var self = (ColorFormatControl)d;
|
||||
var colorText = self.ColorFormatModel.Convert((Color)e.NewValue);
|
||||
self.ColorTextRepresentationTextBlock.Text = colorText;
|
||||
self.SelectedColorCopyHelperText = string.Format(CultureInfo.InvariantCulture, "{0} {1}", self.ColorFormatModel.FormatName, colorText);
|
||||
}
|
||||
|
||||
private static void ColorFormatModelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
|
||||
@@ -239,11 +239,11 @@
|
||||
ShadowDepth="2" />
|
||||
</Grid.Effect>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="36" />
|
||||
<ColumnDefinition Width="36" />
|
||||
<ColumnDefinition Width="46" />
|
||||
<ColumnDefinition Width="46" />
|
||||
<ColumnDefinition Width="165" />
|
||||
<ColumnDefinition Width="36" />
|
||||
<ColumnDefinition Width="36" />
|
||||
<ColumnDefinition Width="46" />
|
||||
<ColumnDefinition Width="46" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="colorVariation1Button"
|
||||
@@ -288,7 +288,7 @@
|
||||
Background="Red"
|
||||
Width="165"
|
||||
Height="48"
|
||||
Margin="72,0,0,0"
|
||||
Margin="92,0,0,0"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Selected_color}"
|
||||
AutomationProperties.HelpText="{x:Static p:Resources.Selected_color_helptext}"
|
||||
ToolTipService.ToolTip="{x:Static p:Resources.Selected_color_tooltip}"
|
||||
@@ -398,7 +398,7 @@
|
||||
Width="72"
|
||||
ui:ControlHelper.CornerRadius="2,0,0,2"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Red_value}"
|
||||
ValueChanged="RGBNumberBox_ValueChanged"
|
||||
TextBoxBase.TextChanged="RGBNumberBox_TextChanged"
|
||||
Minimum="0"
|
||||
Maximum="255" />
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
Width="72"
|
||||
ui:ControlHelper.CornerRadius="0"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Green_value}"
|
||||
ValueChanged="RGBNumberBox_ValueChanged"
|
||||
TextBoxBase.TextChanged="RGBNumberBox_TextChanged"
|
||||
Minimum="0"
|
||||
Maximum="255" />
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
Margin="-1,0,0,0"
|
||||
ui:ControlHelper.CornerRadius="0,2,2,0"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Blue_value}"
|
||||
ValueChanged="RGBNumberBox_ValueChanged"
|
||||
TextBoxBase.TextChanged="RGBNumberBox_TextChanged"
|
||||
Minimum="0"
|
||||
Maximum="255" />
|
||||
</StackPanel>
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using ColorPicker.Helpers;
|
||||
using ModernWpf.Controls;
|
||||
using ModernWpf.Controls.Primitives;
|
||||
|
||||
namespace ColorPicker.Controls
|
||||
@@ -190,13 +191,7 @@ namespace ColorPicker.Controls
|
||||
{
|
||||
_isCollapsed = false;
|
||||
|
||||
var opacityAppear = new DoubleAnimation(1.0, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
opacityAppear.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resize = new DoubleAnimation(400, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
resize.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resizeColor = new DoubleAnimation(309, new Duration(TimeSpan.FromMilliseconds(250)));
|
||||
var resizeColor = new DoubleAnimation(349, new Duration(TimeSpan.FromMilliseconds(250)));
|
||||
resizeColor.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var moveColor = new ThicknessAnimation(new Thickness(0), new Duration(TimeSpan.FromMilliseconds(250)));
|
||||
@@ -216,16 +211,10 @@ namespace ColorPicker.Controls
|
||||
{
|
||||
_isCollapsed = true;
|
||||
|
||||
var opacityAppear = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
opacityAppear.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resize = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
resize.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resizeColor = new DoubleAnimation(165, new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
resizeColor.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var moveColor = new ThicknessAnimation(new Thickness(72, 0, 0, 0), new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
var moveColor = new ThicknessAnimation(new Thickness(92, 0, 0, 0), new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
moveColor.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
ControlHelper.SetCornerRadius(CurrentColorButton, new CornerRadius(0));
|
||||
@@ -297,22 +286,6 @@ namespace ColorPicker.Controls
|
||||
_ignoreGradientsChanges = false;
|
||||
}
|
||||
|
||||
private static Point GetMousePositionWithinGrid(Border border)
|
||||
{
|
||||
var pos = System.Windows.Input.Mouse.GetPosition(border);
|
||||
if (pos.X < 0)
|
||||
{
|
||||
pos.X = 0;
|
||||
}
|
||||
|
||||
if (pos.X > border.Width)
|
||||
{
|
||||
pos.X = border.Width;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
private void HexCode_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
var newValue = (sender as TextBox).Text;
|
||||
@@ -336,21 +309,6 @@ namespace ColorPicker.Controls
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CA1801 // Review unused parameters
|
||||
private void RGBNumberBox_ValueChanged(ModernWpf.Controls.NumberBox sender, ModernWpf.Controls.NumberBoxValueChangedEventArgs args)
|
||||
#pragma warning restore CA1801 // Review unused parameters
|
||||
{
|
||||
if (!_ignoreRGBChanges)
|
||||
{
|
||||
var r = byte.Parse(RNumberBox.Text, CultureInfo.InvariantCulture);
|
||||
var g = byte.Parse(GNumberBox.Text, CultureInfo.InvariantCulture);
|
||||
var b = byte.Parse(BNumberBox.Text, CultureInfo.InvariantCulture);
|
||||
_ignoreRGBChanges = true;
|
||||
SetColorFromTextBoxes(System.Drawing.Color.FromArgb(r, g, b));
|
||||
_ignoreRGBChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetColorFromTextBoxes(System.Drawing.Color color)
|
||||
{
|
||||
if (!_ignoreGradientsChanges)
|
||||
@@ -377,6 +335,65 @@ namespace ColorPicker.Controls
|
||||
{
|
||||
(sender as System.Windows.Controls.TextBox).SelectAll();
|
||||
}
|
||||
|
||||
private void RGBNumberBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (!_ignoreRGBChanges)
|
||||
{
|
||||
var numberBox = sender as NumberBox;
|
||||
var r = numberBox.Name == "RNumberBox" ? GetValueFromNumberBox(numberBox) : (byte)RNumberBox.Value;
|
||||
var g = numberBox.Name == "GNumberBox" ? GetValueFromNumberBox(numberBox) : (byte)GNumberBox.Value;
|
||||
var b = numberBox.Name == "BNumberBox" ? GetValueFromNumberBox(numberBox) : (byte)BNumberBox.Value;
|
||||
_ignoreRGBChanges = true;
|
||||
SetColorFromTextBoxes(System.Drawing.Color.FromArgb(r, g, b));
|
||||
_ignoreRGBChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// NumberBox provides value only after it has been validated - happens after pressing enter or leaving this control.
|
||||
/// However, we need to get value immediately after the underlying textbox value changes
|
||||
/// </summary>
|
||||
/// <param name="numberBox">numberBox control which value we want to get</param>
|
||||
/// <returns>Validated value as per numberbox conditions, if content is invalid it returns previous value</returns>
|
||||
private static byte GetValueFromNumberBox(NumberBox numberBox)
|
||||
{
|
||||
var internalTextBox = GetChildOfType<TextBox>(numberBox);
|
||||
var parsedValue = numberBox.NumberFormatter.ParseDouble(internalTextBox.Text);
|
||||
if (parsedValue != null)
|
||||
{
|
||||
var parsedValueByte = (byte)parsedValue;
|
||||
if (parsedValueByte >= numberBox.Minimum && parsedValueByte <= numberBox.Maximum)
|
||||
{
|
||||
return parsedValueByte;
|
||||
}
|
||||
}
|
||||
|
||||
// not valid input, return previous value
|
||||
return (byte)numberBox.Value;
|
||||
}
|
||||
|
||||
public static T GetChildOfType<T>(DependencyObject depObj)
|
||||
where T : DependencyObject
|
||||
{
|
||||
if (depObj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(depObj, i);
|
||||
|
||||
var result = (child as T) ?? GetChildOfType<T>(child);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable SA1402 // File may only contain a single type
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.ComponentModel.Composition;
|
||||
using System.Windows;
|
||||
using ColorPicker.Settings;
|
||||
using ColorPicker.ViewModelContracts;
|
||||
using Microsoft.PowerToys.Common.UI;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
|
||||
namespace ColorPicker.Helpers
|
||||
@@ -134,6 +135,7 @@ namespace ColorPicker.Helpers
|
||||
_colorEditorWindow = new ColorEditorWindow(this);
|
||||
_colorEditorWindow.Content = _colorEditorViewModel;
|
||||
_colorEditorViewModel.OpenColorPickerRequested += ColorEditorViewModel_OpenColorPickerRequested;
|
||||
_colorEditorViewModel.OpenSettingsRequested += ColorEditorViewModel_OpenSettingsRequested;
|
||||
_colorEditorViewModel.OpenColorPickerRequested += (object sender, EventArgs e) =>
|
||||
{
|
||||
SessionEventHelper.Event.EditorColorPickerOpened = true;
|
||||
@@ -183,5 +185,10 @@ namespace ColorPicker.Helpers
|
||||
|
||||
_colorEditorWindow.Hide();
|
||||
}
|
||||
|
||||
private void ColorEditorViewModel_OpenSettingsRequested(object sender, EventArgs e)
|
||||
{
|
||||
SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.ColorPicker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace ColorPicker.Helpers
|
||||
internal static class ColorHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert a given <see cref="Color"/> to a CYMK color (cyan, magenta, yellow, black key)
|
||||
/// Convert a given <see cref="Color"/> to a CMYK color (cyan, magenta, yellow, black key)
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> to convert</param>
|
||||
/// <returns>The cyan[0..1], magenta[0..1], yellow[0..1] and black key[0..1] of the converted color</returns>
|
||||
@@ -139,6 +139,77 @@ namespace ColorPicker.Helpers
|
||||
return (GetNaturalColorFromHue(color.GetHue()), min, 1 - max);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a given <see cref="Color"/> to a CIE LAB color (LAB)
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> to convert</param>
|
||||
/// <returns>The lightness [0..100] and two chromaticities [-128..127]</returns>
|
||||
internal static (double lightness, double chromaticityA, double chromaticityB) ConvertToCIELABColor(Color color)
|
||||
{
|
||||
var xyz = ConvertToCIEXYZColor(color);
|
||||
var lab = GetCIELABColorFromCIEXYZ(xyz.x, xyz.y, xyz.z);
|
||||
|
||||
return lab;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a given <see cref="Color"/> to a CIE XYZ color (XYZ)
|
||||
/// The constants of the formula used come from this wikipedia page:
|
||||
/// https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation_(sRGB_to_CIE_XYZ)
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> to convert</param>
|
||||
/// <returns>The X [0..1], Y [0..1] and Z [0..1]</returns>
|
||||
internal static (double x, double y, double z) ConvertToCIEXYZColor(Color color)
|
||||
{
|
||||
double r = color.R / 255d;
|
||||
double g = color.G / 255d;
|
||||
double b = color.B / 255d;
|
||||
|
||||
// inverse companding, gamma correction must be undone
|
||||
double rLinear = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : (r / 12.92);
|
||||
double gLinear = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : (g / 12.92);
|
||||
double bLinear = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : (b / 12.92);
|
||||
|
||||
return (
|
||||
(rLinear * 0.4124) + (gLinear * 0.3576) + (bLinear * 0.1805),
|
||||
(rLinear * 0.2126) + (gLinear * 0.7152) + (bLinear * 0.0722),
|
||||
(rLinear * 0.0193) + (gLinear * 0.1192) + (bLinear * 0.9505)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a CIE XYZ color <see cref="double"/> to a CIE LAB color (LAB)
|
||||
/// The constants of the formula used come from this wikipedia page:
|
||||
/// https://en.wikipedia.org/wiki/CIELAB_color_space#Converting_between_CIELAB_and_CIEXYZ_coordinates
|
||||
/// </summary>
|
||||
/// <param name="x">The <see cref="x"/> represents a mix of the three CIE RGB curves</param>
|
||||
/// <param name="y">The <see cref="y"/> represents the luminance</param>
|
||||
/// <param name="z">The <see cref="z"/> is quasi-equal to blue (of CIE RGB)</param>
|
||||
/// <returns>The lightness [0..100] and two chromaticities [-128..127]</returns>
|
||||
private static (double lightness, double chromaticityA, double chromaticityB)
|
||||
GetCIELABColorFromCIEXYZ(double x, double y, double z)
|
||||
{
|
||||
// These values are based on the D65 Illuminant
|
||||
x = x * 100 / 95.0489;
|
||||
y = y * 100 / 100.0;
|
||||
z = z * 100 / 108.8840;
|
||||
|
||||
// XYZ to CIELab transformation
|
||||
double delta = 6d / 29;
|
||||
double m = (1d / 3) * Math.Pow(delta, -2);
|
||||
double t = Math.Pow(delta, 3);
|
||||
|
||||
double fx = (x > t) ? Math.Pow(x, 1.0 / 3.0) : (x * m) + (16.0 / 116.0);
|
||||
double fy = (y > t) ? Math.Pow(y, 1.0 / 3.0) : (y * m) + (16.0 / 116.0);
|
||||
double fz = (z > t) ? Math.Pow(z, 1.0 / 3.0) : (z * m) + (16.0 / 116.0);
|
||||
|
||||
double l = (116 * fy) - 16;
|
||||
double a = 500 * (fx - fy);
|
||||
double b = 200 * (fy - fz);
|
||||
|
||||
return (l, a, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the natural color for the given hue value
|
||||
/// </summary>
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace ColorPicker.Helpers
|
||||
internal static string GetStringRepresentation(Color color, ColorRepresentationType colorRepresentationType)
|
||||
=> colorRepresentationType switch
|
||||
{
|
||||
ColorRepresentationType.CMYK => ColorToCYMK(color),
|
||||
ColorRepresentationType.CMYK => ColorToCMYK(color),
|
||||
ColorRepresentationType.HEX => ColorToHex(color),
|
||||
ColorRepresentationType.HSB => ColorToHSB(color),
|
||||
ColorRepresentationType.HSI => ColorToHSI(color),
|
||||
@@ -44,17 +44,19 @@ namespace ColorPicker.Helpers
|
||||
ColorRepresentationType.HWB => ColorToHWB(color),
|
||||
ColorRepresentationType.NCol => ColorToNCol(color),
|
||||
ColorRepresentationType.RGB => ColorToRGB(color),
|
||||
ColorRepresentationType.CIELAB => ColorToCIELAB(color),
|
||||
ColorRepresentationType.CIEXYZ => ColorToCIEXYZ(color),
|
||||
|
||||
// Fall-back value, when "_userSettings.CopiedColorRepresentation.Value" is incorrect
|
||||
_ => ColorToHex(color),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Return a <see cref="string"/> representation of a CYMK color
|
||||
/// Return a <see cref="string"/> representation of a CMYK color
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> for the CYMK color presentation</param>
|
||||
/// <returns>A <see cref="string"/> representation of a CYMK color</returns>
|
||||
private static string ColorToCYMK(Color color)
|
||||
/// <param name="color">The <see cref="Color"/> for the CMYK color presentation</param>
|
||||
/// <returns>A <see cref="string"/> representation of a CMYK color</returns>
|
||||
private static string ColorToCMYK(Color color)
|
||||
{
|
||||
var (cyan, magenta, yellow, blackKey) = ColorHelper.ConvertToCMYKColor(color);
|
||||
|
||||
@@ -75,7 +77,7 @@ namespace ColorPicker.Helpers
|
||||
/// <param name="color">The see cref="Color"/> for the hexadecimal presentation</param>
|
||||
/// <returns>A hexadecimal <see cref="string"/> representation of a RGB color</returns>
|
||||
private static string ColorToHex(Color color)
|
||||
=> $"#{color.R.ToString("X2", CultureInfo.InvariantCulture)}"
|
||||
=> $"{color.R.ToString("X2", CultureInfo.InvariantCulture)}"
|
||||
+ $"{color.G.ToString("X2", CultureInfo.InvariantCulture)}"
|
||||
+ $"{color.B.ToString("X2", CultureInfo.InvariantCulture)}";
|
||||
|
||||
@@ -191,11 +193,46 @@ namespace ColorPicker.Helpers
|
||||
/// <summary>
|
||||
/// Return a <see cref="string"/> representation of a RGB color
|
||||
/// </summary>
|
||||
/// <param name="color">The see cref="Color"/> for the RGB color presentation</param>
|
||||
/// <param name="color">The <see cref="Color"/> for the RGB color presentation</param>
|
||||
/// <returns>A <see cref="string"/> representation of a RGB color</returns>
|
||||
private static string ColorToRGB(Color color)
|
||||
=> $"rgb({color.R.ToString(CultureInfo.InvariantCulture)}"
|
||||
+ $", {color.G.ToString(CultureInfo.InvariantCulture)}"
|
||||
+ $", {color.B.ToString(CultureInfo.InvariantCulture)})";
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string"/> representation of a CIE LAB color
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> for the CIE LAB color presentation</param>
|
||||
/// <returns>A <see cref="string"/> representation of a CIE LAB color</returns>
|
||||
private static string ColorToCIELAB(Color color)
|
||||
{
|
||||
var (lightness, chromaticityA, chromaticityB) = ColorHelper.ConvertToCIELABColor(color);
|
||||
lightness = Math.Round(lightness, 2);
|
||||
chromaticityA = Math.Round(chromaticityA, 2);
|
||||
chromaticityB = Math.Round(chromaticityB, 2);
|
||||
|
||||
return $"CIELab({lightness.ToString(CultureInfo.InvariantCulture)}" +
|
||||
$", {chromaticityA.ToString(CultureInfo.InvariantCulture)}" +
|
||||
$", {chromaticityB.ToString(CultureInfo.InvariantCulture)})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string"/> representation of a CIE XYZ color
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> for the CIE XYZ color presentation</param>
|
||||
/// <returns>A <see cref="string"/> representation of a CIE XYZ color</returns>
|
||||
private static string ColorToCIEXYZ(Color color)
|
||||
{
|
||||
var (x, y, z) = ColorHelper.ConvertToCIEXYZColor(color);
|
||||
|
||||
x = Math.Round(x * 100, 4);
|
||||
y = Math.Round(y * 100, 4);
|
||||
z = Math.Round(z * 100, 4);
|
||||
|
||||
return $"xyz({x.ToString(CultureInfo.InvariantCulture)}" +
|
||||
$", {y.ToString(CultureInfo.InvariantCulture)}" +
|
||||
$", {z.ToString(CultureInfo.InvariantCulture)})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace ColorPicker
|
||||
{
|
||||
@@ -13,6 +15,9 @@ namespace ColorPicker
|
||||
// will have to rename
|
||||
public static class NativeMethods
|
||||
{
|
||||
private const int GWL_STYLE = -16;
|
||||
private const int WS_POPUP = 1 << 31; // 0x80000000
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Interop")]
|
||||
public const int WH_KEYBOARD_LL = 13;
|
||||
@@ -168,5 +173,17 @@ namespace ColorPicker
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
internal static extern int GetWindowText(int hwnd, StringBuilder text, int count);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
|
||||
internal static void SetPopupStyle(Window win)
|
||||
{
|
||||
var hwnd = new WindowInteropHelper(win).Handle;
|
||||
_ = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_POPUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,12 @@ namespace ColorPicker.ViewModelContracts
|
||||
{
|
||||
event EventHandler OpenColorPickerRequested;
|
||||
|
||||
event EventHandler OpenSettingsRequested;
|
||||
|
||||
ICommand OpenColorPickerCommand { get; }
|
||||
|
||||
ICommand OpenSettingsCommand { get; }
|
||||
|
||||
ICommand RemoveColorCommand { get; }
|
||||
|
||||
ObservableCollection<ColorFormatModel> ColorRepresentations { get; }
|
||||
|
||||