Compare commits
1 Commits
dev/mjolle
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25b8b2d0c7 |
13
.github/actions/spell-check/allow/code.txt
vendored
@@ -51,7 +51,6 @@ resw
|
||||
resx
|
||||
srt
|
||||
Stereolithography
|
||||
taskmgr
|
||||
terabyte
|
||||
UYVY
|
||||
xbf
|
||||
@@ -337,10 +336,6 @@ MRUCMPPROC
|
||||
MRUINFO
|
||||
REGSTR
|
||||
|
||||
#Xaml
|
||||
NVI
|
||||
Storyboards
|
||||
|
||||
# Misc Win32 APIs and PInvokes
|
||||
DEFAULTTONEAREST
|
||||
INVOKEIDLIST
|
||||
@@ -365,10 +360,7 @@ FILESYSONLY
|
||||
URLIS
|
||||
WAITTIMEOUT
|
||||
DEFAULTTONEAREST
|
||||
DWRITE
|
||||
LWIN
|
||||
VCENTER
|
||||
VREDRAW
|
||||
|
||||
|
||||
# COM/WinRT interface prefixes and type fragments
|
||||
BAlt
|
||||
@@ -432,6 +424,3 @@ SHELLEXPERIENCEHOST
|
||||
SHELLHOST
|
||||
STARTMENUEXPERIENCEHOST
|
||||
WIDGETBOARD
|
||||
|
||||
# URIs
|
||||
actioncenter
|
||||
|
||||
212
.github/actions/spell-check/allow/zoomit.txt
vendored
@@ -1,51 +1,23 @@
|
||||
accelscroll
|
||||
acq
|
||||
ADDTO
|
||||
ADDTOOL
|
||||
adr
|
||||
Adr
|
||||
ALWAYSTIP
|
||||
APPLYTOSUBMENUS
|
||||
ARCHMASK
|
||||
archs
|
||||
AUDCLNT
|
||||
autocorr
|
||||
avx
|
||||
axisdefer
|
||||
axisflip
|
||||
axisstart
|
||||
backlight
|
||||
BEOS
|
||||
bfi
|
||||
BFIN
|
||||
bfly
|
||||
BGRX
|
||||
bitmaps
|
||||
bitrev
|
||||
blits
|
||||
Borgerding
|
||||
Borland
|
||||
breakc
|
||||
BREAKSCR
|
||||
BUFFERFLAGS
|
||||
bugzilla
|
||||
Cands
|
||||
capturepath
|
||||
cbs
|
||||
centiseconds
|
||||
cexp
|
||||
cfx
|
||||
cfy
|
||||
cgem
|
||||
cifx
|
||||
cify
|
||||
CLASSW
|
||||
coeffs
|
||||
colblocks
|
||||
constantbuffer
|
||||
coprime
|
||||
cpuid
|
||||
cpx
|
||||
CREATEDIBSECTION
|
||||
CREATESTRUCTW
|
||||
crossfades
|
||||
@@ -56,216 +28,109 @@ CTLCOLORDLG
|
||||
CTLCOLOREDIT
|
||||
CTLCOLORLISTBOX
|
||||
CTrim
|
||||
CVTEPI
|
||||
DBuffer
|
||||
dcl
|
||||
dct
|
||||
ddx
|
||||
ddy
|
||||
Deinterleave
|
||||
denoise
|
||||
denoised
|
||||
DEVSOURCE
|
||||
DFCS
|
||||
DIVSCALAR
|
||||
DJGPP
|
||||
dlg
|
||||
dlu
|
||||
dnn
|
||||
DONTCARE
|
||||
downsample
|
||||
DRAWITEM
|
||||
DRAWITEMSTRUCT
|
||||
droppedband
|
||||
Droppedband
|
||||
DSPs
|
||||
dsum
|
||||
dupburst
|
||||
dupsegments
|
||||
DWLP
|
||||
eband
|
||||
ebx
|
||||
ECX
|
||||
EDITCONTROL
|
||||
EDSP
|
||||
emmintrin
|
||||
EMX
|
||||
ENABLEHOOK
|
||||
endloop
|
||||
ENDOFSTREAM
|
||||
ener
|
||||
enh
|
||||
ettings
|
||||
expectedlock
|
||||
expf
|
||||
fabs
|
||||
fabsf
|
||||
facbuf
|
||||
fastscroll
|
||||
FDE
|
||||
ffast
|
||||
FIXDIV
|
||||
floorf
|
||||
fmadd
|
||||
fout
|
||||
fstride
|
||||
fxc
|
||||
GETCHANNELRECT
|
||||
GETCHECK
|
||||
GETCOUNT
|
||||
GETDISPINFO
|
||||
GETSCREENSAVEACTIVE
|
||||
GETSCREENSAVETIMEOUT
|
||||
GETTHUMBRECT
|
||||
GIFs
|
||||
glu
|
||||
groupshared
|
||||
gru
|
||||
hcfdark
|
||||
hcfwhitespace
|
||||
hlsl
|
||||
Hsieh
|
||||
hstride
|
||||
HTBOTTOMRIGHT
|
||||
HTHEME
|
||||
htol
|
||||
ICONINFORMATION
|
||||
ICONWARNING
|
||||
idct
|
||||
IDIn
|
||||
IDISHWND
|
||||
ifft
|
||||
igc
|
||||
ilog
|
||||
imad
|
||||
imax
|
||||
imin
|
||||
immintrin
|
||||
Inj
|
||||
interp
|
||||
inttypes
|
||||
ishl
|
||||
itof
|
||||
jumprecover
|
||||
kfft
|
||||
kheight
|
||||
kissfft
|
||||
KSDATAFORMAT
|
||||
ksize
|
||||
ktime
|
||||
lastg
|
||||
latestcapture
|
||||
ldx
|
||||
LEFTNOWORDWRAP
|
||||
legitjumps
|
||||
lenmem
|
||||
letterbox
|
||||
lld
|
||||
lldx
|
||||
llu
|
||||
llums
|
||||
logfont
|
||||
lookback
|
||||
lpc
|
||||
lpcnet
|
||||
LPNMHDR
|
||||
LPNMTTDISPINFO
|
||||
lround
|
||||
lte
|
||||
luma
|
||||
Luma
|
||||
maj
|
||||
manualdrop
|
||||
maskcache
|
||||
maxabs
|
||||
maxcorr
|
||||
MAXFACTORS
|
||||
maxperiod
|
||||
maxstep
|
||||
memalign
|
||||
memid
|
||||
memneeded
|
||||
MENUINFO
|
||||
MFSTARTUP
|
||||
mfxhw
|
||||
mic
|
||||
middledrop
|
||||
minperiod
|
||||
MIPSr
|
||||
MJPEG
|
||||
MMRESULT
|
||||
momentumreversal
|
||||
movc
|
||||
mrate
|
||||
mrt
|
||||
MULBYSCALAR
|
||||
MULC
|
||||
MWERKS
|
||||
mycfg
|
||||
narrowstrip
|
||||
nbak
|
||||
nbytes
|
||||
ncapture
|
||||
nchw
|
||||
ncm
|
||||
nduplicates
|
||||
nfft
|
||||
NHWC
|
||||
niterations
|
||||
nmonitor
|
||||
nnet
|
||||
NONCLIENTMETRICS
|
||||
NONOTIFY
|
||||
nonvle
|
||||
normf
|
||||
nredraw
|
||||
nstop
|
||||
nsubpixel
|
||||
ntorn
|
||||
numthreads
|
||||
nvw
|
||||
Octasic
|
||||
osc
|
||||
OSCE
|
||||
ovflw
|
||||
OWNERDRAW
|
||||
PBGRA
|
||||
periodictrap
|
||||
pfdc
|
||||
pillarbox
|
||||
pfdc
|
||||
playhead
|
||||
pnmh
|
||||
pointerreuse
|
||||
PPW
|
||||
prereq
|
||||
PSHR
|
||||
pstdint
|
||||
PSWA
|
||||
pwfx
|
||||
QCONST
|
||||
qpc
|
||||
Qpc
|
||||
quantums
|
||||
qweight
|
||||
RCSEGMODEL
|
||||
RCZOOMITSCR
|
||||
readback
|
||||
READERF
|
||||
realcapture
|
||||
REFKNOWNFOLDERID
|
||||
relu
|
||||
reposted
|
||||
RETURNCMD
|
||||
rnn
|
||||
rnnoise
|
||||
rotateleft
|
||||
rsqrt
|
||||
rtcd
|
||||
RTEXT
|
||||
RTH
|
||||
rtvs
|
||||
SCALEIN
|
||||
SCALEOUT
|
||||
SCREENSAVE
|
||||
SCRNSAVE
|
||||
SCRNSAVECONFIGURE
|
||||
@@ -273,80 +138,43 @@ scrnsavw
|
||||
Scrnsavw
|
||||
scrollramp
|
||||
SCROLLSIZEGRIP
|
||||
selfie
|
||||
selftest
|
||||
SETBARCOLOR
|
||||
SETBKCOLOR
|
||||
SETDEFID
|
||||
SETRECT
|
||||
SETSCREENSAVETIMEOUT
|
||||
SETTIPSIDE
|
||||
sgem
|
||||
sgemv
|
||||
sgv
|
||||
SHAREMODE
|
||||
SHAREVIOLATION
|
||||
shortlist
|
||||
simde
|
||||
siv
|
||||
slowthenfast
|
||||
smallstart
|
||||
SNIPOCR
|
||||
softmax
|
||||
sqrtf
|
||||
SROUND
|
||||
srvs
|
||||
ssi
|
||||
startuprecovery
|
||||
stdint
|
||||
stf
|
||||
stopafter
|
||||
STREAMFLAGS
|
||||
SUBFROM
|
||||
subias
|
||||
submix
|
||||
sxx
|
||||
sxy
|
||||
symbian
|
||||
synthesising
|
||||
syy
|
||||
tallportal
|
||||
TBTS
|
||||
tci
|
||||
tcsicmp
|
||||
TEXTCALLBACK
|
||||
TEXTMETRIC
|
||||
tgsm
|
||||
THIRDPARTY
|
||||
tinystep
|
||||
tme
|
||||
toolbars
|
||||
TOOLINFO
|
||||
TRACKMOUSEEVENT
|
||||
TRIANGLELIST
|
||||
TTM
|
||||
TTN
|
||||
TWID
|
||||
UADD
|
||||
uav
|
||||
uavs
|
||||
uge
|
||||
Unadvise
|
||||
upscaled
|
||||
upscales
|
||||
USUB
|
||||
utof
|
||||
vad
|
||||
vaddq
|
||||
vaddvq
|
||||
valgrind
|
||||
Valin
|
||||
vandq
|
||||
vblank
|
||||
vcgeq
|
||||
vdup
|
||||
vectorizer
|
||||
VERTID
|
||||
VIDCAP
|
||||
vld
|
||||
vle
|
||||
@@ -356,7 +184,6 @@ vminq
|
||||
vmlal
|
||||
vmull
|
||||
vqaddq
|
||||
VSHR
|
||||
vshrn
|
||||
vsntprintf
|
||||
vsnwprintf
|
||||
@@ -367,9 +194,7 @@ WAVEFORMATEXTENSIBLE
|
||||
webcam
|
||||
Webcam
|
||||
webcams
|
||||
Wextra
|
||||
wfopen
|
||||
WGC
|
||||
wideportal
|
||||
wil
|
||||
WMU
|
||||
@@ -377,46 +202,11 @@ wrapjump
|
||||
wtol
|
||||
WTSSESSION
|
||||
WTSUn
|
||||
wxyz
|
||||
xchg
|
||||
xcorr
|
||||
XEnd
|
||||
Xfl
|
||||
Xiang
|
||||
Xiph
|
||||
xmmintrin
|
||||
xptr
|
||||
xshift
|
||||
XStart
|
||||
XStep
|
||||
xxxy
|
||||
xxyx
|
||||
xxyz
|
||||
xyw
|
||||
xywx
|
||||
xyxx
|
||||
xyxz
|
||||
xyzw
|
||||
xyzx
|
||||
xzwx
|
||||
xzxx
|
||||
Yfl
|
||||
YInternal
|
||||
yshift
|
||||
YUV
|
||||
yyyx
|
||||
yyzw
|
||||
yzw
|
||||
yzwy
|
||||
yzyy
|
||||
Zhou
|
||||
Zhu
|
||||
ZMBS
|
||||
zncc
|
||||
Zncc
|
||||
ZNCC
|
||||
zrh
|
||||
zwzz
|
||||
zyzw
|
||||
zzwz
|
||||
zzzw
|
||||
|
||||
8
.github/actions/spell-check/excludes.txt
vendored
@@ -105,13 +105,13 @@
|
||||
^src/common/ManagedCommon/ColorFormatHelper\.cs$
|
||||
^src/common/notifications/BackgroundActivatorDLL/cpp\.hint$
|
||||
^src/common/sysinternals/Eula/
|
||||
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherComparisonTests.cs$
|
||||
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherDiacriticsTests.cs$
|
||||
^src/modules/cmdpal/doc/initial-sdk-spec/list-elements-mock-002\.pdn$
|
||||
^doc/devdocs/modules/cmdpal/initial-sdk-spec/list-elements-mock-002\.pdn$
|
||||
^src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownImagesPage\.cs$
|
||||
^src/modules/cmdpal/Microsoft\.CmdPal\.UI/Settings/InternalPage\.SampleData\.cs$
|
||||
^src/modules/cmdpal/Tests/Microsoft\.CmdPal\.Common\.UnitTests/.*\.TestData\.cs$
|
||||
^src/modules/cmdpal/Tests/Microsoft\.CmdPal\.Common\.UnitTests/Text/.*\.cs$
|
||||
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherComparisonTests.cs$
|
||||
^src/modules/cmdpal/Tests/Microsoft\.CommandPalette\.Extensions\.Toolkit\.UnitTests/FuzzyMatcherDiacriticsTests.cs$
|
||||
^src/modules/colorPicker/ColorPickerUI/Shaders/GridShader\.cso$
|
||||
^src/modules/launcher/Plugins/Microsoft\.PowerToys\.Run\.Plugin\.TimeDate/Properties/
|
||||
^src/modules/MouseUtils/MouseJumpUI/MainForm\.resx$
|
||||
@@ -135,8 +135,6 @@
|
||||
^src/modules/previewpane/SvgPreviewHandler/SvgHTMLPreviewGenerator\.cs$
|
||||
^src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag\.txt$
|
||||
^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
|
||||
^src/modules/ZoomIt/ZoomIt/rnnoise/
|
||||
^src/modules/ZoomIt/ZoomIt/selfie_segmentation\.onnx$
|
||||
^src/modules/ZoomIt/ZoomIt/ZoomIt\.idc$
|
||||
^src/Monaco/
|
||||
^tools/project_template/ModuleTemplate/resource\.h$
|
||||
|
||||
73
.github/actions/spell-check/expect.txt
vendored
@@ -24,8 +24,7 @@ advancedpaste
|
||||
advapi
|
||||
advfirewall
|
||||
AFeature
|
||||
affordance
|
||||
afterfx
|
||||
affordances
|
||||
AFX
|
||||
agentskills
|
||||
AGGREGATABLE
|
||||
@@ -63,7 +62,6 @@ APPEXECLINK
|
||||
appext
|
||||
apphost
|
||||
APPLICATIONFRAMEHOST
|
||||
Applocal
|
||||
appmanifest
|
||||
APPMODEL
|
||||
APPNAME
|
||||
@@ -82,7 +80,6 @@ ARPPRODUCTICON
|
||||
ARRAYSIZE
|
||||
ARROWKEYS
|
||||
arrowshape
|
||||
artboard
|
||||
ARTIFACTSTAGINGDIRECTORY
|
||||
asf
|
||||
Ashcraft
|
||||
@@ -113,12 +110,14 @@ azman
|
||||
azureaiinference
|
||||
azureinference
|
||||
azureopenai
|
||||
Backlight
|
||||
backticks
|
||||
Badflags
|
||||
Badmode
|
||||
Badparam
|
||||
bbwe
|
||||
BCIE
|
||||
bck
|
||||
BESTEFFORT
|
||||
bezelled
|
||||
bhid
|
||||
@@ -157,7 +156,6 @@ breadcrumb
|
||||
Browsable
|
||||
BROWSEINFO
|
||||
bsd
|
||||
BSOD
|
||||
bthprops
|
||||
bti
|
||||
BTNFACE
|
||||
@@ -165,7 +163,6 @@ bugreport
|
||||
bugreportfile
|
||||
BUILDARCH
|
||||
BUILDNUMBER
|
||||
buildsystems
|
||||
buildtransitive
|
||||
builttoroam
|
||||
BUNDLEINFO
|
||||
@@ -203,7 +200,6 @@ checkmarks
|
||||
CHILDACTIVATE
|
||||
CHILDWINDOW
|
||||
CHOOSEFONT
|
||||
chu
|
||||
CIBUILD
|
||||
cidl
|
||||
CIELCh
|
||||
@@ -226,7 +222,6 @@ CLIPSIBLINGS
|
||||
closesocket
|
||||
clp
|
||||
CLSCTX
|
||||
CLSIDs
|
||||
clsids
|
||||
Clusion
|
||||
cmder
|
||||
@@ -337,7 +332,6 @@ dacl
|
||||
DAffine
|
||||
DAFFINETRANSFORM
|
||||
datareader
|
||||
Datasheet
|
||||
datatracker
|
||||
Dayof
|
||||
dbcc
|
||||
@@ -374,7 +368,6 @@ DEFPUSHBUTTON
|
||||
deinitialization
|
||||
DELA
|
||||
DELD
|
||||
deld
|
||||
DELETEDKEYIMAGE
|
||||
DELETESCANS
|
||||
DEMOTYPE
|
||||
@@ -399,7 +392,6 @@ DEVMODE
|
||||
DEVMODEW
|
||||
DEVNODES
|
||||
devpal
|
||||
devpackages
|
||||
DEVTYP
|
||||
dfx
|
||||
DIALOGEX
|
||||
@@ -443,9 +435,9 @@ drawingcolor
|
||||
dreamsofameaningfullife
|
||||
drivedetectionwarning
|
||||
DROPFILES
|
||||
DSPDLOG
|
||||
DSTINVERT
|
||||
DString
|
||||
DSVG
|
||||
dto
|
||||
DUMMYUNIONNAME
|
||||
dumpbin
|
||||
@@ -465,12 +457,13 @@ DWMNCRENDERINGCHANGED
|
||||
Dwmp
|
||||
DWMSENDICONICLIVEPREVIEWBITMAP
|
||||
DWMSENDICONICTHUMBNAIL
|
||||
dwmwa
|
||||
dwmwcp
|
||||
DWMWA
|
||||
DWMWCP
|
||||
DWMWINDOWATTRIBUTE
|
||||
DWMWINDOWMAXIMIZEDCHANGE
|
||||
DWORDLONG
|
||||
dworigin
|
||||
DWRITE
|
||||
dxgi
|
||||
Dxva
|
||||
eab
|
||||
@@ -508,6 +501,7 @@ ETDT
|
||||
etl
|
||||
etw
|
||||
eula
|
||||
eurochange
|
||||
eventvwr
|
||||
evt
|
||||
EWXFORCE
|
||||
@@ -548,7 +542,6 @@ FFFF
|
||||
fffffffzzz
|
||||
FFh
|
||||
Figma
|
||||
figma
|
||||
FILEEXPLORER
|
||||
fileexploreraddons
|
||||
fileexplorerpreview
|
||||
@@ -638,11 +631,9 @@ gpu
|
||||
grabandmove
|
||||
GRABANDMOVEMODULEINTERFACE
|
||||
gradians
|
||||
GRC
|
||||
grctlext
|
||||
GRGX
|
||||
Gridcustomlayout
|
||||
gridlines
|
||||
GSM
|
||||
gtm
|
||||
guiddata
|
||||
@@ -677,7 +668,6 @@ HDEVNOTIFY
|
||||
hdr
|
||||
HDROP
|
||||
hdwwiz
|
||||
Headered
|
||||
Helpline
|
||||
helptext
|
||||
hgdiobj
|
||||
@@ -730,7 +720,6 @@ hotkeys
|
||||
hotlight
|
||||
hotspot
|
||||
HPAINTBUFFER
|
||||
HPS
|
||||
HRAWINPUT
|
||||
HREDRAW
|
||||
hres
|
||||
@@ -794,7 +783,6 @@ imgflip
|
||||
inapp
|
||||
inbox
|
||||
INCONTACT
|
||||
indesign
|
||||
Indo
|
||||
inetcpl
|
||||
Infobar
|
||||
@@ -805,7 +793,6 @@ INITDIALOG
|
||||
INITGUID
|
||||
initialfile
|
||||
INITTOLOGFONTSTRUCT
|
||||
inkscape
|
||||
INLINEPREFIX
|
||||
inlines
|
||||
Inno
|
||||
@@ -849,7 +836,6 @@ issecret
|
||||
ISSEPARATOR
|
||||
issuecomment
|
||||
istep
|
||||
Italicise
|
||||
ith
|
||||
IUI
|
||||
IUWP
|
||||
@@ -857,7 +843,6 @@ IWIC
|
||||
jeli
|
||||
jfif
|
||||
jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi
|
||||
JIDEA
|
||||
jjw
|
||||
jobject
|
||||
JOBOBJECT
|
||||
@@ -869,7 +854,6 @@ Jsons
|
||||
jsonval
|
||||
jxr
|
||||
Kantai
|
||||
KBSC
|
||||
keybd
|
||||
KEYBDDATA
|
||||
KEYBDINPUT
|
||||
@@ -887,7 +871,6 @@ keynum
|
||||
keyremaps
|
||||
keyring
|
||||
keyvault
|
||||
kfull
|
||||
KILLFOCUS
|
||||
killrunner
|
||||
kmph
|
||||
@@ -991,12 +974,12 @@ lstrcmpi
|
||||
lstrcpyn
|
||||
lstrlen
|
||||
LTEXT
|
||||
LTM
|
||||
LTRREADING
|
||||
luid
|
||||
lusrmgr
|
||||
LVDS
|
||||
LWA
|
||||
LWIN
|
||||
LZero
|
||||
MAGTRANSFORM
|
||||
makeappx
|
||||
@@ -1046,7 +1029,6 @@ Mgmt
|
||||
Microwaved
|
||||
middleclickaction
|
||||
midl
|
||||
midtones
|
||||
mii
|
||||
MIIM
|
||||
mikeclayton
|
||||
@@ -1060,7 +1042,7 @@ MINMAXINFO
|
||||
minwindef
|
||||
Mip
|
||||
Miracast
|
||||
miracast
|
||||
MIRACAST
|
||||
mkdn
|
||||
mlcfg
|
||||
mmc
|
||||
@@ -1091,7 +1073,6 @@ MOVESIZEEND
|
||||
MOVESIZESTART
|
||||
MRM
|
||||
mru
|
||||
msaccess
|
||||
MSAL
|
||||
msc
|
||||
mscorlib
|
||||
@@ -1100,6 +1081,8 @@ msdata
|
||||
msdia
|
||||
MSDL
|
||||
MSGFLT
|
||||
MSHCTX
|
||||
MSHLFLAGS
|
||||
msiexec
|
||||
MSIFASTINSTALL
|
||||
MSIHANDLE
|
||||
@@ -1109,16 +1092,13 @@ msixbundle
|
||||
MSIXCA
|
||||
MSLLHOOKSTRUCT
|
||||
Mso
|
||||
mspub
|
||||
msrc
|
||||
msstore
|
||||
mstsc
|
||||
msvcp
|
||||
mswhql
|
||||
MT
|
||||
MTND
|
||||
multimonitor
|
||||
Multiplayer
|
||||
MULTIPLEUSE
|
||||
multizone
|
||||
muxc
|
||||
@@ -1161,6 +1141,7 @@ netcpl
|
||||
netframework
|
||||
netsetup
|
||||
netsh
|
||||
newcolor
|
||||
NEWDIALOGSTYLE
|
||||
NEWFILE
|
||||
NEWFILEHEADER
|
||||
@@ -1206,6 +1187,7 @@ nonclient
|
||||
NONCLIENTMETRICSW
|
||||
NONELEVATED
|
||||
nonspace
|
||||
nonstd
|
||||
NOOWNERZORDER
|
||||
NOPARENTNOTIFY
|
||||
NOPREFIX
|
||||
@@ -1220,7 +1202,6 @@ NORMALDISPLAY
|
||||
NORMALUSER
|
||||
NOSEARCH
|
||||
NOSENDCHANGING
|
||||
NOSIZE
|
||||
nosize
|
||||
notdefault
|
||||
NOTHOUSANDS
|
||||
@@ -1261,6 +1242,7 @@ OFN
|
||||
ofs
|
||||
OICI
|
||||
OICIIO
|
||||
oldcolor
|
||||
olditem
|
||||
oldpath
|
||||
oldtheme
|
||||
@@ -1327,7 +1309,6 @@ pchast
|
||||
PCIDLIST
|
||||
PCTSTR
|
||||
PCWSTR
|
||||
pdbs
|
||||
PDBs
|
||||
PDEVMODE
|
||||
PDFs
|
||||
@@ -1356,7 +1337,6 @@ phbm
|
||||
phbmp
|
||||
phicon
|
||||
Photoshop
|
||||
photoshop
|
||||
phwnd
|
||||
pici
|
||||
pidl
|
||||
@@ -1384,15 +1364,14 @@ POINTERID
|
||||
POINTERUPDATE
|
||||
Pokedex
|
||||
Pomodoro
|
||||
Popups
|
||||
popups
|
||||
POPUPWINDOW
|
||||
portfile
|
||||
POSITIONITEM
|
||||
POWERBROADCAST
|
||||
powerdisplay
|
||||
POWERDISPLAYMODULEINTERFACE
|
||||
powerocr
|
||||
powerpnt
|
||||
POWERRENAMECONTEXTMENU
|
||||
powerrenameinput
|
||||
POWERRENAMETEST
|
||||
@@ -1419,6 +1398,7 @@ Prefixer
|
||||
Premul
|
||||
prependpath
|
||||
prepopulate
|
||||
Prereq
|
||||
prevhost
|
||||
previewer
|
||||
PREVIEWHANDLERFRAMEINFO
|
||||
@@ -1447,7 +1427,6 @@ projectname
|
||||
PROPERTYKEY
|
||||
PROPVARIANT
|
||||
prot
|
||||
Prt
|
||||
PRTL
|
||||
prvpane
|
||||
psapi
|
||||
@@ -1493,7 +1472,6 @@ QUERYOPEN
|
||||
QUEUESYNC
|
||||
quickaccent
|
||||
quicklinks
|
||||
quickmask
|
||||
QUNS
|
||||
RAII
|
||||
randi
|
||||
@@ -1514,6 +1492,7 @@ READMODE
|
||||
READOBJECTS
|
||||
recents
|
||||
RECTDESTINATION
|
||||
rectp
|
||||
RECTSOURCE
|
||||
recursesubdirs
|
||||
recyclebin
|
||||
@@ -1601,15 +1580,14 @@ SAMESHORTCUTPREVIOUSLYMAPPED
|
||||
samsung
|
||||
sancov
|
||||
SAVEFAILED
|
||||
scanled
|
||||
schedtasks
|
||||
SCID
|
||||
SCL
|
||||
Scode
|
||||
SCREENFONTS
|
||||
screenruler
|
||||
screensaver
|
||||
screenshots
|
||||
Scrollback
|
||||
scrollviewer
|
||||
sddl
|
||||
SDKDDK
|
||||
@@ -1779,7 +1757,6 @@ STDAPI
|
||||
stdc
|
||||
stdcpp
|
||||
stdcpplatest
|
||||
stdext
|
||||
STDMETHODCALLTYPE
|
||||
STDMETHODIMP
|
||||
steamapps
|
||||
@@ -1902,7 +1879,6 @@ TNP
|
||||
Toggleable
|
||||
tontrager
|
||||
Toolhelp
|
||||
toolsets
|
||||
toolwindow
|
||||
TOPDOWNDIB
|
||||
TOUCHEVENTF
|
||||
@@ -1952,7 +1928,6 @@ ums
|
||||
uncompilable
|
||||
UNCPRIORITY
|
||||
UNDNAME
|
||||
ungroup
|
||||
UNICODETEXT
|
||||
unins
|
||||
uninsdeletekey
|
||||
@@ -1965,8 +1940,6 @@ UNLEN
|
||||
UNORM
|
||||
unparsable
|
||||
unremapped
|
||||
Unsend
|
||||
Unsubscribes
|
||||
untriaged
|
||||
unvirtualized
|
||||
unwide
|
||||
@@ -1996,11 +1969,11 @@ valuegenerator
|
||||
VARTYPE
|
||||
vbcscompiler
|
||||
vcamp
|
||||
VCENTER
|
||||
vcgtq
|
||||
VCINSTALLDIR
|
||||
vcp
|
||||
Vcpkg
|
||||
vcpkg
|
||||
vcpname
|
||||
VCRT
|
||||
vcruntime
|
||||
@@ -2023,7 +1996,6 @@ VIRTKEY
|
||||
VIRTUALDESK
|
||||
VISEGRADRELAY
|
||||
visiblecolorformats
|
||||
visio
|
||||
visualeffects
|
||||
vkey
|
||||
vmovl
|
||||
@@ -2033,6 +2005,7 @@ vorrq
|
||||
VOS
|
||||
vpaddlq
|
||||
vqsubq
|
||||
VREDRAW
|
||||
vreinterpretq
|
||||
VSC
|
||||
VSCBD
|
||||
@@ -2107,16 +2080,13 @@ winlogon
|
||||
winmd
|
||||
winml
|
||||
WINNT
|
||||
winproj
|
||||
winres
|
||||
winrt
|
||||
winsdk
|
||||
winsta
|
||||
WINTHRESHOLD
|
||||
WINVER
|
||||
winword
|
||||
winxamlmanager
|
||||
wireframes
|
||||
withinrafael
|
||||
Withscript
|
||||
wixproj
|
||||
@@ -2187,7 +2157,6 @@ xxxxxx
|
||||
ycombinator
|
||||
yinle
|
||||
yinyue
|
||||
yoko
|
||||
YVIRTUALSCREEN
|
||||
zamora
|
||||
Zenbook
|
||||
|
||||
13
.github/actions/spell-check/patterns.txt
vendored
@@ -18,13 +18,6 @@ MIcrosoftEdgeLauncherCsharp
|
||||
# marker for ignoring a comment to the end of the line
|
||||
// #no-spell-check.*$
|
||||
|
||||
# JavaScript regex literals that start with \b can be reported as "b..." words.
|
||||
# Example: /\bclass\s+.../
|
||||
^\s*/\\[b].{3,}?/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||
|
||||
# GitHub API header token used in code (not natural language).
|
||||
\bx-ratelimit-reset\b
|
||||
|
||||
# Gaelic
|
||||
Gàidhlig
|
||||
|
||||
@@ -312,9 +305,3 @@ ms-windows-store://\S+
|
||||
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+)*m
|
||||
|
||||
# Special licenses text from RNNoise (BSD-style disclaimer: ``AS IS'')
|
||||
``AS IS''
|
||||
|
||||
# Old school moniker for macOS from RNNoise
|
||||
MacOS
|
||||
|
||||
2
.github/policies/resourceManagement.yml
vendored
@@ -163,7 +163,7 @@ configuration:
|
||||
association: Collaborator
|
||||
then:
|
||||
- addReply:
|
||||
reply: We've identified this issue as a duplicate of an existing one and are closing this thread so discussion stays in one place.<br/><br/>Please see the comment above for the link to the original tracking issue, and feel free to subscribe there for updates.
|
||||
reply: Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report!
|
||||
- closeIssue
|
||||
- removeLabel:
|
||||
label: Needs-Triage
|
||||
|
||||
377
.github/scripts/telemetry-pr-check.js
vendored
@@ -1,377 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Detects telemetry-event additions/modifications in a pull request and
|
||||
* posts (or updates) a PR comment when telemetry-related changes are found.
|
||||
*
|
||||
* This script is executed by .github/workflows/telemetry-pr-check.yml.
|
||||
* Keep both files aligned when changing trigger behavior, env usage, or messaging.
|
||||
*/
|
||||
|
||||
const fs = require('node:fs');
|
||||
const REVIEWER_LOGIN = 'chatasweetie';
|
||||
const REVIEWER_MENTION = `@${REVIEWER_LOGIN}`;
|
||||
|
||||
const COMMENT_MARKER = '<!-- telemetry-event-check -->';
|
||||
const COMMENT_BODY_WITH_PRIVACY_UPDATE = `${COMMENT_MARKER}
|
||||
Thank you for contributing to PowerToys. We've detected that this PR might include a new or modified telemetry event. After this PR is merged, please follow these next steps:
|
||||
|
||||
- [ ] Reach out to Jessica (${REVIEWER_MENTION}) to follow up on the next steps: https://aka.ms/pt-telemetry-process
|
||||
`;
|
||||
|
||||
const COMMENT_BODY_WITHOUT_PRIVACY_UPDATE = `${COMMENT_MARKER}
|
||||
Thank you for contributing to PowerToys. We've detected that this PR might include a new or modified telemetry event. Please ensure the following before merging:
|
||||
|
||||
- [ ] Add your telemetry events to [DATA_AND_PRIVACY](https://github.com/microsoft/PowerToys/blob/main/DATA_AND_PRIVACY.md).md within this PR.
|
||||
|
||||
- [ ] Reach out to Jessica (${REVIEWER_MENTION}) to follow up on the next steps: https://aka.ms/pt-telemetry-process`;
|
||||
|
||||
const TELEMETRY_PATH_PATTERNS = [
|
||||
/(^|\/)trace\.(h|hpp|cpp|cs)$/i,
|
||||
/(^|\/)telemetry\//i,
|
||||
/(^|\/)events\/.+event\.cs$/i,
|
||||
/^src\/common\/Telemetry\//i,
|
||||
/^src\/common\/ManagedTelemetry\//i,
|
||||
/^src\/runner\/trace\.(h|cpp)$/i,
|
||||
/^src\/settings-ui\/.+\/Telemetry\//i,
|
||||
];
|
||||
|
||||
const TELEMETRY_LINE_PATTERNS = [
|
||||
/TraceLoggingWriteWrapper\s*\(/,
|
||||
/\bTraceLoggingWrite\s*\(/,
|
||||
/\bTRACELOGGING_DEFINE_PROVIDER\b/,
|
||||
/\bTraceLoggingOptionProjectTelemetry\b/,
|
||||
/\bProjectTelemetryPrivacyDataTag\b/,
|
||||
/\bPROJECT_KEYWORD_MEASURE\b/,
|
||||
/\bRegisterProvider\s*\(/,
|
||||
/\bUnregisterProvider\s*\(/,
|
||||
/\bPowerToysTelemetry\.Log\.WriteEvent\s*\(/,
|
||||
/\bclass\s+\w+\s*:\s*EventBase\s*,\s*IEvent\b/,
|
||||
/\bclass\s+\w+\s*:\s*TelemetryBase\b/,
|
||||
/\bPartA_PrivTags\b/,
|
||||
/\[EventData\]/,
|
||||
/\bEventName\b/,
|
||||
];
|
||||
|
||||
function requireEnv(name) {
|
||||
const value = process.env[name];
|
||||
if (!value) {
|
||||
throw new Error(`Missing required environment variable: ${name}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function validateRepository(repository) {
|
||||
if (!/^[^/]+\/[^/]+$/.test(repository)) {
|
||||
throw new Error(
|
||||
`GITHUB_REPOSITORY must be in owner/repo format, received: ${JSON.stringify(repository)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function readEventPayload(eventPath) {
|
||||
let raw;
|
||||
try {
|
||||
raw = fs.readFileSync(eventPath, 'utf8');
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to read event payload at ${eventPath}: ${error.message}`);
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to parse JSON from ${eventPath}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function resolvePullNumber(event) {
|
||||
const fromPullRequest = event?.pull_request?.number;
|
||||
const fromWorkflowDispatch = event?.inputs?.pr_number;
|
||||
const rawPullNumber = fromPullRequest ?? fromWorkflowDispatch;
|
||||
|
||||
if (rawPullNumber === undefined || rawPullNumber === null || rawPullNumber === '') {
|
||||
throw new Error(
|
||||
'Unable to determine pull request number from event payload. Expected pull_request.number or inputs.pr_number.'
|
||||
);
|
||||
}
|
||||
|
||||
const pullNumber = Number.parseInt(String(rawPullNumber), 10);
|
||||
if (!Number.isInteger(pullNumber) || pullNumber <= 0) {
|
||||
throw new Error(`Invalid pull request number: ${JSON.stringify(rawPullNumber)}`);
|
||||
}
|
||||
|
||||
return pullNumber;
|
||||
}
|
||||
|
||||
function isTelemetryPath(filePath) {
|
||||
return TELEMETRY_PATH_PATTERNS.some((pattern) => pattern.test(filePath));
|
||||
}
|
||||
|
||||
function changedLinesFromPatch(patch) {
|
||||
if (!patch) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return patch
|
||||
.split('\n')
|
||||
.filter((line) => {
|
||||
if (line.startsWith('+++') || line.startsWith('---')) {
|
||||
return false;
|
||||
}
|
||||
return line.startsWith('+') || line.startsWith('-');
|
||||
})
|
||||
.map((line) => line.slice(1));
|
||||
}
|
||||
|
||||
function hasTelemetryLineSignal(lines) {
|
||||
return lines.some((line) => TELEMETRY_LINE_PATTERNS.some((pattern) => pattern.test(line)));
|
||||
}
|
||||
|
||||
async function apiRequest(url, method = 'GET', body) {
|
||||
const token = requireEnv('GITHUB_TOKEN');
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(url, {
|
||||
method,
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
Accept: 'application/vnd.github+json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(`Network error during ${method} ${url}: ${error.message}`);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text();
|
||||
const rateLimitReset = response.headers.get('x-ratelimit-reset');
|
||||
const rateLimitHint =
|
||||
response.status === 403 && rateLimitReset
|
||||
? ` (rate limit reset at epoch ${rateLimitReset})`
|
||||
: '';
|
||||
throw new Error(`${method} ${url} failed (${response.status})${rateLimitHint}: ${text}`);
|
||||
}
|
||||
|
||||
if (response.status === 204) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to parse JSON response for ${method} ${url}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllPullFiles(apiBaseUrl, repository, pullNumber) {
|
||||
const files = [];
|
||||
let page = 1;
|
||||
|
||||
while (true) {
|
||||
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}/files?per_page=100&page=${page}`;
|
||||
const batch = await apiRequest(url);
|
||||
if (!Array.isArray(batch)) {
|
||||
throw new Error(`Unexpected response while listing PR files on page ${page}.`);
|
||||
}
|
||||
|
||||
if (batch.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
files.push(...batch);
|
||||
|
||||
if (batch.length < 100) {
|
||||
break;
|
||||
}
|
||||
|
||||
page += 1;
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
async function getPullRequest(apiBaseUrl, repository, pullNumber) {
|
||||
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}`;
|
||||
const pullRequest = await apiRequest(url);
|
||||
if (!pullRequest || typeof pullRequest !== 'object') {
|
||||
throw new Error('Unexpected response while fetching pull request details.');
|
||||
}
|
||||
return pullRequest;
|
||||
}
|
||||
|
||||
async function ensureReviewerRequested(apiBaseUrl, repository, pullNumber, pullRequest) {
|
||||
const authorLogin = String(pullRequest?.user?.login || '').toLowerCase();
|
||||
const targetReviewer = REVIEWER_LOGIN.toLowerCase();
|
||||
|
||||
if (authorLogin === targetReviewer) {
|
||||
console.log(`Skipping reviewer request: ${REVIEWER_LOGIN} is the PR author.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const requestedReviewers = Array.isArray(pullRequest?.requested_reviewers)
|
||||
? pullRequest.requested_reviewers
|
||||
: [];
|
||||
const alreadyRequested = requestedReviewers.some(
|
||||
(reviewer) => String(reviewer?.login || '').toLowerCase() === targetReviewer
|
||||
);
|
||||
|
||||
if (alreadyRequested) {
|
||||
console.log(`Reviewer ${REVIEWER_LOGIN} is already requested.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const url = `${apiBaseUrl}/repos/${repository}/pulls/${pullNumber}/requested_reviewers`;
|
||||
try {
|
||||
await apiRequest(url, 'POST', { reviewers: [REVIEWER_LOGIN] });
|
||||
console.log(`Requested reviewer ${REVIEWER_LOGIN}.`);
|
||||
} catch (error) {
|
||||
// Reviewer request should not fail the telemetry guidance workflow.
|
||||
console.warn(
|
||||
`Unable to request reviewer ${REVIEWER_LOGIN}: ${error instanceof Error ? error.message : String(error)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function findExistingTelemetryComment(apiBaseUrl, repository, pullNumber) {
|
||||
let page = 1;
|
||||
|
||||
while (true) {
|
||||
const commentsUrl = `${apiBaseUrl}/repos/${repository}/issues/${pullNumber}/comments?per_page=100&page=${page}`;
|
||||
const comments = await apiRequest(commentsUrl);
|
||||
|
||||
if (!Array.isArray(comments)) {
|
||||
throw new Error(`Unexpected response while listing issue comments on page ${page}.`);
|
||||
}
|
||||
|
||||
const existing = comments.find(
|
||||
(comment) => typeof comment.body === 'string' && comment.body.includes(COMMENT_MARKER)
|
||||
);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
if (comments.length < 100) {
|
||||
return null;
|
||||
}
|
||||
|
||||
page += 1;
|
||||
}
|
||||
}
|
||||
|
||||
function detectTelemetryChanges(files) {
|
||||
const matches = [];
|
||||
|
||||
for (const file of files) {
|
||||
const filename = file.filename || '';
|
||||
const telemetryPath = isTelemetryPath(filename);
|
||||
const changedLines = changedLinesFromPatch(file.patch);
|
||||
const telemetryLineSignal = hasTelemetryLineSignal(changedLines);
|
||||
|
||||
// Some large diffs omit patch content. If the file path is telemetry-centric,
|
||||
// treat it as a telemetry modification to avoid false negatives.
|
||||
const patchUnavailable = !file.patch && telemetryPath;
|
||||
|
||||
if (telemetryPath || telemetryLineSignal || patchUnavailable) {
|
||||
matches.push({
|
||||
filename,
|
||||
telemetryPath,
|
||||
telemetryLineSignal,
|
||||
patchUnavailable,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
function hasDataAndPrivacyChange(files) {
|
||||
return files.some((file) => {
|
||||
const filename = (file.filename || '').toLowerCase();
|
||||
return filename === 'data_and_privacy.md';
|
||||
});
|
||||
}
|
||||
|
||||
async function upsertPrComment(apiBaseUrl, repository, pullNumber, body) {
|
||||
const existing = await findExistingTelemetryComment(apiBaseUrl, repository, pullNumber);
|
||||
|
||||
if (existing) {
|
||||
const updateUrl = `${apiBaseUrl}/repos/${repository}/issues/comments/${existing.id}`;
|
||||
await apiRequest(updateUrl, 'PATCH', { body });
|
||||
console.log(`Updated existing telemetry comment (id: ${existing.id}).`);
|
||||
return;
|
||||
}
|
||||
|
||||
const createUrl = `${apiBaseUrl}/repos/${repository}/issues/${pullNumber}/comments`;
|
||||
await apiRequest(createUrl, 'POST', { body });
|
||||
console.log('Created telemetry comment on PR.');
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const eventPath = requireEnv('GITHUB_EVENT_PATH');
|
||||
const repository = requireEnv('GITHUB_REPOSITORY');
|
||||
const apiBaseUrl = process.env.GITHUB_API_URL || 'https://api.github.com';
|
||||
validateRepository(repository);
|
||||
|
||||
let parsedApiBaseUrl;
|
||||
try {
|
||||
parsedApiBaseUrl = new URL(apiBaseUrl);
|
||||
} catch {
|
||||
throw new Error(`Invalid GITHUB_API_URL: ${JSON.stringify(apiBaseUrl)}`);
|
||||
}
|
||||
|
||||
const event = readEventPayload(eventPath);
|
||||
const pullNumber = resolvePullNumber(event);
|
||||
|
||||
console.log(`Event name: ${process.env.GITHUB_EVENT_NAME || 'unknown'}`);
|
||||
console.log(`Repository: ${repository}`);
|
||||
console.log(`PR number: ${pullNumber}`);
|
||||
|
||||
const files = await getAllPullFiles(parsedApiBaseUrl.origin, repository, pullNumber);
|
||||
|
||||
if (files.length === 0) {
|
||||
console.log('No changed files found for PR; skipping telemetry comment update.');
|
||||
return;
|
||||
}
|
||||
|
||||
const matches = detectTelemetryChanges(files);
|
||||
const dataAndPrivacyChanged = hasDataAndPrivacyChange(files);
|
||||
|
||||
console.log(`Scanned ${files.length} changed files.`);
|
||||
console.log(`Telemetry matches found: ${matches.length}.`);
|
||||
console.log(`DATA_AND_PRIVACY.md changed: ${dataAndPrivacyChanged}.`);
|
||||
|
||||
if (matches.length === 0) {
|
||||
console.log('No telemetry-related additions/modifications detected.');
|
||||
return;
|
||||
}
|
||||
|
||||
for (const match of matches) {
|
||||
console.log(
|
||||
`- ${match.filename} (telemetryPath=${match.telemetryPath}, telemetryLineSignal=${match.telemetryLineSignal}, patchUnavailable=${match.patchUnavailable})`
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const pullRequest = await getPullRequest(parsedApiBaseUrl.origin, repository, pullNumber);
|
||||
await ensureReviewerRequested(parsedApiBaseUrl.origin, repository, pullNumber, pullRequest);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
'Failed to fetch PR details or request reviewer; continuing to post telemetry guidance comment.'
|
||||
);
|
||||
console.warn(error instanceof Error ? error.stack || error.message : error);
|
||||
}
|
||||
|
||||
const commentBody = dataAndPrivacyChanged
|
||||
? COMMENT_BODY_WITH_PRIVACY_UPDATE
|
||||
: COMMENT_BODY_WITHOUT_PRIVACY_UPDATE;
|
||||
|
||||
await upsertPrComment(apiBaseUrl, repository, pullNumber, commentBody);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Telemetry PR check failed.');
|
||||
console.error(error instanceof Error ? error.stack || error.message : error);
|
||||
process.exit(1);
|
||||
});
|
||||
229
.github/skills/wpf-to-winui3-migration/SKILL.md
vendored
@@ -31,9 +31,7 @@ Migrate PowerToys modules from WPF (`System.Windows.*`) to WinUI 3 (`Microsoft.U
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Phase-by-Phase Scope
|
||||
|
||||
Work on bounded problems, not the entire codebase at once. Each phase should compile before moving to the next.
|
||||
### Recommended Order
|
||||
|
||||
1. **Project file** — Update TFM, NuGet packages, set `<UseWinUI>true</UseWinUI>`
|
||||
2. **Data models and business logic** — No UI dependencies, migrate first
|
||||
@@ -47,213 +45,79 @@ Work on bounded problems, not the entire codebase at once. Each phase should com
|
||||
10. **Installer & build pipeline** — Update WiX, signing, build events
|
||||
11. **Tests** — Adapt for WinUI 3 runtime, async patterns
|
||||
|
||||
### Migration Contract: Prohibited Patterns
|
||||
### Key Principles
|
||||
|
||||
These rules capture human judgment and must be applied consistently across every file. Do NOT deviate.
|
||||
|
||||
**Architecture prohibitions:**
|
||||
- **Do NOT overwrite `App.xaml` / `App.xaml.cs`** — WinUI 3 has different lifecycle boilerplate. Merge resources and init code into the generated WinUI 3 App class.
|
||||
- **Do NOT create Exe→WinExe `ProjectReference`** — Extract shared code to a Library project. Causes phantom build artifacts.
|
||||
- **Do NOT instantiate services directly** — Use DI and CommunityToolkit.Mvvm patterns.
|
||||
- **Do NOT create a `Window` subclass for every dialog or sub-page** — use `ContentDialog` for in-app dialogs and `Frame`/`Page` navigation for sub-views. Separate `Window` classes are reserved for distinct top-level surfaces (e.g., FancyZones editor, OOBE).
|
||||
- **Do NOT omit `WindowsPackageType=None` and `WindowsAppSDKSelfContained=true`** — Both are mandatory in the csproj for every WinUI 3 module in PowerToys. Without them the app crashes at startup with `COMException: ClassFactory cannot supply requested class` because the WinUI 3 runtime DLLs are not found.
|
||||
|
||||
**XAML prohibitions:**
|
||||
- **Do NOT use `{DynamicResource}`** — Replace with `{ThemeResource}` (theme-reactive) or `{StaticResource}`.
|
||||
- **Do NOT use `{Binding}` in `Setter.Value`** — Not supported in WinUI 3. Use `{StaticResource}`.
|
||||
- **Do NOT use `{x:Static}`** — Replace with `{x:Bind}`, `x:Uid`, or code-behind.
|
||||
- **Do NOT use `{x:Type}`** — Not supported. Use `x:DataType` for DataTemplate, or code-behind.
|
||||
- **Do NOT use `clr-namespace:`** — Replace with `using:` in all xmlns declarations.
|
||||
- **Do NOT use `Style.Triggers` / `DataTrigger` / `EventTrigger`** — Replace with `VisualStateManager`.
|
||||
- **Do NOT use `MultiBinding`** — Replace with `x:Bind` function binding or computed ViewModel property.
|
||||
- **Do NOT use `Visibility="Hidden"`** — WinUI only has `Visible` and `Collapsed`. Use `Opacity="0"` if layout must be preserved.
|
||||
- **Do NOT use `IsDefault` / `IsCancel`** — Use `AccentButtonStyle` for primary button; handle Enter/Escape in code-behind.
|
||||
- **Do NOT omit `BasedOn` when overriding default styles** — Without it, your style replaces the entire default. Always use `BasedOn="{StaticResource DefaultButtonStyle}"` etc.
|
||||
- **Do NOT omit `XamlControlsResources` as first merged dictionary** — It provides default Fluent styles. Without it, controls have no visual appearance.
|
||||
|
||||
**Code-behind prohibitions:**
|
||||
- **Do NOT use `Application.Current.Dispatcher`** — Store `DispatcherQueue` in a static field explicitly.
|
||||
- **Do NOT use `Window.Current`** — Not supported. Use a custom `App.Window` static property.
|
||||
- **Do NOT put `DataContext`, `Resources`, or `VisualStateManager` on `Window`** — WinUI 3 `Window` is NOT a `DependencyObject`. Use a root `Page`/`UserControl`/`Grid`.
|
||||
- **Do NOT use tunneling/preview events** (`PreviewMouseDown`, `PreviewKeyDown`) — WinUI has no tunneling. Use bubbling equivalents with `Handled` property or `AddHandler(handledEventsToo: true)`.
|
||||
|
||||
**Resource prohibitions:**
|
||||
- **Do NOT use `Properties.Resources.MyString`** — Replace with `ResourceLoaderInstance.ResourceLoader.GetString("MyString")`.
|
||||
- **Do NOT initialize `ResourceLoader`-dependent values as static fields** — Wrap in `Lazy<T>` or null-coalescing property.
|
||||
- **Do NOT use `pack://` URIs** — Replace with `ms-appx:///` scheme.
|
||||
- **Do NOT overwrite `App.xaml` / `App.xaml.cs`** — WinUI 3 has different application lifecycle boilerplate. Merge your resources and initialization code into the generated WinUI 3 App class.
|
||||
- **Do NOT create Exe→WinExe `ProjectReference`** — Extract shared code to a Library project. This causes phantom build artifacts.
|
||||
- **Use `Lazy<T>` for resource-dependent statics** — `ResourceLoader` is not available at class-load time in all contexts.
|
||||
|
||||
## Quick Reference Tables
|
||||
|
||||
### Namespace Mapping
|
||||
|
||||
| WPF | WinUI 3 | Notes |
|
||||
|-----|---------|-------|
|
||||
| `System.Windows` | `Microsoft.UI.Xaml` | Root namespace |
|
||||
| `System.Windows.Controls` | `Microsoft.UI.Xaml.Controls` | Core controls |
|
||||
| `System.Windows.Controls.Primitives` | `Microsoft.UI.Xaml.Controls.Primitives` | Low-level primitives |
|
||||
| `System.Windows.Media` | `Microsoft.UI.Xaml.Media` | Brushes, transforms |
|
||||
| `System.Windows.Media.Animation` | `Microsoft.UI.Xaml.Media.Animation` | Storyboard, animations |
|
||||
| `System.Windows.Media.Imaging` | `Microsoft.UI.Xaml.Media.Imaging` (UI) / `Windows.Graphics.Imaging` (processing) | Split by purpose |
|
||||
| `System.Windows.Media.Media3D` | **No equivalent** | Use Win2D or Composition APIs |
|
||||
| `System.Windows.Shapes` | `Microsoft.UI.Xaml.Shapes` | Rectangle, Ellipse, Path |
|
||||
| `System.Windows.Input` | `Microsoft.UI.Xaml.Input` | Pointer, keyboard, focus |
|
||||
| `System.Windows.Data` | `Microsoft.UI.Xaml.Data` | Binding, IValueConverter |
|
||||
| `System.Windows.Documents` | `Microsoft.UI.Xaml.Documents` | Limited — RichTextBlock + Paragraph |
|
||||
| `System.Windows.Markup` | `Microsoft.UI.Xaml.Markup` | XAML parsing, markup extensions |
|
||||
| `System.Windows.Automation` | `Microsoft.UI.Xaml.Automation` | Accessibility / UI Automation |
|
||||
| `System.Windows.Navigation` | **No direct equivalent** | Use `Frame.Navigate()` |
|
||||
| `System.Windows.Threading` | `Microsoft.UI.Dispatching` | Dispatcher → DispatcherQueue |
|
||||
| `System.Windows.Interop` | `WinRT.Interop` / `Microsoft.UI.Xaml.Hosting` | HWND interop |
|
||||
|
||||
### Control Replacements (No 1:1 Mapping)
|
||||
|
||||
These WPF controls have no direct counterpart and require a different control or third-party package:
|
||||
|
||||
| WPF Control | WinUI 3 Replacement | Notes |
|
||||
|-------------|---------------------|-------|
|
||||
| `DataGrid` | [`WinUI.TableView`](https://github.com/w-ahmad/WinUI.TableView) | Community library; the Toolkit `DataGrid` is no longer maintained. Legacy code may still pin v7 `CommunityToolkit.WinUI.UI.Controls.DataGrid` 7.1.2 |
|
||||
| `Ribbon` | `CommandBar` / `NavigationView`, or [Toolkit Labs Ribbon](https://github.com/CommunityToolkit/Labs-Windows/tree/main/components/Ribbon) | No first-party Ribbon in WinUI; Labs component is experimental/partial |
|
||||
| `Menu` / `MenuItem` | `MenuBar` / `MenuBarItem` / `MenuFlyout` | `MenuBar` for classic menu, `MenuFlyout` for context |
|
||||
| `ContextMenu` | `MenuFlyout` | Assign to `ContextFlyout` property |
|
||||
| `ToolBar` / `ToolBarTray` | `CommandBar` + `AppBarButton` | |
|
||||
| `StatusBar` | Custom `Grid`/`StackPanel` or `InfoBar` | No StatusBar control |
|
||||
| `TabControl` | `TabView` or `NavigationView` (top mode) | `TabView` for closeable tabs |
|
||||
| `DocumentViewer` | `WebView2` | Render PDFs/XPS inside WebView2 |
|
||||
| `FlowDocument` | `RichTextBlock` | Partial replacement only |
|
||||
| `RichTextBox` | `RichEditBox` | Rich text editing |
|
||||
| `GroupBox` | `Expander` (built-in) or `HeaderedContentControl` (Toolkit) | See [Layout & Header Controls from CommunityToolkit.WinUI](#layout--header-controls-from-communitytoolkitwinui) below |
|
||||
| `Label` | `TextBlock` | WPF `Label` is a `ContentControl`; use `TextBlock` + `AccessKey` |
|
||||
| `TreeView` | `TreeView` (native) | Available natively, but data binding model differs significantly |
|
||||
| `MessageBox` | `ContentDialog` | Must set `XamlRoot` before `ShowAsync()` |
|
||||
| `MediaElement` | `MediaPlayerElement` | Different API |
|
||||
| `AccessText` | Not available | Use `AccessKey` property on target control |
|
||||
|
||||
### Layout & Header Controls from CommunityToolkit.WinUI
|
||||
|
||||
These WPF controls have no built-in WinUI 3 equivalent — install the corresponding CommunityToolkit package. **The NuGet package id and the XAML namespace differ intentionally**: package names end in `.Primitives` / `.HeaderedControls`, but the registered XAML namespace is the shorter `CommunityToolkit.WinUI.Controls` (confirmed in the [official Microsoft Q&A](https://learn.microsoft.com/en-us/answers/questions/5746230/why-does-communitytoolkit-uwp-controls-primitive-u)).
|
||||
|
||||
| WPF Control | WinUI 3 Replacement | NuGet Package | XAML Namespace |
|
||||
|-------------|---------------------|---------------|----------------|
|
||||
| `WrapPanel` | `WrapPanel` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
| `UniformGrid` | `UniformGrid` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
| `DockPanel` | `DockPanel` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
| `GroupBox` (alt.) | `HeaderedContentControl` | `CommunityToolkit.WinUI.Controls.HeaderedControls` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
|
||||
### No Equivalent — Requires Architectural Rework
|
||||
|
||||
These WPF features have no WinUI counterpart and require redesign, not find-and-replace:
|
||||
|
||||
| WPF Feature | WinUI 3 Replacement Strategy |
|
||||
|-------------|------------------------------|
|
||||
| `Style.Triggers` / `DataTrigger` | `VisualStateManager` with `StateTrigger` — see [XAML Migration](./references/xaml-migration.md) |
|
||||
| `MultiBinding` | `x:Bind` function binding: `{x:Bind local:Converters.Format(VM.A, VM.B), Mode=OneWay}` |
|
||||
| `RoutedUICommand` / `CommandBinding` | `ICommand` / `[RelayCommand]` from CommunityToolkit.Mvvm. WinUI also has `StandardUICommand` / `XamlUICommand` for platform commands. |
|
||||
| `AdornerLayer` / `Adorner` | Depends on use case: `TeachingTip`/`InfoBar` (validation), `Popup` (overlays), `PlaceholderText` (watermarks), Canvas overlay (decorations) |
|
||||
| `Visibility.Hidden` | `Opacity="0"` with `Visibility="Visible"` (preserves layout space) |
|
||||
| `Window.Resources` / `Window.DataContext` | Move to root `Grid.Resources` / root `Page`/`UserControl` — WinUI `Window` is NOT a DependencyObject |
|
||||
| Tunneling events (`Preview*`) | Use bubbling equivalents + `Handled` property or `AddHandler(handledEventsToo: true)` |
|
||||
| WPF | WinUI 3 |
|
||||
|-----|---------|
|
||||
| `System.Windows` | `Microsoft.UI.Xaml` |
|
||||
| `System.Windows.Controls` | `Microsoft.UI.Xaml.Controls` |
|
||||
| `System.Windows.Media` | `Microsoft.UI.Xaml.Media` |
|
||||
| `System.Windows.Media.Imaging` | `Microsoft.UI.Xaml.Media.Imaging` (UI) / `Windows.Graphics.Imaging` (processing) |
|
||||
| `System.Windows.Input` | `Microsoft.UI.Xaml.Input` |
|
||||
| `System.Windows.Data` | `Microsoft.UI.Xaml.Data` |
|
||||
| `System.Windows.Threading` | `Microsoft.UI.Dispatching` |
|
||||
| `System.Windows.Interop` | `WinRT.Interop` |
|
||||
|
||||
### Critical API Replacements
|
||||
|
||||
| WPF | WinUI 3 | Notes |
|
||||
|-----|---------|-------|
|
||||
| `Dispatcher.Invoke()` | `DispatcherQueue.TryEnqueue()` | Different return type (`bool`), async by default |
|
||||
| `Dispatcher.Invoke()` | `DispatcherQueue.TryEnqueue()` | Different return type (`bool`) |
|
||||
| `Dispatcher.CheckAccess()` | `DispatcherQueue.HasThreadAccess` | Property vs method |
|
||||
| `Application.Current.Dispatcher` | Store `DispatcherQueue` in static field | See [Threading](./references/threading-and-windowing.md) |
|
||||
| `Window.Current` | Custom `App.Window` static property | Not supported in Windows App SDK |
|
||||
| `Application.Current.MainWindow` | Custom `App.Window` static property | Must track manually |
|
||||
| `MessageBox.Show()` | `ContentDialog` | Must set `XamlRoot` |
|
||||
| `System.Windows.Clipboard` | `Windows.ApplicationModel.DataTransfer.Clipboard` | Different API surface |
|
||||
| `RoutedUICommand` / `CommandBinding` | `ICommand` / `[RelayCommand]` | Remove `CommandBinding`; bind `ICommand` directly |
|
||||
| `Properties.Resources.MyString` | `ResourceLoaderInstance.ResourceLoader.GetString("MyString")` | Lazy-init pattern |
|
||||
| `DynamicResource` | `ThemeResource` | Theme-reactive only |
|
||||
| `clr-namespace:` | `using:` | XAML namespace prefix |
|
||||
| `{x:Static props:Resources.Key}` | `x:Uid` or `ResourceLoader.GetString()` | .resx → .resw |
|
||||
| `DataType="{x:Type m:Foo}"` | `x:DataType="m:Foo"` | `x:Type` not supported |
|
||||
| `DataType="{x:Type m:Foo}"` | Remove or use code-behind | `x:Type` not supported |
|
||||
| `Properties.Resources.MyString` | `ResourceLoaderInstance.ResourceLoader.GetString("MyString")` | Lazy-init pattern |
|
||||
| `Application.Current.MainWindow` | Custom `App.Window` static property | Must track manually |
|
||||
| `SizeToContent="Height"` | Custom `SizeToContent()` via `AppWindow.Resize()` | See [Windowing](./references/threading-and-windowing.md) |
|
||||
| `MouseLeftButtonDown` | `PointerPressed` | Mouse → Pointer events |
|
||||
| `Pack URI (pack://...)` | `ms-appx:///` | Resource URI scheme |
|
||||
| `Observable` (custom base) | `ObservableObject` + `[ObservableProperty]` | CommunityToolkit.Mvvm |
|
||||
| `RelayCommand` (custom) | `[RelayCommand]` source generator | CommunityToolkit.Mvvm |
|
||||
| `JpegBitmapEncoder` | `BitmapEncoder.CreateAsync(JpegEncoderId, stream)` | Async, unified API |
|
||||
| `encoder.QualityLevel = 85` | `BitmapPropertySet { "ImageQuality", 0.85f }` | int 1-100 → float 0-1 |
|
||||
|
||||
### Event Replacements (Mouse → Pointer)
|
||||
|
||||
| WPF Event | WinUI 3 Event | Notes |
|
||||
|-----------|--------------|-------|
|
||||
| `MouseLeftButtonDown` | `PointerPressed` | Check `IsLeftButtonPressed` on args |
|
||||
| `MouseLeftButtonUp` | `PointerReleased` | Check pointer properties |
|
||||
| `MouseRightButtonDown` | `RightTapped` | Or `PointerPressed` with right button check |
|
||||
| `MouseMove` | `PointerMoved` | `MouseEventArgs` → `PointerRoutedEventArgs` |
|
||||
| `MouseWheel` | `PointerWheelChanged` | Different event args |
|
||||
| `MouseEnter` / `MouseLeave` | `PointerEntered` / `PointerExited` | |
|
||||
| `MouseDoubleClick` | `DoubleTapped` | Different event args |
|
||||
| `PreviewMouseDown` | `PointerPressed` | No tunneling — use `Handled` or `AddHandler` |
|
||||
| `PreviewKeyDown` | `KeyDown` | `KeyEventArgs` → `KeyRoutedEventArgs` |
|
||||
|
||||
### Property Replacements
|
||||
|
||||
| WPF | WinUI 3 | Context |
|
||||
|-----|---------|---------|
|
||||
| `Visibility.Hidden` | `Visibility.Collapsed` or `Opacity="0"` | Use `Opacity="0"` to preserve layout |
|
||||
| `TextWrapping.WrapWithOverflow` | `TextWrapping.Wrap` | WinUI doesn't distinguish |
|
||||
| `Focusable="True"` | `IsTabStop="True"` | Different property name |
|
||||
| `ContextMenu=` | `ContextFlyout=` | On any `UIElement` |
|
||||
| `MediaElement` | `MediaPlayerElement` | Different API |
|
||||
| `SnapsToDevicePixels` | Not available | WinUI handles pixel snapping internally |
|
||||
|
||||
### NuGet Package Migration
|
||||
|
||||
| WPF | WinUI 3 | Notes |
|
||||
|-----|---------|-------|
|
||||
| `Microsoft.Xaml.Behaviors.Wpf` | `Microsoft.Xaml.Behaviors.WinUI.Managed` | |
|
||||
| `WPF-UI` (Lepo) | **Remove** — use native WinUI 3 controls | |
|
||||
| `CommunityToolkit.Mvvm` | `CommunityToolkit.Mvvm` (same) | |
|
||||
| `Microsoft.Toolkit.Wpf.*` | `CommunityToolkit.WinUI.*` | |
|
||||
| (none) | `Microsoft.WindowsAppSDK` | Required |
|
||||
| (none) | `Microsoft.Windows.SDK.BuildTools` | Required |
|
||||
| (none) | `WinUIEx` | Optional, window helpers |
|
||||
| (none) | `CommunityToolkit.WinUI.Converters` | Optional |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.Primitives` | Optional — `WrapPanel`, `UniformGrid`, `DockPanel`, `ConstrainedBox` |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.HeaderedControls` | Optional — `HeaderedContentControl`, `HeaderedItemsControl`, `HeaderedTreeView` |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.SettingsControls` | Optional — `SettingsCard`, `SettingsExpander` |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.Sizers` | Optional — `GridSplitter` |
|
||||
| (none) | `CommunityToolkit.WinUI.UI.Controls.DataGrid` | Legacy v7 — only for migrating existing `DataGrid` code; prefer `WinUI.TableView` |
|
||||
| WPF | WinUI 3 |
|
||||
|-----|---------|
|
||||
| `Microsoft.Xaml.Behaviors.Wpf` | `Microsoft.Xaml.Behaviors.WinUI.Managed` |
|
||||
| `WPF-UI` (Lepo) | Remove — use native WinUI 3 controls |
|
||||
| `CommunityToolkit.Mvvm` | `CommunityToolkit.Mvvm` (same) |
|
||||
| `Microsoft.Toolkit.Wpf.*` | `CommunityToolkit.WinUI.*` |
|
||||
| (none) | `Microsoft.WindowsAppSDK` |
|
||||
| (none) | `Microsoft.Windows.SDK.BuildTools` |
|
||||
| (none) | `WinUIEx` (optional, for window helpers) |
|
||||
| (none) | `CommunityToolkit.WinUI.Converters` |
|
||||
|
||||
### XAML Syntax Changes
|
||||
|
||||
| WPF | WinUI 3 | Notes |
|
||||
|-----|---------|-------|
|
||||
| `xmlns:local="clr-namespace:MyApp"` | `xmlns:local="using:MyApp"` | CLR → using syntax |
|
||||
| `{DynamicResource Key}` | `{ThemeResource Key}` | Re-evaluates on theme change |
|
||||
| `{StaticResource Key}` | `{StaticResource Key}` | Same — resolved once at load |
|
||||
| `{x:Static Type.Member}` | `{x:Bind}` or code-behind | |
|
||||
| `{x:Type local:MyType}` | Not supported | Use `x:DataType` for DataTemplate |
|
||||
| `{x:Array}` | Not supported | Create collections in code-behind |
|
||||
| `<Style.Triggers>` / `<DataTrigger>` | `VisualStateManager` | See [XAML Migration](./references/xaml-migration.md) |
|
||||
| `{Binding}` in `Setter.Value` | Not supported — use `StaticResource` | |
|
||||
| `Content="{x:Static p:Resources.Cancel}"` | `x:Uid="Cancel"` with `.Content` in `.resw` | |
|
||||
| `sys:String` / `sys:Int32` / etc. | `x:String` / `x:Int32` / etc. | XAML intrinsic types |
|
||||
| `<ui:FluentWindow>` (WPF-UI) | `<Window>` | Native + `ExtendsContentIntoTitleBar` |
|
||||
| `<ui:NumberBox>` / `<ui:ProgressRing>` (WPF-UI) | Native `<NumberBox>` / `<ProgressRing>` | |
|
||||
| `BasedOn="{StaticResource {x:Type ui:Button}}"` | `BasedOn="{StaticResource DefaultButtonStyle}"` | Named style keys |
|
||||
| `IsDefault="True"` / `IsCancel="True"` | `Style="{StaticResource AccentButtonStyle}"` / KeyDown | |
|
||||
| `<AccessText>` | Not available — use `AccessKey` property | |
|
||||
| `<behaviors:Interaction.Triggers>` | Code-behind or WinUI behaviors | |
|
||||
| `Window.Resources` | Root container's `Resources` (e.g. `Grid.Resources`) | Window is not a DependencyObject |
|
||||
|
||||
### Binding: {Binding} vs {x:Bind}
|
||||
|
||||
Both work in WinUI 3. Prefer `{x:Bind}` for new/migrated code.
|
||||
|
||||
| Feature | `{Binding}` | `{x:Bind}` |
|
||||
|---------|------------|------------|
|
||||
| Default mode | `OneWay` | **`OneTime`** — add `Mode=OneWay` explicitly! |
|
||||
| Default source | `DataContext` | Page/UserControl code-behind |
|
||||
| Compile-time validation | No | Yes |
|
||||
| Function binding | No | Yes (replaces `MultiBinding`) |
|
||||
| Performance | Reflection-based | Compiled, no reflection |
|
||||
| `MultiBinding` support | No (not in WinUI) | Use function binding |
|
||||
| WPF | WinUI 3 |
|
||||
|-----|---------|
|
||||
| `xmlns:local="clr-namespace:MyApp"` | `xmlns:local="using:MyApp"` |
|
||||
| `{DynamicResource Key}` | `{ThemeResource Key}` |
|
||||
| `{x:Static Type.Member}` | `{x:Bind}` or code-behind |
|
||||
| `{x:Type local:MyType}` | Not supported |
|
||||
| `<Style.Triggers>` / `<DataTrigger>` | `VisualStateManager` |
|
||||
| `{Binding}` in `Setter.Value` | Not supported — use `StaticResource` |
|
||||
| `Content="{x:Static p:Resources.Cancel}"` | `x:Uid="Cancel"` with `.Content` in `.resw` |
|
||||
| `<ui:FluentWindow>` / `<ui:Button>` (WPF-UI) | Native `<Window>` / `<Button>` |
|
||||
| `<ui:NumberBox>` / `<ui:ProgressRing>` (WPF-UI) | Native `<NumberBox>` / `<ProgressRing>` |
|
||||
| `BasedOn="{StaticResource {x:Type ui:Button}}"` | `BasedOn="{StaticResource DefaultButtonStyle}"` |
|
||||
| `IsDefault="True"` / `IsCancel="True"` | `Style="{StaticResource AccentButtonStyle}"` / handle via KeyDown |
|
||||
| `<AccessText>` | Not available — use `AccessKey` property |
|
||||
| `<behaviors:Interaction.Triggers>` | Migrate to code-behind or WinUI behaviors |
|
||||
|
||||
## Detailed Reference Docs
|
||||
|
||||
@@ -287,8 +151,6 @@ Read only the section relevant to your current task:
|
||||
| JPEG quality value wrong after migration | WPF: int 1-100; WinRT: float 0.0-1.0 |
|
||||
| MSIX packaging fails in PreBuildEvent | Move to PostBuildEvent; artifacts not ready at PreBuild time |
|
||||
| RC file icon path with forward slashes | Use double-backslash escaping: `..\\ui\\Assets\\icon.ico` |
|
||||
| `COMException: ClassFactory cannot supply requested class` at startup | Missing `<WindowsPackageType>None</WindowsPackageType>` and/or `<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>` in csproj. Without these, the app tries to locate the Windows App SDK framework package (not installed) instead of using bundled runtime DLLs. **Both properties are mandatory for every WinUI 3 module in PowerToys.** |
|
||||
| `CombinedGeometry` not available in WinUI 3 | WinUI 3 `UIElement.Clip` only accepts `RectangleGeometry`. For overlay hole effects (exclude region), use a `Path` element with `GeometryGroup FillRule="EvenOdd"` containing two `RectangleGeometry` children — the EvenOdd rule creates a transparent hole where geometries overlap. |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -301,4 +163,3 @@ Read only the section relevant to your current task:
|
||||
| NuGet restore failures | Run `build-essentials.cmd` after adding `Microsoft.WindowsAppSDK` package |
|
||||
| `Parallel.ForEach` compilation error | Migrate to `Parallel.ForEachAsync` for async imaging operations |
|
||||
| Signing check fails on leaked artifacts | Run `generateAllFileComponents.ps1`; verify only `WinUI3Apps\\` paths in signing config |
|
||||
| `COMException` / `ClassFactory` error at app launch | Ensure csproj has `<WindowsPackageType>None</WindowsPackageType>` and `<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>`. These are required for all unpackaged WinUI 3 apps in PowerToys — without them the WinUI 3 COM runtime cannot be found. |
|
||||
|
||||
@@ -4,26 +4,24 @@ Complete reference for mapping WPF types to WinUI 3 equivalents, based on the Im
|
||||
|
||||
## Root Namespace Mapping
|
||||
|
||||
| WPF Namespace | WinUI 3 Namespace | Notes |
|
||||
|---------------|-------------------|-------|
|
||||
| `System.Windows` | `Microsoft.UI.Xaml` | Root namespace |
|
||||
| `System.Windows.Automation` | `Microsoft.UI.Xaml.Automation` | Accessibility / UI Automation |
|
||||
| `System.Windows.Automation.Peers` | `Microsoft.UI.Xaml.Automation.Peers` | |
|
||||
| `System.Windows.Controls` | `Microsoft.UI.Xaml.Controls` | Core controls |
|
||||
| `System.Windows.Controls.Primitives` | `Microsoft.UI.Xaml.Controls.Primitives` | Low-level primitives |
|
||||
| `System.Windows.Data` | `Microsoft.UI.Xaml.Data` | Binding, IValueConverter |
|
||||
| `System.Windows.Documents` | `Microsoft.UI.Xaml.Documents` | Limited — RichTextBlock + Paragraph only |
|
||||
| `System.Windows.Input` | `Microsoft.UI.Xaml.Input` | Pointer, keyboard, focus |
|
||||
| `System.Windows.Markup` | `Microsoft.UI.Xaml.Markup` | XAML parsing, markup extensions |
|
||||
| `System.Windows.Media` | `Microsoft.UI.Xaml.Media` | Brushes, transforms |
|
||||
| `System.Windows.Media.Animation` | `Microsoft.UI.Xaml.Media.Animation` | Storyboard, animations |
|
||||
| `System.Windows.Media.Imaging` | `Microsoft.UI.Xaml.Media.Imaging` | UI display only — use `Windows.Graphics.Imaging` for processing |
|
||||
| `System.Windows.Media.Media3D` | **No equivalent** | Use Win2D or Composition APIs |
|
||||
| `System.Windows.Navigation` | `Microsoft.UI.Xaml.Navigation` | For Frame navigation events; no `NavigationService` |
|
||||
| `System.Windows.Shapes` | `Microsoft.UI.Xaml.Shapes` | Rectangle, Ellipse, Path |
|
||||
| `System.Windows.Threading` | `Microsoft.UI.Dispatching` | Dispatcher → DispatcherQueue |
|
||||
| `System.Windows.Interop` | `WinRT.Interop` | HWND interop |
|
||||
| `System.Windows.Interop` | `Microsoft.UI.Xaml.Hosting` | XAML Islands |
|
||||
| WPF Namespace | WinUI 3 Namespace |
|
||||
|---------------|-------------------|
|
||||
| `System.Windows` | `Microsoft.UI.Xaml` |
|
||||
| `System.Windows.Automation` | `Microsoft.UI.Xaml.Automation` |
|
||||
| `System.Windows.Automation.Peers` | `Microsoft.UI.Xaml.Automation.Peers` |
|
||||
| `System.Windows.Controls` | `Microsoft.UI.Xaml.Controls` |
|
||||
| `System.Windows.Controls.Primitives` | `Microsoft.UI.Xaml.Controls.Primitives` |
|
||||
| `System.Windows.Data` | `Microsoft.UI.Xaml.Data` |
|
||||
| `System.Windows.Documents` | `Microsoft.UI.Xaml.Documents` |
|
||||
| `System.Windows.Input` | `Microsoft.UI.Xaml.Input` |
|
||||
| `System.Windows.Markup` | `Microsoft.UI.Xaml.Markup` |
|
||||
| `System.Windows.Media` | `Microsoft.UI.Xaml.Media` |
|
||||
| `System.Windows.Media.Animation` | `Microsoft.UI.Xaml.Media.Animation` |
|
||||
| `System.Windows.Media.Imaging` | `Microsoft.UI.Xaml.Media.Imaging` |
|
||||
| `System.Windows.Navigation` | `Microsoft.UI.Xaml.Navigation` |
|
||||
| `System.Windows.Shapes` | `Microsoft.UI.Xaml.Shapes` |
|
||||
| `System.Windows.Threading` | `Microsoft.UI.Dispatching` |
|
||||
| `System.Windows.Interop` | `WinRT.Interop` |
|
||||
|
||||
## Core Type Mapping
|
||||
|
||||
@@ -47,7 +45,7 @@ Complete reference for mapping WPF types to WinUI 3 equivalents, based on the Im
|
||||
|
||||
These controls exist in both frameworks with the same name — change `System.Windows.Controls` to `Microsoft.UI.Xaml.Controls`:
|
||||
|
||||
`Button`, `TextBox`, `TextBlock`, `ComboBox`, `CheckBox`, `ListView`, `Image`, `StackPanel`, `Grid`, `Border`, `ScrollViewer`, `ContentControl`, `UserControl`, `Page`, `Frame`, `Slider`, `ProgressBar`, `ToolTip`, `RadioButton`, `ToggleButton`
|
||||
`Button`, `TextBox`, `TextBlock`, `ComboBox`, `CheckBox`, `ListBox`, `ListView`, `Image`, `StackPanel`, `Grid`, `Border`, `ScrollViewer`, `ContentControl`, `UserControl`, `Page`, `Frame`, `Slider`, `ProgressBar`, `ToolTip`, `RadioButton`, `ToggleButton`
|
||||
|
||||
### Controls With Different Names or Behavior
|
||||
|
||||
@@ -58,7 +56,6 @@ These controls exist in both frameworks with the same name — change `System.Wi
|
||||
| `TabControl` | `TabView` | Different API |
|
||||
| `Menu` | `MenuBar` | Different API |
|
||||
| `StatusBar` | Custom `StackPanel` layout | No built-in equivalent |
|
||||
| `ListBox` | `ListView` (or `ItemsView`) | **Deprecated in WinUI 3 — do not use.** Prefer `ListView`, or `ItemsView` (WinUI 1.5+) for modern collection scenarios |
|
||||
| `AccessText` | Not available | Use `AccessKey` property on target control |
|
||||
|
||||
### WPF-UI (Lepo) to Native WinUI 3
|
||||
@@ -112,43 +109,6 @@ Last parameter changes from `CultureInfo` to `string` (BCP-47 language tag). All
|
||||
| `System.Windows.Interop.WindowInteropHelper` | `WinRT.Interop.WindowNative.GetWindowHandle()` | |
|
||||
| `System.Windows.SystemColors` | Resource keys via `ThemeResource` | No direct static class |
|
||||
| `System.Windows.SystemParameters` | Win32 API or `DisplayInformation` | No direct equivalent |
|
||||
| `System.Windows.Clipboard` | `Windows.ApplicationModel.DataTransfer.Clipboard` | Different API surface |
|
||||
| `System.Windows.Input.RoutedUICommand` | `Microsoft.UI.Xaml.Input.StandardUICommand` / `XamlUICommand` | Or use `ICommand` / `[RelayCommand]` |
|
||||
| `System.Windows.Input.CommandBinding` | **Remove** | Bind `ICommand` directly in XAML |
|
||||
|
||||
## Controls That Need Translation (No 1:1 Mapping)
|
||||
|
||||
These controls exist in WPF but require a different control, third-party library, or Community Toolkit package in WinUI 3:
|
||||
|
||||
| WPF Control | WinUI 3 Replacement | Package / Notes |
|
||||
|-------------|---------------------|-----------------|
|
||||
| `DataGrid` | [`WinUI.TableView`](https://github.com/w-ahmad/WinUI.TableView) | Community library; the Toolkit `DataGrid` is no longer maintained. PowerToys legacy modules may still pin v7 `CommunityToolkit.WinUI.UI.Controls.DataGrid` 7.1.2 — prefer `WinUI.TableView` for new work. |
|
||||
| `Ribbon` | `CommandBar` / `NavigationView`, or [Toolkit Labs Ribbon](https://github.com/CommunityToolkit/Labs-Windows/tree/main/components/Ribbon) | No first-party Ribbon in WinUI; the Labs component is experimental and partial |
|
||||
| `Menu` / `MenuItem` | `MenuBar` / `MenuBarItem` / `MenuFlyoutItem` | `MenuBar` for classic menu, `MenuFlyout` for context |
|
||||
| `ContextMenu` | `MenuFlyout` | Assign to `ContextFlyout` property |
|
||||
| `ToolBar` / `ToolBarTray` | `CommandBar` + `AppBarButton` | |
|
||||
| `StatusBar` | Custom `Grid`/`StackPanel` or `InfoBar` | No StatusBar control |
|
||||
| `TabControl` | `TabView` or `NavigationView` (top mode) | `TabView` for closeable tabs |
|
||||
| `DocumentViewer` | `WebView2` | `Microsoft.Web.WebView2` — render PDFs/XPS |
|
||||
| `FlowDocument` | `RichTextBlock` | Partial replacement only |
|
||||
| `RichTextBox` | `RichEditBox` | Rich text editing |
|
||||
| `GroupBox` | `Expander` (built-in) or `HeaderedContentControl` (Toolkit) | See [Layout & Header Controls from CommunityToolkit.WinUI](#layout--header-controls-from-communitytoolkitwinui) below |
|
||||
| `Label` | `TextBlock` | WPF `Label` is a `ContentControl`; use `TextBlock` + `AccessKey` |
|
||||
| `TreeView` | `TreeView` (native) | Available natively, but data binding model differs significantly |
|
||||
| `MediaElement` | `MediaPlayerElement` | Different API |
|
||||
|
||||
## Layout & Header Controls from CommunityToolkit.WinUI
|
||||
|
||||
These WPF layout/header controls have no built-in WinUI 3 equivalent — install the corresponding CommunityToolkit package. **The NuGet package id and the XAML namespace differ intentionally**: package names end in `.Primitives` / `.HeaderedControls`, but both packages register their controls in the shorter `CommunityToolkit.WinUI.Controls` XAML namespace (confirmed in the [official Microsoft Q&A](https://learn.microsoft.com/en-us/answers/questions/5746230/why-does-communitytoolkit-uwp-controls-primitive-u): *"all controls live under `CommunityToolkit.WinUI.Controls` … This is intentional"*).
|
||||
|
||||
| WPF Control | WinUI 3 Replacement | NuGet Package | XAML Namespace |
|
||||
|-------------|---------------------|---------------|----------------|
|
||||
| `WrapPanel` | `WrapPanel` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
| `UniformGrid` | `UniformGrid` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
| `DockPanel` | `DockPanel` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
| `GroupBox` (alt.) | `HeaderedContentControl` | `CommunityToolkit.WinUI.Controls.HeaderedControls` | `using:CommunityToolkit.WinUI.Controls` |
|
||||
|
||||
Other primitives in `Primitives`: `ConstrainedBox`, `SwitchPresenter`, `WrapLayout`, `StaggeredPanel`. Other Headered controls in `HeaderedControls`: `HeaderedItemsControl`, `HeaderedTreeView`.
|
||||
|
||||
## NuGet Package Migration
|
||||
|
||||
@@ -164,11 +124,6 @@ Other primitives in `Primitives`: `ConstrainedBox`, `SwitchPresenter`, `WrapLayo
|
||||
| (none) | `WinUIEx` | Optional, window helpers |
|
||||
| (none) | `CommunityToolkit.WinUI.Converters` | Optional |
|
||||
| (none) | `CommunityToolkit.WinUI.Extensions` | Optional |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.Primitives` | Optional — `WrapPanel`, `UniformGrid`, `DockPanel`, `ConstrainedBox`, `SwitchPresenter` |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.HeaderedControls` | Optional — `HeaderedContentControl`, `HeaderedItemsControl`, `HeaderedTreeView` |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.SettingsControls` | Optional — `SettingsCard`, `SettingsExpander` |
|
||||
| (none) | `CommunityToolkit.WinUI.Controls.Sizers` | Optional — `GridSplitter`, `PropertySizer` |
|
||||
| (none) | `CommunityToolkit.WinUI.UI.Controls.DataGrid` | Legacy v7 — only if migrating existing `DataGrid` code; prefer [`WinUI.TableView`](https://github.com/w-ahmad/WinUI.TableView) for new work |
|
||||
| (none) | `Microsoft.Web.WebView2` | If using WebView |
|
||||
|
||||
## Project File Changes
|
||||
@@ -212,9 +167,8 @@ Other primitives in `Primitives`: `ConstrainedBox`, `SwitchPresenter`, `WrapLayo
|
||||
Key changes:
|
||||
- `UseWPF` → `UseWinUI`
|
||||
- TFM: `net8.0-windows` → `net8.0-windows10.0.19041.0`
|
||||
- **CRITICAL: Add `WindowsPackageType=None`** — marks the app as unpackaged (no MSIX). Without this, the build produces an MSIX-style package that won't run as a standalone PowerToys module.
|
||||
- **CRITICAL: Add `WindowsAppSDKSelfContained=true`** — bundles the Windows App SDK runtime DLLs (e.g. `Microsoft.UI.Xaml.dll`) into the output directory. Without this, the app throws `COMException: ClassFactory cannot supply requested class` at startup because the WinUI 3 COM classes cannot be found.
|
||||
- Add `SelfContained=true` (usually via `Common.SelfContained.props`)
|
||||
- Add `WindowsPackageType=None` for unpackaged desktop apps
|
||||
- Add `SelfContained=true` + `WindowsAppSDKSelfContained=true`
|
||||
- Add `DISABLE_XAML_GENERATED_MAIN` if using custom `Program.cs` entry point
|
||||
- Set `ProjectPriFileName` to match your module's assembly name
|
||||
- Move icon from `Resources/` to `Assets/<Module>/`
|
||||
|
||||
@@ -127,74 +127,6 @@ If the module uses the `WPF-UI` library, replace all Lepo controls with native W
|
||||
</Window>
|
||||
```
|
||||
|
||||
#### Recommended: Use WindowEx from WinUIEx
|
||||
|
||||
> **Tip:** Prefer `WinUIEx.WindowEx` over bare `Window`. It restores many WPF-like window properties directly in XAML, avoiding boilerplate code-behind for common windowing tasks.
|
||||
|
||||
```xml
|
||||
<!-- WinUI 3 with WindowEx (preferred in PowerToys) -->
|
||||
<winuiex:WindowEx
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
x:Class="MyApp.MainWindow"
|
||||
MinWidth="480"
|
||||
MinHeight="320"
|
||||
IsShownInSwitchers="True"
|
||||
IsTitleBarVisible="True">
|
||||
<Window.SystemBackdrop>
|
||||
<MicaBackdrop />
|
||||
</Window.SystemBackdrop>
|
||||
<Grid>
|
||||
...
|
||||
</Grid>
|
||||
</winuiex:WindowEx>
|
||||
```
|
||||
|
||||
Properties available on `WindowEx` that mirror WPF `Window`:
|
||||
|
||||
| WPF Window Property | WindowEx Property | Notes |
|
||||
|---------------------|-------------------|-------|
|
||||
| `MinWidth` / `MinHeight` | `MinWidth` / `MinHeight` | Set directly in XAML |
|
||||
| `Width` / `Height` | `Width` / `Height` | Initial window size |
|
||||
| `WindowState` | `WindowState` | Minimized, Maximized, Normal |
|
||||
| `Title` | `Title` or `x:Uid` | Window title |
|
||||
| `Icon` | Use `TitleBar.IconSource` | Via WinUI TitleBar control |
|
||||
| `ShowInTaskbar` | `IsShownInSwitchers` | Alt-Tab visibility |
|
||||
| `TopMost` | `IsAlwaysOnTop` | Always-on-top window |
|
||||
|
||||
NuGet: `WinUIEx` — already referenced by most PowerToys modules.
|
||||
|
||||
#### Recommended: Page-in-Window Architecture
|
||||
|
||||
> **Tip:** WinUI 3 `Window` is NOT a `FrameworkElement` — it does not support `Resources`, `DataContext`, `x:Bind`, or `VisualStateManager` directly. Place a `Page` as the Window's root content to regain these WPF-like capabilities.
|
||||
|
||||
```xml
|
||||
<!-- WinUI 3 — Window contains a Page for full FrameworkElement support -->
|
||||
<winuiex:WindowEx x:Class="MyApp.MainWindow"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
xmlns:views="using:MyApp.Views">
|
||||
<views:MainPage x:Name="mainPage" />
|
||||
</winuiex:WindowEx>
|
||||
```
|
||||
|
||||
```xml
|
||||
<!-- MainPage.xaml — has full FrameworkElement capabilities -->
|
||||
<Page x:Class="MyApp.Views.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<Page.Resources>
|
||||
<!-- Resources work here (unlike on Window) -->
|
||||
<SolidColorBrush x:Key="MyBrush" Color="Red"/>
|
||||
</Page.Resources>
|
||||
<Grid>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<!-- VisualStateManager works here (unlike on Window) -->
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
...
|
||||
</Grid>
|
||||
</Page>
|
||||
```
|
||||
|
||||
This is the standard pattern in PowerToys (e.g., FileLocksmith, EnvironmentVariables).
|
||||
|
||||
### App.xaml Resources
|
||||
|
||||
```xml
|
||||
@@ -218,20 +150,6 @@ This is the standard pattern in PowerToys (e.g., FileLocksmith, EnvironmentVaria
|
||||
</Application.Resources>
|
||||
```
|
||||
|
||||
### CommunityToolkit.WinUI — WPF Replacement Controls
|
||||
|
||||
> **Tip:** The `CommunityToolkit.WinUI` package provides many controls and helpers familiar to WPF developers that are missing from WinUI 3 out of the box. Before writing custom replacements, check whether CommunityToolkit already provides what you need.
|
||||
|
||||
Key packages (XAML namespace is `using:CommunityToolkit.WinUI.Controls` for the `Controls.*` family):
|
||||
- **`CommunityToolkit.WinUI.Controls.Primitives`** — `WrapPanel`, `UniformGrid`, `DockPanel`, `ConstrainedBox`, `SwitchPresenter`
|
||||
- **`CommunityToolkit.WinUI.Controls.HeaderedControls`** — `HeaderedContentControl`, `HeaderedItemsControl`, `HeaderedTreeView`
|
||||
- **`CommunityToolkit.WinUI.Controls.SettingsControls`** — `SettingsCard`, `SettingsExpander`
|
||||
- **`CommunityToolkit.WinUI.Controls.Sizers`** — `GridSplitter`, `PropertySizer`, `ContentSizer`
|
||||
- **`CommunityToolkit.WinUI.UI.Controls.DataGrid`** — legacy v7 `DataGrid` (no longer maintained); prefer [`WinUI.TableView`](https://github.com/w-ahmad/WinUI.TableView) for new work
|
||||
- **`CommunityToolkit.WinUI.Converters`** — Common value converters (`BoolToVisibilityConverter`, `StringFormatConverter`, etc.)
|
||||
- **`CommunityToolkit.WinUI.Behaviors`** — XAML behaviors for animations and interactions
|
||||
- **`CommunityToolkit.WinUI.Extensions`** — Extension methods for WinUI types
|
||||
|
||||
### Common Control Replacements
|
||||
|
||||
```xml
|
||||
@@ -269,135 +187,11 @@ Key packages (XAML namespace is `using:CommunityToolkit.WinUI.Controls` for the
|
||||
<!-- Handle Enter/Escape keys in code-behind if needed -->
|
||||
```
|
||||
|
||||
## No-Equivalent Patterns (Requires Architectural Rework)
|
||||
|
||||
These WPF features demand design changes, not find-and-replace. Read this section BEFORE attempting to migrate any file that uses these patterns.
|
||||
|
||||
### MultiBinding → x:Bind Function Binding
|
||||
|
||||
WinUI does not support `MultiBinding`. Replace with `x:Bind` function binding (most direct replacement), a computed ViewModel property, or multiple simple bindings.
|
||||
|
||||
**WPF:**
|
||||
```xml
|
||||
<TextBlock>
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0} {1}">
|
||||
<Binding Path="FirstName" />
|
||||
<Binding Path="LastName" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
```
|
||||
|
||||
**WinUI 3:**
|
||||
```xml
|
||||
<TextBlock Text="{x:Bind local:Converters.FormatFullName(ViewModel.FirstName, ViewModel.LastName), Mode=OneWay}" />
|
||||
```
|
||||
|
||||
```csharp
|
||||
public static class Converters
|
||||
{
|
||||
public static string FormatFullName(string first, string last) => $"{first} {last}";
|
||||
}
|
||||
```
|
||||
|
||||
### Adorners → Context-Dependent Replacements
|
||||
|
||||
WPF's `AdornerLayer` has no WinUI equivalent. Choose replacement by use case:
|
||||
|
||||
| Adorner Use Case | WinUI 3 Replacement |
|
||||
|------------------|---------------------|
|
||||
| Validation indicators | `TeachingTip`, `InfoBar`, or InputValidation templates |
|
||||
| Resize handles | `Popup` positioned relative to target |
|
||||
| Drag preview | `DragItemsStarting` event with custom DragUI |
|
||||
| Overlay decorations | Canvas overlay or Popup layer |
|
||||
| Watermark / Placeholder | `TextBox.PlaceholderText` (built-in) |
|
||||
|
||||
### RoutedUICommand → ICommand / RelayCommand
|
||||
|
||||
WinUI does not support routed commands or `CommandBinding`. Replace with standard `ICommand` pattern:
|
||||
|
||||
```csharp
|
||||
// CommunityToolkit.Mvvm
|
||||
[RelayCommand(CanExecute = nameof(CanSave))]
|
||||
private void Save() { /* save logic */ }
|
||||
private bool CanSave() => IsDirty;
|
||||
```
|
||||
|
||||
WinUI 3 also provides `StandardUICommand` and `XamlUICommand` for pre-defined platform commands (Cut, Copy, Paste, Delete) with built-in icons and keyboard accelerators.
|
||||
|
||||
### Tunneling / Preview Events
|
||||
|
||||
WinUI has no tunneling event model. `PreviewMouseDown`, `PreviewKeyDown`, etc. do not exist.
|
||||
|
||||
- Replace with the bubbling equivalent (`PointerPressed`, `KeyDown`)
|
||||
- If you relied on tunneling to intercept events before children, restructure using the `Handled` property
|
||||
- For must-handle scenarios, use `AddHandler` with `handledEventsToo: true`:
|
||||
```csharp
|
||||
myElement.AddHandler(UIElement.PointerPressedEvent,
|
||||
new PointerEventHandler(OnPointerPressed), handledEventsToo: true);
|
||||
```
|
||||
|
||||
## Style and Template Changes
|
||||
|
||||
### Implicit Styles — Always Use BasedOn
|
||||
|
||||
> **Warning:** In WinUI 3, always use `BasedOn` when overriding default control styles. Without it, your style **replaces the entire default style** rather than extending it.
|
||||
|
||||
```xml
|
||||
<!-- WRONG — replaces entire default style, control may lose all visual appearance -->
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Background" Value="Red" />
|
||||
</Style>
|
||||
|
||||
<!-- CORRECT — extends the default style -->
|
||||
<Style TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}">
|
||||
<Setter Property="Background" Value="Red" />
|
||||
</Style>
|
||||
```
|
||||
|
||||
### Triggers → VisualStateManager
|
||||
|
||||
WPF `Triggers`, `DataTriggers`, and `EventTriggers` are not supported. Two replacement approaches:
|
||||
|
||||
#### Approach 1: StateTrigger (direct DataTrigger replacement — simpler)
|
||||
|
||||
Use this for data-driven state changes. This is the closest equivalent to WPF `DataTrigger`:
|
||||
|
||||
**WPF:**
|
||||
```xml
|
||||
<Style TargetType="Border">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsActive}" Value="True">
|
||||
<Setter Property="Background" Value="Green" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
```
|
||||
|
||||
**WinUI 3:**
|
||||
```xml
|
||||
<Border x:Name="MyBorder">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup>
|
||||
<VisualState x:Name="Active">
|
||||
<VisualState.StateTriggers>
|
||||
<StateTrigger IsActive="{x:Bind ViewModel.IsActive, Mode=OneWay}" />
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="MyBorder.Background" Value="Green" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Border>
|
||||
```
|
||||
|
||||
Note: `VisualStateManager` must be placed on a control inside the Window, NOT on the Window itself.
|
||||
|
||||
#### Approach 2: ControlTemplate (for property triggers like IsMouseOver)
|
||||
|
||||
Use this when replacing `<Trigger Property="IsMouseOver">` or similar control-state triggers:
|
||||
WPF `Triggers`, `DataTriggers`, and `EventTriggers` are not supported.
|
||||
|
||||
**WPF:**
|
||||
```xml
|
||||
@@ -406,6 +200,9 @@ Use this when replacing `<Trigger Property="IsMouseOver">` or similar control-st
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="LightBlue"/>
|
||||
</Trigger>
|
||||
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.5"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
```
|
||||
@@ -452,42 +249,11 @@ Use this when replacing `<Trigger Property="IsMouseOver">` or similar control-st
|
||||
| `Disabled` | `Disabled` |
|
||||
| `Pressed` | `Pressed` |
|
||||
|
||||
## Visibility.Hidden — No Equivalent
|
||||
|
||||
WinUI only has `Visible` and `Collapsed`. There is no `Hidden`.
|
||||
|
||||
| WPF | WinUI 3 | Behavior |
|
||||
|-----|---------|----------|
|
||||
| `Visibility.Visible` | `Visibility.Visible` | Rendered and occupies layout space |
|
||||
| `Visibility.Hidden` | **Not available** | Use `Opacity="0"` with `Visibility="Visible"` to hide but keep layout |
|
||||
| `Visibility.Collapsed` | `Visibility.Collapsed` | Not rendered, no layout space |
|
||||
|
||||
## Resource Dictionary Changes
|
||||
|
||||
### XamlControlsResources Must Be First
|
||||
### Window.Resources → Grid.Resources
|
||||
|
||||
> **Warning:** `XamlControlsResources` must be the **first** merged dictionary in `App.xaml`. It provides the default Fluent styles. Omitting it gives you controls with no visual appearance. Resource paths use `ms-appx:///` instead of relative paths.
|
||||
|
||||
```xml
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!-- MUST be first -->
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<!-- Then your custom dictionaries -->
|
||||
<ResourceDictionary Source="ms-appx:///Styles/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
```
|
||||
|
||||
### Window.Resources → Grid.Resources (or use Page)
|
||||
|
||||
WinUI 3 `Window` is NOT a `FrameworkElement` — no `Window.Resources`, `DataContext`, or `VisualStateManager`.
|
||||
|
||||
**Preferred approach:** Use the [Page-in-Window architecture](#recommended-page-in-window-architecture) described above. A `Page` inside the `Window` gives you full `FrameworkElement` capabilities (Resources, DataContext, x:Bind, VisualStateManager).
|
||||
|
||||
**Fallback** (for simple windows without a Page):
|
||||
WinUI 3 `Window` is NOT a `DependencyObject` — no `Window.Resources`, `DataContext`, or `VisualStateManager`.
|
||||
|
||||
```xml
|
||||
<!-- WPF -->
|
||||
@@ -551,25 +317,19 @@ Both are available. Prefer `{x:Bind}` for compile-time safety and performance.
|
||||
| Performance | Reflection-based | Compiled |
|
||||
| Function binding | No | Yes |
|
||||
|
||||
### Binding Differences from WPF
|
||||
|
||||
These WPF binding patterns behave differently in WinUI 3 — review on a case-by-case basis rather than mechanically removing.
|
||||
### WPF-Specific Binding Features to Remove
|
||||
|
||||
```xml
|
||||
<!-- UpdateSourceTrigger: limited support in WinUI 3 -->
|
||||
<!-- These WPF-only features must be removed or rewritten -->
|
||||
<TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<!-- WinUI 3: UpdateSourceTrigger=LostFocus does NOT exist; PropertyChanged is the TextBox default.
|
||||
Prefer x:Bind, which binds with PropertyChanged semantics by default for TwoWay. -->
|
||||
<!-- WinUI 3: UpdateSourceTrigger not needed; TextBox uses PropertyChanged by default -->
|
||||
<TextBox Text="{x:Bind ViewModel.Value, Mode=TwoWay}" />
|
||||
|
||||
<!-- RelativeSource: Self and TemplatedParent ARE supported in WinUI 3 -->
|
||||
<TextBlock Text="{Binding Tag, RelativeSource={RelativeSource Self}}" />
|
||||
<!-- Works in WinUI 3. FindAncestor mode is NOT supported — use ElementName, x:Bind,
|
||||
or the CommunityToolkit FrameworkElementExtensions.Ancestor attached property to reach ancestors. -->
|
||||
{Binding RelativeSource={RelativeSource Self}, ...}
|
||||
<!-- WinUI 3: Use x:Bind which binds to the page itself, or use ElementName -->
|
||||
|
||||
<!-- {Binding} empty path: works in WinUI 3 (binds to the current DataContext) -->
|
||||
<ItemsControl ItemsSource="{Binding}" />
|
||||
<!-- This is valid. Note: x:Bind requires an explicit path — there is no empty-path x:Bind. -->
|
||||
<!-- WinUI 3: Must specify explicit path -->
|
||||
<ItemsControl ItemsSource="{x:Bind ViewModel.Items}" />
|
||||
```
|
||||
|
||||
@@ -595,64 +355,6 @@ ExtendsContentIntoTitleBar="True" <!-- Set in code-behind -->
|
||||
| `IsHitTestVisible` | `IsHitTestVisible` | Same |
|
||||
| `TextBox.VerticalScrollBarVisibility` | `ScrollViewer.VerticalScrollBarVisibility` (attached) | Attached property |
|
||||
|
||||
## Complete Find-and-Replace Reference
|
||||
|
||||
Use this table for mechanical batch translation. Apply these rules consistently to every file.
|
||||
|
||||
### XAML Attribute Replacements
|
||||
|
||||
| Find | Replace With | Context |
|
||||
|------|-------------|---------|
|
||||
| `ContextMenu=` | `ContextFlyout=` | On any UIElement |
|
||||
| `{DynamicResource ` | `{ThemeResource ` | Theme-responsive references |
|
||||
| `{x:Static prefix:Resources.Key}` | `x:Uid="Key"` (with `.resw`) | Resource string — most common WPF case; mechanical `{x:Bind}` will NOT compile here |
|
||||
| `{x:Static prefix:Type.Member}` | `{x:Bind prefix:Type.Member}` | Static field/property reference (function binding) |
|
||||
| `Visibility="Hidden"` | `Visibility="Collapsed"` | Or use `Opacity="0"` for layout |
|
||||
| `MouseLeftButtonDown` | `PointerPressed` | Event handlers |
|
||||
| `MouseLeftButtonUp` | `PointerReleased` | Event handlers |
|
||||
| `MouseRightButtonDown` | `RightTapped` | Or `PointerPressed` + check `IsRightButtonPressed` |
|
||||
| `MouseRightButtonUp` | `PointerReleased` + check `IsRightButtonPressed` | No direct WinUI event; use `RightTapped` only for context-menu-open semantics |
|
||||
| `MouseEnter` | `PointerEntered` | Event handlers |
|
||||
| `MouseLeave` | `PointerExited` | Event handlers |
|
||||
| `MouseMove` | `PointerMoved` | Event handlers |
|
||||
| `MouseWheel` | `PointerWheelChanged` | Event handlers |
|
||||
| `MouseDoubleClick` | `DoubleTapped` | Event handlers |
|
||||
| `PreviewMouseDown` | `PointerPressed` | No tunneling in WinUI — remove Preview |
|
||||
| `PreviewMouseUp` | `PointerReleased` | No tunneling in WinUI — remove Preview |
|
||||
| `PreviewKeyDown` | `KeyDown` | No tunneling in WinUI — remove Preview |
|
||||
| `PreviewKeyUp` | `KeyUp` | No tunneling in WinUI — remove Preview |
|
||||
| `PreviewMouseWheel` | `PointerWheelChanged` | No tunneling in WinUI — remove Preview |
|
||||
| `Focusable="True"` | `IsTabStop="True"` | Focus behavior |
|
||||
| `Focusable="False"` | `IsTabStop="False"` | Focus behavior |
|
||||
| `TextWrapping="WrapWithOverflow"` | `TextWrapping="Wrap"` | TextBlock, TextBox |
|
||||
| `MediaElement` | `MediaPlayerElement` | Media playback |
|
||||
| `clr-namespace:` | `using:` | xmlns declarations |
|
||||
| `;assembly=` | (remove) | Assembly qualification not needed |
|
||||
|
||||
### Code-Behind Replacements
|
||||
|
||||
| Find | Replace With |
|
||||
|------|-------------|
|
||||
| `using System.Windows;` | `using Microsoft.UI.Xaml;` |
|
||||
| `using System.Windows.Controls;` | `using Microsoft.UI.Xaml.Controls;` |
|
||||
| `using System.Windows.Media;` | `using Microsoft.UI.Xaml.Media;` |
|
||||
| `using System.Windows.Data;` | `using Microsoft.UI.Xaml.Data;` |
|
||||
| `using System.Windows.Input;` | `using Microsoft.UI.Xaml.Input;` |
|
||||
| `using System.Windows.Threading;` | `using Microsoft.UI.Dispatching;` |
|
||||
| `using System.Windows.Shapes;` | `using Microsoft.UI.Xaml.Shapes;` |
|
||||
| `using System.Windows.Markup;` | `using Microsoft.UI.Xaml.Markup;` |
|
||||
| `using System.Windows.Automation;` | `using Microsoft.UI.Xaml.Automation;` |
|
||||
| `using System.Windows.Media.Animation;` | `using Microsoft.UI.Xaml.Media.Animation;` |
|
||||
| `using System.Windows.Documents;` | `using Microsoft.UI.Xaml.Documents;` |
|
||||
| `using System.Windows.Navigation;` | `using Microsoft.UI.Xaml.Navigation;` |
|
||||
| `Dispatcher.Invoke(` | `DispatcherQueue.TryEnqueue(` |
|
||||
| `Dispatcher.BeginInvoke(` | `DispatcherQueue.TryEnqueue(` |
|
||||
| `Dispatcher.CheckAccess()` | `DispatcherQueue.HasThreadAccess` |
|
||||
| `MouseEventArgs` | `PointerRoutedEventArgs` |
|
||||
| `KeyEventArgs` | `KeyRoutedEventArgs` |
|
||||
| `RoutedUICommand` | `RelayCommand` (CommunityToolkit.Mvvm) |
|
||||
| `CommandBinding` | Remove; bind ICommand directly |
|
||||
|
||||
## XAML Formatting (XamlStyler)
|
||||
|
||||
After migration, run XamlStyler to normalize formatting:
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
name: Automatic Triaging on Issue/PR Creation
|
||||
name: Automatic Triaging on Issue Creation
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize]
|
||||
# Manual trigger: go to Actions → "Automatic Triaging on Issue Creation" → Run workflow.
|
||||
# Enter one or more comma-separated issue numbers (e.g. "1234" or "1234,1235,1236")
|
||||
# to apply AI-generated area labels to existing untriaged issues.
|
||||
@@ -17,14 +15,12 @@ on:
|
||||
permissions:
|
||||
models: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
# Each workflow run gets its own concurrency group.
|
||||
# For issue events, group by issue number so a rapid close+reopen only runs once.
|
||||
# For pull request events, group by PR number so rapid updates coalesce.
|
||||
# For manual dispatch (which may cover multiple issues), use the unique run ID.
|
||||
group: ${{ github.event_name == 'issues' && format('{0}-issues-{1}', github.workflow, github.event.issue.number) || github.event_name == 'pull_request_target' && format('{0}-pr-{1}', github.workflow, github.event.pull_request.number) || github.run_id }}
|
||||
group: ${{ github.event_name == 'issues' && format('{0}-issue-{1}', github.workflow, github.event.issue.number) || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
@@ -42,7 +38,7 @@ jobs:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
// When triggered manually, process each supplied issue number in turn.
|
||||
// When triggered by an issue or PR event, use the event's number.
|
||||
// When triggered by an issue event, use the event's issue number.
|
||||
let issueNumbers;
|
||||
if (context.eventName === 'workflow_dispatch') {
|
||||
issueNumbers = String(context.payload.inputs.issue_numbers)
|
||||
@@ -59,25 +55,23 @@ jobs:
|
||||
}
|
||||
|
||||
for (const issueNumber of issueNumbers) {
|
||||
console.log(`\n--- Processing item #${issueNumber} ---`);
|
||||
console.log(`\n--- Processing issue #${issueNumber} ---`);
|
||||
await labelIssue(issueNumber);
|
||||
}
|
||||
|
||||
async function labelIssue(issueNumber) {
|
||||
// Fetch as an issue resource; PRs are represented by issues with a pull_request field.
|
||||
// Fetch the issue so both the automatic and manual paths have the same data.
|
||||
const { data: issue } = await github.rest.issues.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
|
||||
const itemType = issue.pull_request ? 'Pull request' : 'Issue';
|
||||
|
||||
const title = issue.title ?? '';
|
||||
const body = issue.body ?? '';
|
||||
|
||||
if (!title && !body) {
|
||||
console.log(`${itemType} #${issueNumber} has no title or body; skipping.`);
|
||||
console.log(`Issue #${issueNumber} has no title or body; skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -94,8 +88,8 @@ jobs:
|
||||
'Product-Advanced Paste',
|
||||
'Product-Always On Top',
|
||||
'Product-Awake',
|
||||
'Product-Color Picker',
|
||||
'Product-CommandNotFound',
|
||||
'Product-ColorPicker',
|
||||
'Product-Command Not Found',
|
||||
'Product-Command Palette',
|
||||
'Product-CropAndLock',
|
||||
'Product-Environment Variables',
|
||||
@@ -104,7 +98,7 @@ jobs:
|
||||
'Product-File Locksmith',
|
||||
'Product-Find My Mouse',
|
||||
'Product-Grab And Move',
|
||||
'Product-Hosts File Editor',
|
||||
'Product-Hosts',
|
||||
'Product-Image Resizer',
|
||||
'Product-Keyboard Manager',
|
||||
'Product-LightSwitch',
|
||||
@@ -115,7 +109,7 @@ jobs:
|
||||
'Product-Mouse Without Borders',
|
||||
'Product-New+',
|
||||
'Product-Peek',
|
||||
'Product-PowerDisplay',
|
||||
'Product-Power Display',
|
||||
'Product-PowerRename',
|
||||
'Product-PowerToys Run',
|
||||
'Product-Quick Accent',
|
||||
@@ -130,8 +124,8 @@ jobs:
|
||||
'Area-Localization',
|
||||
];
|
||||
|
||||
const systemPrompt = `You are a GitHub triage assistant for the microsoft/PowerToys repository.
|
||||
Your job is to classify issues and pull requests by assigning the correct area label(s).
|
||||
const systemPrompt = `You are a GitHub issue triage assistant for the microsoft/PowerToys repository.
|
||||
Your job is to classify issues by assigning the correct area label(s).
|
||||
|
||||
Rules:
|
||||
- Only return labels from the following list, exactly as written:
|
||||
@@ -142,9 +136,9 @@ jobs:
|
||||
- Respond with ONLY a JSON array of label strings, no explanation.
|
||||
Example: ["Product-FancyZones","Product-Settings"]`;
|
||||
|
||||
const userPrompt = `${itemType} title: ${title}
|
||||
const userPrompt = `Issue title: ${title}
|
||||
|
||||
${itemType} body:
|
||||
Issue body:
|
||||
${body.slice(0, MAX_BODY_LENGTH)}`;
|
||||
|
||||
// Validate that the token is available before making the API call.
|
||||
@@ -209,25 +203,11 @@ jobs:
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
labels: toApply,
|
||||
});
|
||||
console.log(`${itemType} #${issueNumber}: added labels: ${toApply.join(', ')}`);
|
||||
} catch (error) {
|
||||
// Some contexts (for example, restricted integrations) can deny
|
||||
// label writes even when workflow permissions request write scope.
|
||||
// Skip without failing the entire triage workflow.
|
||||
const status = error?.status;
|
||||
const message = error?.message ?? String(error);
|
||||
if (status === 403 && message.includes('Resource not accessible by integration')) {
|
||||
console.log(`${itemType} #${issueNumber}: skipping label write due to restricted token context (403).`);
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
labels: toApply,
|
||||
});
|
||||
console.log(`Issue #${issueNumber}: added labels: ${toApply.join(', ')}`);
|
||||
}
|
||||
35
.github/workflows/telemetry-pr-check.yml
vendored
@@ -1,35 +0,0 @@
|
||||
# NOTE: This workflow depends on .github/scripts/telemetry-pr-check.js for telemetry detection and PR comments.
|
||||
# Keep this workflow and script behavior in sync when making changes.
|
||||
name: Telemetry PR Check
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize, ready_for_review]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: "Pull Request Number to test against"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: telemetry-pr-check-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
detect-telemetry-events:
|
||||
if: ${{ github.event.pull_request.draft == false }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Detect telemetry event changes and comment PR
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: node .github/scripts/telemetry-pr-check.js
|
||||
11
.gitignore
vendored
@@ -19,9 +19,6 @@
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
!**/rnnoise/
|
||||
!**/rnnoise/x86/
|
||||
!**/rnnoise/x86/**
|
||||
ARM64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
@@ -373,11 +370,3 @@ installer/*/*.wxs.bk
|
||||
.squad-workstream
|
||||
.github/agents/**squad**.md
|
||||
.github/workflows/**squad**.yml
|
||||
|
||||
# vcpkg manifest mode installed packages
|
||||
vcpkg_installed/
|
||||
|
||||
deps/vcpkg/
|
||||
|
||||
# Superpowers-generated docs (specs, design, plans) — local-only, not committed
|
||||
docs/superpowers/
|
||||
|
||||
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "deps/spdlog"]
|
||||
path = deps/spdlog
|
||||
url = https://github.com/gabime/spdlog.git
|
||||
[submodule "deps/expected-lite"]
|
||||
path = deps/expected-lite
|
||||
url = https://github.com/martinmoene/expected-lite.git
|
||||
@@ -212,7 +212,6 @@
|
||||
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.win10.dll",
|
||||
|
||||
"PowerAccent.Core.dll",
|
||||
"PowerAccent.Common.dll",
|
||||
"PowerToys.PowerAccent.dll",
|
||||
"PowerToys.PowerAccent.exe",
|
||||
"PowerToys.PowerAccentModuleInterface.dll",
|
||||
@@ -244,12 +243,8 @@
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.exe",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.dll",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.IndexYmlGenerator.dll",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe",
|
||||
"WinUI3Apps\\ShortcutGuide.CPPProject.dll",
|
||||
"PowerToys.ShortcutGuide.exe",
|
||||
"PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
|
||||
"PowerToys.ZoomIt.exe",
|
||||
"PowerToys.ZoomItModuleInterface.dll",
|
||||
@@ -388,11 +383,6 @@
|
||||
"ColorCode.Core.dll",
|
||||
"Microsoft.SemanticKernel.Connectors.Ollama.dll",
|
||||
"OllamaSharp.dll",
|
||||
"WinUI3Apps\\Google.Apis.dll",
|
||||
"WinUI3Apps\\Google.Apis.Auth.dll",
|
||||
"WinUI3Apps\\Google.Apis.Core.dll",
|
||||
"WinUI3Apps\\Google.GenAI.dll",
|
||||
"WinUI3Apps\\YamlDotNet.dll",
|
||||
|
||||
"boost_regex-vc143-mt-gd-x32-1_87.dll",
|
||||
"boost_regex-vc143-mt-gd-x64-1_87.dll",
|
||||
|
||||
@@ -104,10 +104,6 @@ extends:
|
||||
# Have msbuild use the release nuget config profile
|
||||
additionalBuildOptions: /p:RestoreConfigFile="$(Build.SourcesDirectory)\.pipelines\release-nuget.config" /p:EnableCmdPalAOT=true
|
||||
beforeBuildSteps:
|
||||
# Install the Terrapin retrieval tool, which replaces vcpkg's download handler
|
||||
# to redirect it to a safe Microsoft-controlled location
|
||||
- template: .pipelines/v2/templates/steps-install-terrapin.yml@self
|
||||
|
||||
# Sets versions for all PowerToy created DLLs
|
||||
- pwsh: |-
|
||||
.pipelines/versionSetting.ps1 -versionNumber '${{ parameters.versionNumber }}' -DevEnvironment ''
|
||||
@@ -144,10 +140,6 @@ extends:
|
||||
signCertName: $(SigningSignCertName)
|
||||
useManagedIdentity: $(SigningUseManagedIdentity)
|
||||
clientId: $(SigningOriginalClientId)
|
||||
beforeBuildSteps:
|
||||
# Install the Terrapin retrieval tool, which replaces vcpkg's download handler
|
||||
# to redirect it to a safe Microsoft-controlled location
|
||||
- template: .pipelines/v2/templates/steps-install-terrapin.yml@self
|
||||
|
||||
- stage: Publish
|
||||
displayName: Publish
|
||||
|
||||
@@ -270,34 +270,6 @@ jobs:
|
||||
parameters:
|
||||
directory: $(build.sourcesdirectory)\src\modules\cmdpal
|
||||
|
||||
# --- vcpkg detection + binary cache --------------------------------------
|
||||
# PowerToys consumes spdlog (and, over time, other native deps) via vcpkg in
|
||||
# manifest mode. steps-install-vcpkg.yml prefers the vcpkg shipped with
|
||||
# Visual Studio (Microsoft.VisualStudio.Component.Vcpkg) and falls back to a
|
||||
# fresh clone of microsoft/vcpkg into deps/vcpkg if VS doesn't have it.
|
||||
# Either way it sets the VCPKG_ROOT pipeline variable; MSBuild integration
|
||||
# is wired globally from Cpp.Build.props (with vcpkg.targets in
|
||||
# Cpp.Build.targets) using the three-tier VcpkgRoot fallback
|
||||
# (env var > VS-shipped > deps/vcpkg runtime clone).
|
||||
#
|
||||
# Vcpkg's MSBuild integration runs `vcpkg install` once per project, so the
|
||||
# binary cache below saves ~3-5 minutes per triplet on cache hits.
|
||||
- template: .\steps-install-vcpkg.yml
|
||||
parameters:
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
|
||||
- ${{ if eq(parameters.enablePackageCaching, true) }}:
|
||||
- task: Cache@2
|
||||
displayName: 'Cache vcpkg binary archives'
|
||||
inputs:
|
||||
# Key on the inputs vcpkg uses to compute its package ABI: the manifest,
|
||||
# configuration, every overlay-port file, and the agent OS.
|
||||
key: '"vcpkg" | "$(Agent.OS)" | vcpkg.json | vcpkg-configuration.json | deps/vcpkg-overlays/**'
|
||||
restoreKeys: |
|
||||
"vcpkg" | "$(Agent.OS)"
|
||||
"vcpkg"
|
||||
path: $(LOCALAPPDATA)\vcpkg\archives
|
||||
|
||||
|
||||
|
||||
- ${{ parameters.beforeBuildSteps }}
|
||||
|
||||
@@ -15,9 +15,6 @@ parameters:
|
||||
- name: signingIdentity
|
||||
type: object
|
||||
default: {}
|
||||
- name: beforeBuildSteps
|
||||
type: stepList
|
||||
default: []
|
||||
|
||||
jobs:
|
||||
- job: "BuildSDK"
|
||||
@@ -48,8 +45,6 @@ jobs:
|
||||
parameters:
|
||||
directory: $(build.sourcesdirectory)\src\modules\cmdpal
|
||||
|
||||
- ${{ parameters.beforeBuildSteps }}
|
||||
|
||||
- pwsh: |-
|
||||
& "$(build.sourcesdirectory)\src\modules\cmdpal\extensionsdk\nuget\BuildSDKHelper.ps1" -Configuration "Release" -BuildStep "build" -IsAzurePipelineBuild
|
||||
displayName: Build SDK
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
steps:
|
||||
- pwsh: |-
|
||||
nuget install -source "https://microsoft.pkgs.visualstudio.com/Dart/_packaging/PowerToysDependencies/nuget/v3/index.json" TerrapinRetrievalTool -Prerelease -OutputDirectory _trt -Config "$(Build.SourcesDirectory)\.pipelines\release-nuget.config"
|
||||
$TerrapinRetrievalToolPath = (Get-Item _trt\TerrapinRetrievalTool.*\win-x64\TerrapinRetrievalTool.exe).FullName
|
||||
Write-Host "##vso[task.setvariable variable=X_VCPKG_ASSET_SOURCES]x-script,${TerrapinRetrievalToolPath} -b https://vcpkg.storage.devpackages.microsoft.io/artifacts/ -a true -u None -p {url} -s {sha512} -d {dst};x-block-origin"
|
||||
displayName: Set up the Terrapin Retrieval Tool (vcpkg cache)
|
||||
@@ -1,41 +0,0 @@
|
||||
# Adapted from microsoft/terminal build/pipelines/templates-v2/steps-install-vcpkg.yml.
|
||||
#
|
||||
# Detects vcpkg from (in order):
|
||||
# 1. The Visual Studio installation (Microsoft.VisualStudio.Component.Vcpkg,
|
||||
# declared in the repo-root .vsconfig).
|
||||
# 2. A local clone at deps/vcpkg, cloned and bootstrapped on demand.
|
||||
#
|
||||
# Sets the pipeline-scoped VCPKG_ROOT variable; the rest of the build
|
||||
# resolves vcpkg through it (see the three-tier VcpkgRoot fallback in
|
||||
# Cpp.Build.props). No repo-level vcpkg submodule required.
|
||||
parameters:
|
||||
- name: useVSPreview
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
steps:
|
||||
- pwsh: |-
|
||||
# vswhere -prerelease is opt-in via the useVSPreview parameter so CI on
|
||||
# stable VS doesn't accidentally pick up a Preview install when both
|
||||
# are present. Matches the existing useVSPreview plumbing for
|
||||
# verifyAndSetLatestVCToolsVersion.ps1.
|
||||
$vswhereArgs = @('-latest', '-requires', 'Microsoft.VisualStudio.Component.Vcpkg', '-property', 'installationPath')
|
||||
$useVSPreview = '${{ parameters.useVSPreview }}' -eq 'True'
|
||||
if ($useVSPreview) { $vswhereArgs = @('-prerelease') + $vswhereArgs }
|
||||
$VsInstallRoot = & 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' @vswhereArgs
|
||||
If ([String]::IsNullOrEmpty($VsInstallRoot)) {
|
||||
Remove-Item -Recurse -Force deps/vcpkg -ErrorAction:Ignore
|
||||
git clone https://github.com/microsoft/vcpkg deps/vcpkg
|
||||
if ($LASTEXITCODE -ne 0) { throw "git clone vcpkg failed (exit $LASTEXITCODE)" }
|
||||
Push-Location deps/vcpkg
|
||||
& ./bootstrap-vcpkg.bat -disableMetrics
|
||||
if ($LASTEXITCODE -ne 0) { Pop-Location; throw "bootstrap-vcpkg failed (exit $LASTEXITCODE)" }
|
||||
$VcpkgRoot = $PWD
|
||||
Pop-Location
|
||||
Write-Host "Using vcpkg from local checkout ($VcpkgRoot)"
|
||||
} Else {
|
||||
$VcpkgRoot = Join-Path $VsInstallRoot 'VC\vcpkg'
|
||||
Write-Host "Using vcpkg from Visual Studio installation ($VcpkgRoot)"
|
||||
}
|
||||
Write-Host "##vso[task.setvariable variable=VCPKG_ROOT]$VcpkgRoot"
|
||||
displayName: Detect VS vcpkg or bootstrap locally
|
||||
@@ -48,11 +48,6 @@ foreach ($csprojFile in $csprojFilesArray) {
|
||||
continue
|
||||
}
|
||||
|
||||
# The PowerAccent.Common project does not target WinRT, so skip it
|
||||
if ($csprojFile -like '*PowerAccent.Common.csproj') {
|
||||
continue
|
||||
}
|
||||
|
||||
$importExists = Test-ImportSharedCsWinRTProps -filePath $csprojFile
|
||||
if (!$importExists) {
|
||||
Write-Output "$csprojFile need to import 'Common.Dotnet.CsWinRT.props'."
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre",
|
||||
"Microsoft.VisualStudio.Component.VC.ATL",
|
||||
"Microsoft.VisualStudio.Component.VC.ATL.Spectre",
|
||||
"Microsoft.VisualStudio.Component.Vcpkg",
|
||||
"Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs"
|
||||
]
|
||||
}
|
||||
@@ -39,8 +39,7 @@
|
||||
<PropertyGroup>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
<PreferredToolArchitecture Condition="'$(PROCESSOR_ARCHITECTURE)' == 'ARM64' or '$(PROCESSOR_ARCHITEW6432)' == 'ARM64'">arm64</PreferredToolArchitecture>
|
||||
<!-- vcpkg.targets is imported via Cpp.Build.targets after Microsoft.Cpp.targets. -->
|
||||
<ForceImportAfterCppTargets>$(MSBuildThisFileDirectory)Cpp.Build.targets</ForceImportAfterCppTargets>
|
||||
<VcpkgEnabled>false</VcpkgEnabled>
|
||||
<ReplaceWildcardsInProjectItems>true</ReplaceWildcardsInProjectItems>
|
||||
<ExternalIncludePath>$(MSBuildThisFileDirectory)deps;$(MSBuildThisFileDirectory)packages;$(ExternalIncludePath)</ExternalIncludePath>
|
||||
<!-- Enable control flow guard for C++ projects that don't consume any C++ files -->
|
||||
@@ -122,48 +121,6 @@
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
vcpkg integration. Set globally and loaded before Microsoft.Cpp.props (via
|
||||
ForceImportBeforeCppProps) so that vcpkg.props' ClCompile hook is in place
|
||||
before the C++ targets run. VcpkgRoot is resolved via the same three-tier
|
||||
fallback used by microsoft/terminal (env var → VS-shipped → deps/vcpkg).
|
||||
-->
|
||||
<PropertyGroup Label="vcpkg">
|
||||
<VcpkgEnabled>true</VcpkgEnabled>
|
||||
<VcpkgEnableManifest>true</VcpkgEnableManifest>
|
||||
<VcpkgManifestEnabled>true</VcpkgManifestEnabled>
|
||||
<VcpkgManifestRoot>$(MSBuildThisFileDirectory)</VcpkgManifestRoot>
|
||||
<VcpkgOSTarget>windows</VcpkgOSTarget>
|
||||
<VcpkgUseStatic>true</VcpkgUseStatic>
|
||||
<!--
|
||||
Force VcpkgConfiguration to follow $(Configuration). Without this,
|
||||
vcpkg.props infers VcpkgConfiguration from $(UseDebugLibraries), which
|
||||
Microsoft.Cpp.Default.props has already defaulted to 'false' by the
|
||||
time vcpkg.props is imported here (the PowerToys-wide Debug override
|
||||
below runs LATER). That would silently link the Release-built spdlog
|
||||
into Debug consumers and trigger LNK2038 (MT/MTd, _ITERATOR_DEBUG_LEVEL).
|
||||
-->
|
||||
<VcpkgConfiguration>$(Configuration)</VcpkgConfiguration>
|
||||
<!-- vcpkg validates triplets case-sensitively; PowerToys uses ARM64 capital-case. -->
|
||||
<VcpkgPlatformTarget Condition="'$(Platform)' == 'ARM64'">arm64</VcpkgPlatformTarget>
|
||||
<VcpkgApplocalDeps>false</VcpkgApplocalDeps>
|
||||
<VcpkgInstalledDir>$(MSBuildThisFileDirectory)vcpkg_installed\$(Platform)\</VcpkgInstalledDir>
|
||||
<VcpkgRoot Condition="'$(VcpkgRoot)' == ''">$(VCPKG_ROOT)</VcpkgRoot>
|
||||
<VcpkgRoot Condition="'$(VcpkgRoot)' == '' and '$(VsInstallRoot)' != ''">$(VsInstallRoot)\VC\vcpkg</VcpkgRoot>
|
||||
<VcpkgRoot Condition="'$(VcpkgRoot)' == '' or !Exists('$(VcpkgRoot)\vcpkg.exe')">$(MSBuildThisFileDirectory)deps\vcpkg</VcpkgRoot>
|
||||
<CAExcludePath>$(CAExcludePath);$(VcpkgInstalledDir)</CAExcludePath>
|
||||
<VCPkgLocalAppDataDisabled>true</VCPkgLocalAppDataDisabled>
|
||||
</PropertyGroup>
|
||||
<!-- Fail fast with an actionable message instead of opaque C1083 spdlog/spdlog.h errors. -->
|
||||
<Target Name="PowerToysEnsureVcpkgAvailable"
|
||||
BeforeTargets="PrepareForBuild"
|
||||
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and '$(VcpkgEnabled)' == 'true' and !Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props')">
|
||||
<Error Text="PowerToys requires the 'vcpkg' Visual Studio component, but it was not found.%0A%0AOpen the Visual Studio Installer, click Modify on your VS install, search for 'vcpkg', enable 'C++ vcpkg package manager', and click Modify. (Visual Studio will also prompt you to install missing .vsconfig components when you open PowerToys.slnx.)%0A%0AIf you have vcpkg installed elsewhere, set the VCPKG_ROOT environment variable to its root before building.%0A%0ASearched: '$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props'" />
|
||||
</Target>
|
||||
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props"
|
||||
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.props')" />
|
||||
|
||||
|
||||
<!-- Debug/Release props -->
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<!--
|
||||
PowerToys global C++ post-targets. Wired in via
|
||||
<ForceImportAfterCppTargets> in Cpp.Build.props so MSBuild loads this
|
||||
file AFTER Microsoft.Cpp.targets for every .vcxproj.
|
||||
|
||||
Conditionally imports vcpkg.targets to hook ClCompile into vcpkg's
|
||||
VcpkgInstallManifestDependencies target so spdlog headers are
|
||||
auto-discovered on the include path and spdlog.lib is auto-linked.
|
||||
vcpkg.props is imported in Cpp.Build.props (before Microsoft.Cpp.props);
|
||||
vcpkg.targets needs the matching "after" hook here.
|
||||
-->
|
||||
<Import Project="$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets"
|
||||
Condition="'$(MSBuildProjectExtension)' == '.vcxproj' and '$(VcpkgEnabled)' == 'true' and Exists('$(VcpkgRoot)\scripts\buildsystems\msbuild\vcpkg.targets')" />
|
||||
</Project>
|
||||
@@ -41,34 +41,34 @@
|
||||
<PackageVersion Include="MessagePack" Version="3.1.3" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.102" />
|
||||
<PackageVersion Include="Microsoft.CommandPalette.Extensions" Version="0.9.260303001" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.7" />
|
||||
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
|
||||
<PackageVersion Include="Microsoft.Windows.CppWinRT" Version="2.0.250303.1" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.2.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.0.1-preview.1.25571.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI" Version="9.9.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.9.1-preview.1.25474.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.AI.Foundry.Local" Version="0.3.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.71.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.71.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureAIInference" Version="1.71.0-beta" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.71.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.MistralAI" Version="1.71.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.71.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.66.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.66.0" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureAIInference" Version="1.66.0-beta" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.66.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.MistralAI" Version="1.66.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.66.0-alpha" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3719.77" />
|
||||
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="10.0.8" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="10.0.7" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.269" />
|
||||
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
||||
<!--
|
||||
@@ -78,10 +78,10 @@
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.250325.1"/>
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="2.1.0" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="2.2.3" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="2.0.1" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="2.0.20" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="2.0.185" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="2.0.1" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
|
||||
@@ -90,12 +90,11 @@
|
||||
<PackageVersion Include="MSTest" Version="$(MSTestVersion)" />
|
||||
<PackageVersion Include="MSTest.TestFramework" Version="$(MSTestVersion)" />
|
||||
<PackageVersion Include="NJsonSchema" Version="11.4.0" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageVersion Include="NLog" Version="5.2.8" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
|
||||
<PackageVersion Include="OpenAI" Version="2.7.0" />
|
||||
<PackageVersion Include="Polly.Core" Version="8.6.5" />
|
||||
<PackageVersion Include="OpenAI" Version="2.5.0" />
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="RtfPipe" Version="2.0.7677.4303" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
@@ -106,28 +105,28 @@
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.CodeDom" Version="10.0.8" />
|
||||
<PackageVersion Include="System.CodeDom" Version="10.0.7" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="10.0.8" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="10.0.7" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="10.0.7" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="10.0.7" />
|
||||
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="10.0.7" />
|
||||
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="10.0.8" />
|
||||
<PackageVersion Include="System.ClientModel" Version="1.8.1" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="10.0.7" />
|
||||
<PackageVersion Include="System.ClientModel" Version="1.7.0" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="10.0.7" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
|
||||
<PackageVersion Include="System.Management" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Management" Version="10.0.7" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Numerics.Tensors" Version="10.0.2" />
|
||||
<PackageVersion Include="System.Numerics.Tensors" Version="9.0.11" />
|
||||
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="10.0.8" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.8" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="10.0.7" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="10.0.7" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.7" />
|
||||
<PackageVersion Include="System.Text.Json" Version="10.0.7" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="ToolGood.Words.Pinyin" Version="3.1.0.3" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
@@ -135,8 +134,8 @@
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />
|
||||
<PackageVersion Include="WinUIEx" Version="2.8.0" />
|
||||
<PackageVersion Include="WmiLight" Version="6.14.0" />
|
||||
<PackageVersion Include="WPF-UI" Version="3.0.5" />
|
||||
<PackageVersion Include="WyHash" Version="1.0.5" />
|
||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageVersion Include="WixToolset.Heat" Version="5.0.2" />
|
||||
<PackageVersion Include="WixToolset.Firewall.wixext" Version="5.0.2" />
|
||||
<PackageVersion Include="WixToolset.Util.wixext" Version="5.0.2" />
|
||||
|
||||
@@ -1600,5 +1600,5 @@ SOFTWARE.
|
||||
- UTF.Unknown
|
||||
- WinUIEx
|
||||
- WmiLight
|
||||
- WPF-UI
|
||||
- WyHash
|
||||
- YamlDotNet
|
||||
@@ -57,7 +57,6 @@
|
||||
<Project Path="src/common/UnitTests-CommonLib/UnitTests-CommonLib.vcxproj" Id="1a066c63-64b3-45f8-92fe-664e1cce8077" />
|
||||
<Project Path="src/common/UnitTests-CommonUtils/UnitTests-CommonUtils.vcxproj" Id="8b5cfb38-ccba-40a8-ad7a-89c57b070884" />
|
||||
<Project Path="src/common/updating/updating.vcxproj" Id="17da04df-e393-4397-9cf0-84dabe11032e" />
|
||||
<Project Path="src/common/updating/UnitTests/UpdatingUnitTests.vcxproj" Id="a1b2c3d4-e5f6-7890-abcd-ef1234567890" />
|
||||
<Project Path="src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
||||
</Folder>
|
||||
<Folder Name="/common/interop/">
|
||||
@@ -68,7 +67,10 @@
|
||||
<Project Path="src/common/interop/PowerToys.Interop.vcxproj" Id="f055103b-f80b-4d0c-bf48-057c55620033" />
|
||||
</Folder>
|
||||
<Folder Name="/common/log/">
|
||||
<Project Path="src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd" />
|
||||
<Project Path="src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd">
|
||||
<BuildDependency Project="src/logging/logging.vcxproj" />
|
||||
</Project>
|
||||
<Project Path="src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f" />
|
||||
</Folder>
|
||||
<Folder Name="/common/notifications/">
|
||||
<Project Path="src/common/notifications/BackgroundActivator/BackgroundActivator.vcxproj" Id="0b593a6c-4143-4337-860e-db5710fb87db" />
|
||||
@@ -799,14 +801,6 @@
|
||||
<Project Path="src/modules/peek/peek/peek.vcxproj" Id="a1425b53-3d61-4679-8623-e64a0d3d0a48" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/PowerAccent/">
|
||||
<Project Path="src/modules/poweraccent/PowerAccent.Common.UnitTests/PowerAccent.Common.UnitTests.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/poweraccent/PowerAccent.Common/PowerAccent.Common.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/poweraccent/PowerAccent.Core/PowerAccent.Core.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
@@ -995,16 +989,9 @@
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Folder Name="/modules/ShortcutGuide/">
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/ShortcutGuide.IndexYmlGenerator.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="e487304a-b1fb-4e6b-8e70-014051af5b99" />
|
||||
<Folder Name="/modules/shortcutguide/">
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuide/ShortcutGuide.vcxproj" Id="2edb3eb4-fa92-4bff-b2d8-566584837231" />
|
||||
<Project Path="src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj" Id="2d604c07-51fc-46bb-9eb7-75aecc7f5e81" />
|
||||
</Folder>
|
||||
<Folder Name="/modules/Workspaces/">
|
||||
<Project Path="src/modules/Workspaces/Workspaces.ModuleServices/Workspaces.ModuleServices.csproj">
|
||||
@@ -1139,5 +1126,3 @@
|
||||
<Project Path="src/Update/PowerToys.Update.vcxproj" Id="44ce9ae1-4390-42c5-bacc-0fd6b40aa203" />
|
||||
<Project Path="tools/project_template/ModuleTemplate/ModuleTemplateCompileTest.vcxproj" Id="64a80062-4d8b-4229-8a38-dfa1d7497749" />
|
||||
</Solution>
|
||||
|
||||
|
||||
|
||||
1
deps/expected-lite
vendored
Submodule
7
deps/expected.props
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<Project>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)expected-lite\include\nonstd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
1
deps/spdlog
vendored
Submodule
94
deps/spdlog-msvc-fix/include/spdlog-msvc-fix.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// spdlog-msvc-fix.h
|
||||
//
|
||||
// Workaround for MSVC 14.51 (compiler version 19.51, _MSC_VER >= 1951) removing
|
||||
// stdext::checked_array_iterator. Force-included for all spdlog consumers via
|
||||
// deps/spdlog.props, because spdlog v1.8.5's bundled fmt format.h(357) still
|
||||
// references this type inside #if defined(_SECURE_SCL) && _SECURE_SCL -- a
|
||||
// branch entered in Debug builds where _ITERATOR_DEBUG_LEVEL > 0.
|
||||
//
|
||||
// On MSVC 14.50 and earlier, the type still exists in <iterator>, so this shim
|
||||
// is a no-op via the _MSC_VER guard. On MSVC 14.51+, it provides a minimal
|
||||
// pointer-backed substitute that satisfies the bundled fmt's usage:
|
||||
//
|
||||
// template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
|
||||
// template <typename T> checked_ptr<T> make_checked(T* p, size_t size) {
|
||||
// return {p, size};
|
||||
// }
|
||||
// ... return make_checked(get_data(c) + size, n);
|
||||
//
|
||||
// When deps/spdlog is bumped past v1.14 (which ships fmt 10.2 and drops this
|
||||
// dependency), this shim and its <ForcedIncludeFiles> entry in deps/spdlog.props
|
||||
// can be deleted.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER >= 1951
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace stdext
|
||||
{
|
||||
template <typename _Ptr>
|
||||
class checked_array_iterator
|
||||
{
|
||||
_Ptr _Myarray = nullptr;
|
||||
std::size_t _Mysize = 0;
|
||||
std::size_t _Myindex = 0;
|
||||
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = std::remove_cv_t<std::remove_pointer_t<_Ptr>>;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = _Ptr;
|
||||
using reference = std::remove_pointer_t<_Ptr>&;
|
||||
|
||||
constexpr checked_array_iterator() = default;
|
||||
|
||||
constexpr checked_array_iterator(_Ptr arr, std::size_t size, std::size_t idx = 0) noexcept
|
||||
: _Myarray(arr), _Mysize(size), _Myindex(idx)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr reference operator*() const noexcept { return _Myarray[_Myindex]; }
|
||||
constexpr pointer operator->() const noexcept { return _Myarray + _Myindex; }
|
||||
constexpr reference operator[](difference_type n) const noexcept
|
||||
{
|
||||
return _Myarray[_Myindex + static_cast<std::size_t>(n)];
|
||||
}
|
||||
|
||||
constexpr checked_array_iterator& operator++() noexcept { ++_Myindex; return *this; }
|
||||
constexpr checked_array_iterator operator++(int) noexcept { auto t = *this; ++_Myindex; return t; }
|
||||
constexpr checked_array_iterator& operator--() noexcept { --_Myindex; return *this; }
|
||||
constexpr checked_array_iterator operator--(int) noexcept { auto t = *this; --_Myindex; return t; }
|
||||
|
||||
constexpr checked_array_iterator& operator+=(difference_type n) noexcept
|
||||
{
|
||||
_Myindex = static_cast<std::size_t>(static_cast<difference_type>(_Myindex) + n);
|
||||
return *this;
|
||||
}
|
||||
constexpr checked_array_iterator& operator-=(difference_type n) noexcept
|
||||
{
|
||||
_Myindex = static_cast<std::size_t>(static_cast<difference_type>(_Myindex) - n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend constexpr checked_array_iterator operator+(checked_array_iterator it, difference_type n) noexcept { it += n; return it; }
|
||||
friend constexpr checked_array_iterator operator+(difference_type n, checked_array_iterator it) noexcept { return it + n; }
|
||||
friend constexpr checked_array_iterator operator-(checked_array_iterator it, difference_type n) noexcept { it -= n; return it; }
|
||||
friend constexpr difference_type operator-(checked_array_iterator a, checked_array_iterator b) noexcept
|
||||
{
|
||||
return static_cast<difference_type>(a._Myindex) - static_cast<difference_type>(b._Myindex);
|
||||
}
|
||||
|
||||
friend constexpr bool operator==(checked_array_iterator a, checked_array_iterator b) noexcept { return a._Myindex == b._Myindex; }
|
||||
friend constexpr bool operator!=(checked_array_iterator a, checked_array_iterator b) noexcept { return !(a == b); }
|
||||
friend constexpr bool operator<(checked_array_iterator a, checked_array_iterator b) noexcept { return a._Myindex < b._Myindex; }
|
||||
friend constexpr bool operator>(checked_array_iterator a, checked_array_iterator b) noexcept { return b < a; }
|
||||
friend constexpr bool operator<=(checked_array_iterator a, checked_array_iterator b) noexcept { return !(b < a); }
|
||||
friend constexpr bool operator>=(checked_array_iterator a, checked_array_iterator b) noexcept { return !(a < b); }
|
||||
};
|
||||
} // namespace stdext
|
||||
|
||||
#endif // __cplusplus && _MSC_VER >= 1951
|
||||
19
deps/spdlog.props
vendored
@@ -1,14 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<!--
|
||||
SPDLOG_* preprocessor defines for spdlog consumers. The actual vcpkg
|
||||
integration (VcpkgEnabled, VcpkgRoot, triplet, manifest install) lives
|
||||
in Cpp.Build.props; this file just carries the defines that match how
|
||||
the pre-vcpkg in-tree build was configured.
|
||||
-->
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)spdlog\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ForcedIncludeFiles>$(MSBuildThisFileDirectory)spdlog-msvc-fix\include\spdlog-msvc-fix.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
--- a/include/spdlog/fmt/bundled/format.h
|
||||
+++ b/include/spdlog/fmt/bundled/format.h
|
||||
@@ -354,7 +354,12 @@ inline typename Container::value_type* get_data(Container& c) {
|
||||
return c.data();
|
||||
}
|
||||
|
||||
-#if defined(_SECURE_SCL) && _SECURE_SCL
|
||||
+// PowerToys: stdext::checked_array_iterator was deprecated in VS 2019 16.10
|
||||
+// and removed entirely in MSVC 14.51 (compiler 19.51, _MSC_VER >= 1951;
|
||||
+// see microsoft/STL STL4043). Skip the broken branch on those toolsets so the
|
||||
+// pointer-based fallback below is used instead. Drop this guard once
|
||||
+// deps/spdlog is bumped past v1.14 (which ships fmt 10.2 and removes this code).
|
||||
+#if defined(_SECURE_SCL) && _SECURE_SCL && (!defined(_MSC_VER) || _MSC_VER < 1951)
|
||||
// Make a checked iterator to avoid MSVC warnings.
|
||||
template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
|
||||
template <typename T> checked_ptr<T> make_checked(T* p, size_t size) {
|
||||
43
deps/vcpkg-overlays/spdlog/portfile.cmake
vendored
@@ -1,43 +0,0 @@
|
||||
# PowerToys overlay port for spdlog.
|
||||
#
|
||||
# Pinned to the same git commit that the deleted deps/spdlog submodule pointed
|
||||
# at, so this is a 1:1 submodule->vcpkg migration with no version change
|
||||
# (per the maintainer guidance: convert one submodule at a time, atomic
|
||||
# commit, don't also bump the version).
|
||||
#
|
||||
# A single hunk patch works around MSVC 14.51 STL4043 (removal of
|
||||
# stdext::checked_array_iterator) in spdlog's bundled fmt 7. Drop this overlay
|
||||
# (and switch to upstream vcpkg's spdlog port) once PowerToys bumps spdlog
|
||||
# past v1.14, which ships fmt 10.2 and removes the affected code path.
|
||||
|
||||
vcpkg_from_github(
|
||||
OUT_SOURCE_PATH SOURCE_PATH
|
||||
REPO gabime/spdlog
|
||||
REF 616866fcf40340ea25a8f218369bad810ef58e72
|
||||
SHA512 2076c527c7768627e6856b2f7ef663b185fd6251894cffd9299203d00f3d2de5696461060442dd72b96c9d3f0fd27f7f63ad2edfdf295e9b06c5fac6d6212faf
|
||||
HEAD_REF v1.x
|
||||
PATCHES
|
||||
msvc-14.51-stdext-checked-array-iterator.patch
|
||||
)
|
||||
|
||||
vcpkg_cmake_configure(
|
||||
SOURCE_PATH "${SOURCE_PATH}"
|
||||
OPTIONS
|
||||
-DSPDLOG_BUILD_EXAMPLE=OFF
|
||||
-DSPDLOG_BUILD_TESTS=OFF
|
||||
-DSPDLOG_BUILD_BENCH=OFF
|
||||
-DSPDLOG_FMT_EXTERNAL=OFF
|
||||
-DSPDLOG_WCHAR_SUPPORT=ON
|
||||
-DSPDLOG_WCHAR_FILENAMES=ON
|
||||
-DSPDLOG_NO_EXCEPTIONS=OFF
|
||||
-DSPDLOG_BUILD_SHARED=OFF
|
||||
)
|
||||
|
||||
vcpkg_cmake_install()
|
||||
vcpkg_cmake_config_fixup(PACKAGE_NAME spdlog CONFIG_PATH lib/cmake/spdlog)
|
||||
vcpkg_fixup_pkgconfig()
|
||||
vcpkg_copy_pdbs()
|
||||
|
||||
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
|
||||
|
||||
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
|
||||
18
deps/vcpkg-overlays/spdlog/vcpkg.json
vendored
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "spdlog",
|
||||
"version-string": "1.8.5-pt-616866fc",
|
||||
"port-version": 0,
|
||||
"description": "Very fast, header-only/compiled, C++ logging library. PowerToys overlay pinned to gabime/spdlog@616866fc (the exact submodule commit before this migration), with a single-hunk patch that works around MSVC 14.51 removing stdext::checked_array_iterator (STL4043).",
|
||||
"homepage": "https://github.com/gabime/spdlog",
|
||||
"license": "MIT",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "vcpkg-cmake",
|
||||
"host": true
|
||||
},
|
||||
{
|
||||
"name": "vcpkg-cmake-config",
|
||||
"host": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -97,10 +97,6 @@ The Shell Process Debugging Tool is a Visual Studio extension that helps debug m
|
||||
- Check Event Viewer for application crashes related to `PowerToys.Settings.exe`
|
||||
- Crash dumps can be obtained from Event Viewer
|
||||
|
||||
### Debugging Command Palette
|
||||
Command Palette can be easily debugged using the solution filter in `src/modules/cmdpal/Command Palette.slnf`. This will open Command Palette as its own Visual Studio solution that can be run and debugged directly in Visual Studio without the need for the Shell Process Debugging Tool.
|
||||
|
||||
|
||||
## Troubleshooting Build Errors
|
||||
|
||||
### Missing Image Files or Corrupted Build State
|
||||
|
||||
BIN
doc/devdocs/images/shortcutguide/diagram.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 5.3 MiB After Width: | Height: | Size: 5.3 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 3.5 MiB After Width: | Height: | Size: 3.5 MiB |
|
Before Width: | Height: | Size: 497 KiB After Width: | Height: | Size: 497 KiB |
|
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 276 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 491 KiB After Width: | Height: | Size: 491 KiB |
|
Before Width: | Height: | Size: 706 KiB After Width: | Height: | Size: 706 KiB |
|
Before Width: | Height: | Size: 408 KiB After Width: | Height: | Size: 408 KiB |
|
Before Width: | Height: | Size: 384 KiB After Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 493 KiB After Width: | Height: | Size: 493 KiB |
|
Before Width: | Height: | Size: 492 KiB After Width: | Height: | Size: 492 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 311 KiB After Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 297 KiB After Width: | Height: | Size: 297 KiB |
|
Before Width: | Height: | Size: 284 KiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 225 KiB |
|
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 890 KiB After Width: | Height: | Size: 890 KiB |
|
Before Width: | Height: | Size: 858 KiB After Width: | Height: | Size: 858 KiB |
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
@@ -42,4 +42,4 @@ In the PR that adds a new plugin, reference a new issue to track the work for fu
|
||||
|
||||
- [ ] Add the resource folder to https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L825
|
||||
- [ ] Add the resource files under the section https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L882
|
||||
- [ ] Your plugin's executable file (DLL) has to have correct version information after building it. (This version information will be shown on the settings page.)
|
||||
- [ ] Your plugin's executable file (DLL) has to have correct version informations after building it. (This version information will be shown on the settings page.)
|
||||
|
||||
@@ -9,14 +9,12 @@
|
||||
[Pull Requests](https://github.com/microsoft/PowerToys/pulls?q=is%3Apr+is%3Aopen+label%3A%22Product-Shortcut+Guide%22+)
|
||||
|
||||
## Overview
|
||||
Shortcut Guide is a PowerToy that displays an overlay of available keyboard shortcuts when a user-set keyboard shortcut is pressed. It helps users discover and remember keyboard shortcuts for Windows and apps.
|
||||
|
||||
> [!NOTE]
|
||||
> The spec for the manifest files is in development and will be linked here once available.
|
||||
Shortcut Guide is a PowerToy that displays an overlay of available keyboard shortcuts when the Windows key is pressed and held. It provides a visual reference for Windows key combinations, helping users discover and utilize built-in Windows shortcuts.
|
||||
|
||||
## Usage
|
||||
- Press the user-defined hotkey to display the overlay
|
||||
- Press the hotkey again or press ESC to dismiss the overlay
|
||||
- Press and hold the Windows key to display the overlay of available shortcuts
|
||||
- Press the hotkey again to dismiss the overlay
|
||||
- The overlay displays Windows shortcuts with their corresponding actions
|
||||
|
||||
## Build and Debug Instructions
|
||||
|
||||
@@ -27,89 +25,67 @@ Shortcut Guide is a PowerToy that displays an overlay of available keyboard shor
|
||||
4. The executable is named PowerToys.ShortcutGuide.exe
|
||||
|
||||
### Debug
|
||||
1. Right-click the ShortcutGuide.Ui project and select 'Set as Startup Project'
|
||||
1. Right-click the ShortcutGuide project and select 'Set as Startup Project'
|
||||
2. Right-click the project again and select 'Debug'
|
||||
|
||||
> [!NOTE]
|
||||
> When run in debug mode, the window behaves differently than in release mode. It will not automatically close when loosing focus, it will be displayed on top of all other windows, and it is not hidden from the taskbar.
|
||||
## Code Structure
|
||||
|
||||
## Project Structure
|
||||

|
||||
|
||||
The Shortcut Guide module consists of the following 4 projects:
|
||||
### Core Files
|
||||
|
||||
### [`ShortcutGuide.Ui`](/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj
|
||||
#### [`dllmain.cpp`](/src/modules/shortcut_guide/dllmain.cpp)
|
||||
Contains DLL boilerplate code. Implements the PowertoyModuleIface, including enable/disable functionality and GPO policy handling. Captures hotkey events and starts the PowerToys.ShortcutGuide.exe process to display the shortcut guide window.
|
||||
|
||||
This is the main UI project for the Shortcut Guide module. Upon startup it does the following tasks:
|
||||
#### [`shortcut_guide.cpp`](/src/modules/shortcut_guide/shortcut_guide.cpp)
|
||||
Contains the module interface code. It initializes the settings values and the keyboard event listener. Defines the OverlayWindow class, which manages the overall logic and event handling for the PowerToys Shortcut Guide.
|
||||
|
||||
1. Copies the built-in manifest files to the users manifest directory (overwriting existing files).
|
||||
2. Generate the `index.yml` manifest file.
|
||||
3. Populate the PowerToys shortcut manifest with the user-defined shortcuts.
|
||||
4. Starts the UI.
|
||||
#### [`overlay_window.cpp`](/src/modules/shortcut_guide/overlay_window.cpp)
|
||||
Contains the code for loading the SVGs, creating and rendering of the overlay window. Manages and displays overlay windows with SVG graphics through two main classes:
|
||||
- D2DOverlaySVG: Handles loading, resizing, and manipulation of SVG graphics
|
||||
- D2DOverlayWindow: Manages the display and behavior of the overlay window
|
||||
|
||||
### Related files in PowerToys.Interop
|
||||
#### [`keyboard_state.cpp`](/src/modules/shortcut_guide/keyboard_state.cpp)
|
||||
Contains helper methods for checking the current state of the keyboard.
|
||||
|
||||
#### [`excluded_app.cpp`](/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.cpp)
|
||||
#### [`target_state.cpp`](/src/modules/shortcut_guide/target_state.cpp)
|
||||
State machine that handles the keyboard events. It's responsible for deciding when to show the overlay, when to suppress the Start menu (if the overlay is displayed long enough), etc. Handles state transitions and synchronization to ensure the overlay is shown or hidden appropriately based on user interactions.
|
||||
|
||||
This file contains one function with the following signature:
|
||||
#### [`trace.cpp`](/src/modules/shortcut_guide/trace.cpp)
|
||||
Contains code for telemetry.
|
||||
|
||||
```cpp
|
||||
__declspec(dllexport) bool IsCurrentWindowExcludedFromShortcutGuide()
|
||||
```
|
||||
### Supporting Files
|
||||
|
||||
This function checks if the current window is excluded from the Shortcut Guide overlay. It returns `true` if the current window is excluded otherwise it returns `false`.
|
||||
#### [`animation.cpp`](/src/modules/shortcut_guide/animation.cpp)
|
||||
Handles the timing and interpolation of animations. Calculates the current value of an animation based on elapsed time and a specified easing function.
|
||||
|
||||
#### [`tasklist_positions.cpp`](/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp)
|
||||
#### [`d2d_svg.cpp`](/src/modules/shortcut_guide/d2d_svg.cpp)
|
||||
Provides functionality for loading, resizing, recoloring, rendering, and manipulating SVG images using Direct2D.
|
||||
|
||||
This file contains helper functions to retrieve the positions of the taskbar buttons. It exports the following function:
|
||||
#### [`d2d_text.cpp`](/src/modules/shortcut_guide/d2d_text.cpp)
|
||||
Handles creation, resizing, alignment, and rendering of text using Direct2D and DirectWrite.
|
||||
|
||||
```cpp
|
||||
__declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size)
|
||||
```
|
||||
#### [`d2d_window.cpp`](/src/modules/shortcut_guide/d2d_window.cpp)
|
||||
Manages a window using Direct2D and Direct3D for rendering. Handles window creation, resizing, rendering, and destruction.
|
||||
|
||||
This function retrieves the positions of the taskbar buttons for a given monitor. It returns an array of `TasklistButton` structures (max 10), which contain the position and size of each button.
|
||||
#### [`native_event_waiter.cpp`](/src/modules/shortcut_guide/native_event_waiter.cpp)
|
||||
Waits for a named event and executes a specified action when the event is triggered. Uses a separate thread to handle event waiting and action execution.
|
||||
|
||||
`monitor` must be the monitor handle of the monitor containing the taskbar instance of which the buttons should be retrieved.
|
||||
#### [`tasklist_positions.cpp`](/src/modules/shortcut_guide/tasklist_positions.cpp)
|
||||
Handles retrieving and updating the positions and information of taskbar buttons in Windows.
|
||||
|
||||
`size` will contain the resulting array size.
|
||||
|
||||
It determines the positions through Windows `FindWindowEx` function.
|
||||
For the primary taskbar it searches for:
|
||||
* A window called "Shell_TrayWnd"
|
||||
* that contains a window called "ReBarWindow32"
|
||||
* that contains a window called "MSTaskSwWClass"
|
||||
* that contains a window called "MSTaskListWClass"
|
||||
|
||||
For any secondary taskbar it searches for:
|
||||
* A window called "Shell_SecondaryTrayWnd"
|
||||
* that contains a window called "WorkerW"
|
||||
* that contains a window called "MSTaskListWClass"
|
||||
|
||||
It then enumerates all the button elements inside "MSTaskListWClass" while skipping such with a same name (which implies the user does not use combining taskbar buttons)
|
||||
|
||||
If this method fails, which it will for newer versions of Windows, it falls back to searching for:
|
||||
* A window called "Shell_TrayWnd" or "Shell_SecondaryTrayWnd"
|
||||
* that contains a window called "Windows.UI.Composition.DesktopWindowContentBridge"
|
||||
* that contains a window called "Windows.UI.Input.InputSite.WindowClass"
|
||||
* the first child element
|
||||
|
||||
It then enumerates all the button elements inside the selected while skipping such with a same name (which implies the user does not use combining taskbar buttons) and such that do not start with "Appid:" (which are not actual taskbar buttons related to apps, but others like the widgets or the search button).
|
||||
|
||||
### [`ShortcutGuide.IndexYmlGenerator`](/src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/)
|
||||
|
||||
This application generates the `index.yml` manifest file.
|
||||
|
||||
It is a separate project so that its code can be easier ported to WinGet in the future.
|
||||
|
||||
### [`ShortcutGuideModuleInterface`](/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj)
|
||||
|
||||
The module interface that handles opening and closing the user interface.
|
||||
#### [`main.cpp`](/src/modules/shortcut_guide/main.cpp)
|
||||
The entry point for the PowerToys Shortcut Guide application. Handles initialization, ensures single instance execution, manages parent process termination, creates and displays the overlay window, and runs the main event loop.
|
||||
|
||||
## Features and Limitations
|
||||
|
||||
- Currently the displayed shortcuts (Except the ones from PowerToys) are not localized.
|
||||
- The overlay displays Windows shortcuts (Windows key combinations)
|
||||
- The module supports localization, but only for the Windows controls on the left side of the overlay
|
||||
- It's currently rated as a P3 (lower priority) module
|
||||
|
||||
## Future Development
|
||||
|
||||
- Implementing with WinGet to get new shortcut manifest files
|
||||
- Adding localization support for the built-in manifest files
|
||||
A community-contributed version 2 is in development that will support:
|
||||
- Application-specific shortcuts based on the active application
|
||||
- Additional shortcuts beyond Windows key combinations
|
||||
- PowerToys shortcuts
|
||||
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 258 KiB |
@@ -1,318 +0,0 @@
|
||||
# WinGet Manifest Keyboard Shortcuts schema
|
||||
|
||||
## 1 What this spec is about
|
||||
|
||||
This spec provides an extension to the existing [WinGet manifest schema](https://github.com/microsoft/winget-pkgs/blob/master/doc/manifest/README.md) in form of an additional yaml file, that describes keyboard shortcuts the application provides.
|
||||
|
||||
These yaml files are saved on a per-user base and so called manifest interpreters can then display these manifests in a human-friendly version.
|
||||
|
||||
### 1.1 What this spec is not about
|
||||
|
||||
This spec does not provide a way to back up or save user-defined keyboard shortcuts.
|
||||
|
||||
## 2 Save location of manifests
|
||||
|
||||
### 2.1 WinGet
|
||||
|
||||
These files are saved online along with the other manifest files in the [WinGet Package repository](https://github.com/microsoft/winget-pkgs).
|
||||
|
||||
### 2.2 Locally
|
||||
|
||||
All manifests and one index file are saved locally under `%LocalAppData%/Microsoft/WinGet/KeyboardShortcuts`. All apps are allowed to add their manifest files there. In addition Package Managers (like WinGet) and manifest interpreters (like PowerToys Shortcut Guide) can control and add other manifests themselves.
|
||||
|
||||
#### 2.2.1 Downloading manifests
|
||||
|
||||
When WinGet or other package managers download a package, they should also download the corresponding keyboard shortcuts manifest file and save it in the local directory, given such a file exists in the WinGet repository.
|
||||
|
||||
The downloader is also responsible for updating the local `index.yaml` file, which contains all the information about the different manifest files that are saved in the same directory.
|
||||
|
||||
#### 2.2.2 Updating manifests
|
||||
|
||||
When a manifest interpreter starts, it should download the latest version of the manifests from the WinGet repository and save them in the local directory. If a manifest interpreter is not able to download the manifests or they do not exist, it should use the locally saved manifests.
|
||||
|
||||
The updater is also responsible for updating the local `index.yaml` file, which contains all the information about the different manifest files that are saved in the same directory.
|
||||
|
||||
> Note: WinGet must provide a way to update the keyboard shortcuts manifests given a package id.
|
||||
|
||||
### 2.3 File names
|
||||
|
||||
The file name of a keyboard shortcuts file is the WinGet package identifier, plus the locale of the strings of the file and at last the `.KBSC.yaml` file extension.
|
||||
|
||||
For example the package "test.bar" saves its manifest with `en-US` strings in `test.bar.en-US.KBSC.yaml`.
|
||||
|
||||
#### 2.3.1 No winget package available
|
||||
|
||||
If an application has no corresponding WinGet package its name starts with a plus (`+`) symbol.
|
||||
|
||||
### 2.4 Reserved namespaces
|
||||
|
||||
Every name starting with `+WindowsNT` is reserved for the Windows OS and its components.
|
||||
|
||||
## 3 File syntax
|
||||
|
||||
All relevant files are written in [YAML](https://yaml.org/spec).
|
||||
|
||||
> Note: A JSON schema will be provided as soon as the spec reaches a further step
|
||||
|
||||
### 3.1 Manifest Schema vNext Keyboard Shortcuts File
|
||||
|
||||
```
|
||||
PackageName: # The package unique identifier
|
||||
WindowFilter: # The filter of window processes to which the shortcuts apply to
|
||||
BackgroundProcess: # Optionally allows applying WindowFilter to background processes
|
||||
Shortcuts: # List of sections with keyboard shortcuts
|
||||
- SectionName: # Name of the category of shortcuts
|
||||
Properties: # List of shortcuts in the category
|
||||
- Name: # Name of the shortcut
|
||||
Description: # Optional description of the shortcut
|
||||
AdditionalInfo: # Optional additional information about the shortcut
|
||||
Recommended: # Optionally determines if the shortcut is displayed in a designated recommended area
|
||||
Shortcut: # An array of shortcuts that need to be pressed
|
||||
- Win: # Determines if the Windows Key is part of the shortcut
|
||||
Ctrl: # Determines if the Ctrl Key is part of the shortcut
|
||||
Shift: # Determines if the Shift Key is part of the shortcut
|
||||
Alt: # Determines if the Alt Key is part of the shortcut
|
||||
Keys: # Array of keys that need to be pressed
|
||||
```
|
||||
|
||||
Per Application/Package one or more Keyboard manifests can be declared. Every manifest must have a different locale and the same `PackageName`, `WindowFilter` and `BackgroundProcess` fields.
|
||||
|
||||
<details>
|
||||
<summary><b>PackageName</b> - The package unique identifier</summary>
|
||||
|
||||
Package identifier (see 2.1 for more information on the package identifier).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>WindowFilter</b> - The filter of window processes to which the shortcuts apply to</summary>
|
||||
|
||||
This field declares for which process name the shortcuts should be shown (To rephrase: For which processes the shortcut will have an effect if pressed). The value can be either an exact process executable name, for example `explorer.exe` or `chrome.exe`, or a single asterisk (`*`) to apply to any process. No other wildcard patterns are supported by this specification.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>BackgroundProcess</b> - Optionally allows applying WindowFilter to background processes.</summary>
|
||||
|
||||
**Optional field**
|
||||
|
||||
Defaults to `False`. Determines if WindowFilter should apply to background processes as well (Rephrased: When the process is running, the shortcuts will apply).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Shortcuts</b> - List of sections with keyboard shortcuts</summary>
|
||||
|
||||
List of different section (also called categories) of shortcuts.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>SectionName</b> - Name of the category of shortcuts</summary>
|
||||
|
||||
Name of the section of shortcuts.
|
||||
|
||||
**Special sections**:
|
||||
|
||||
Special sections start with an identifier enclosed between `<` and `>`. This declares the category as a special display. If the interpreter of the manifest file can't understand the content this section should be left out.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Properties</b> - List of shortcuts in the category</summary>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Name</b> - Name of the shortcut</summary>
|
||||
|
||||
Name of the shortcut. This is the name that will be displayed in the interpreter.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Description</b> - Optional description of the shortcut</summary>
|
||||
|
||||
Optional description of the shortcut. This is the description that will be displayed by the interpreter.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>AdditionalInfo</b> - Optional additional information about the shortcut</summary>
|
||||
|
||||
Array of additional information about the shortcut. This is the additional information that will be displayed by the interpreter and are not part of this manifest.
|
||||
|
||||
**Example**:
|
||||
|
||||
For example, if the shortcut is only available on a certain Windows version, this information could be added here.
|
||||
```yaml
|
||||
AdditionalInfo:
|
||||
- MinWindowsVersion: "10.0.19041.0"
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Shortcut</b> - An array of shortcuts that need to be pressed</summary>
|
||||
|
||||
An array of shortcuts that need to be pressed. This allows defining sequential shortcuts that need to be pressed in order to trigger the action.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Win</b> - Determines if the Windows Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Windows Key on the keyboard.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Ctrl</b> - Determines if the Ctrl Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Ctrl Key on the keyboard.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Shift</b> - Determines if the Shift Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Shift Key on the keyboard.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Alt</b> - Determines if the Alt Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Alt Key on the keyboard.
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Recommended</b> - Optionally determines if the shortcut is displayed in a designated recommended area</summary>
|
||||
|
||||
**Optional field**
|
||||
|
||||
Defaults to `False`. Determines if the shortcut should be displayed in a designated recommended area. This is a visual hint for the user that this shortcut is important.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Keys</b> - Array of keys that need to be pressed</summary>
|
||||
|
||||
A string array of all the keys that need to be pressed. If a number is supplied, it should be read as a [KeyCode](https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes) and displayed accordingly (based on the Keyboard Layout of the user).
|
||||
|
||||
**Special keys**:
|
||||
|
||||
Special keys are enclosed between `<` and `>` and correspond to a key that should be displayed in a certain way. If the interpreter of the manifest file can't understand the content, the brackets should be left out.
|
||||
|
||||
|Name|Description|
|
||||
|----|-----------|
|
||||
|`<Office>`| Corresponds to the Office key on some Windows keyboards |
|
||||
|`<Copilot>`| Corresponds to the Copilot key on some Windows keyboards |
|
||||
|`<Left>`| Corresponds to the left arrow key |
|
||||
|`<Right>`| Corresponds to the right arrow key |
|
||||
|`<Up>`| Corresponds to the up arrow key |
|
||||
|`<Down>`| Corresponds to the down arrow key |
|
||||
|`<Enter>`| Corresponds to the Enter key |
|
||||
|`<Space>`| Corresponds to the Space key |
|
||||
|`<Tab>`| Corresponds to the Tab key |
|
||||
|`<Backspace>`| Corresponds to the Backspace key |
|
||||
|`<Delete>`| Corresponds to the Delete key |
|
||||
|`<Insert>`| Corresponds to the Insert key |
|
||||
|`<Home>`| Corresponds to the Home key |
|
||||
|`<End>`| Corresponds to the End key |
|
||||
|`<PrtScr>`| Corresponds to the Print Screen key |
|
||||
|`<Pause>`| Corresponds to the pause key |
|
||||
|`<PageUp>`| Corresponds to the Page Up key |
|
||||
|`<PageDown>`| Corresponds to the Page Down key |
|
||||
|`<Escape>`| Corresponds to the Escape key |
|
||||
|`<Arrow>`| Corresponds to either the left, right, up or down arrow key |
|
||||
|`<ArrowLR>`| Corresponds to either the left or right arrow key |
|
||||
|`<ArrowUD>`| Corresponds to either the up or down arrow key |
|
||||
|`<Underlined letter>`| Corresponds to any letter that is _underlined_ in the UI |
|
||||
|
||||
</details>
|
||||
|
||||
#### 3.2.2 Example
|
||||
|
||||
```yaml
|
||||
PackageName: Microsoft.PowerToys
|
||||
WindowFilter: "*"
|
||||
BackgroundProcess: True
|
||||
Shortcuts:
|
||||
- SectionName: General
|
||||
Properties:
|
||||
- Name: Advanced Paste
|
||||
Shortcut:
|
||||
- Win: True
|
||||
Ctrl: False
|
||||
Alt: False
|
||||
Shift: False
|
||||
Keys:
|
||||
- 86
|
||||
Description: Open Advanced Paste window
|
||||
- Name: Advanced Paste
|
||||
Shortcut:
|
||||
- Win: True
|
||||
Ctrl: True
|
||||
Alt: True
|
||||
Shift: False
|
||||
Keys:
|
||||
- 86
|
||||
Description: Paste as plain text directly
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 3.2 `index.yaml` file
|
||||
|
||||
The `index.yaml` file is a file that contains all the information about the different manifest files that are saved in the same directory. This file is only available locally and is not saved in the WinGet repository as it is specific to the user.
|
||||
|
||||
```yaml
|
||||
DefaultShellName: # The package identifier of the default shell used in Windows
|
||||
Index: # List of all manifest files
|
||||
- WindowFilter: # The filter of window processes to which the shortcuts apply to
|
||||
BackgroundProcess: # Optionally allows applying WindowFilter to background processes
|
||||
Apps: # List of all manifest files for the filter
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><b>DefaultShellName</b> - The package identifier of the default shell used in Windows</summary>
|
||||
|
||||
This declares the package identifier of the default shell used in Windows. Most commonly it is `+WindowsNT.Shell`. Although not enforced, only the shell declared in the registry key `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell` should be used here.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Index</b> - List of all manifest files</summary>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>WindowFilter</b> - The filter of window processes to which the shortcuts apply to</summary>
|
||||
|
||||
See the `WindowFilter` field in the manifest file for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>BackgroundProcess</b> - Optionally allows applying WindowFilter to background processes</summary>
|
||||
|
||||
**Optional field**
|
||||
|
||||
See the `BackgroundProcess` field in the manifest file for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Apps</b> - List of all the package identifiers applying for the filter</summary>
|
||||
</details>
|
||||
|
||||
#### 3.2.1 Example
|
||||
|
||||
```yaml
|
||||
DefaultShellName: "+WindowsNT.Shell"
|
||||
Index:
|
||||
- Filter: "*"
|
||||
BackgroundProcess: True
|
||||
Apps: ["+WindowsNT.Shell", "Microsoft.PowerToys"]
|
||||
- Filter: "explorer.exe"
|
||||
Apps: ["+WindowsNT.WindowsExplorer"]
|
||||
- Filter: "taskmgr.exe"
|
||||
Apps: ["+WindowsNT.TaskManager"]
|
||||
- Filter: "msedge.exe"
|
||||
Apps: ["+WindowsNT.Edge"]
|
||||
```
|
||||
@@ -79,4 +79,3 @@ Below are community created plugins that target a website or software. They are
|
||||
| [Linear](https://github.com/vednig/powertoys-linear) | [vednig](https://github.com/vednig) | Create Linear Issues directly from Powertoys Run |
|
||||
| [PerplexitySearchShortcut](https://github.com/0x6f677548/PowerToys-Run-PerplexitySearchShortcut) | [0x6f677548](https://github.com/0x6f677548) | Search Perplexity |
|
||||
| [SpeedTest](https://github.com/ruslanlap/PowerToysRun-SpeedTest) | [ruslanlap](https://github.com/ruslanlap) | One-command internet speed tests with real-time results, modern UI, and shareable links. |
|
||||
| [DiskAnalyzer](https://github.com/valley-soft/powertoys-diskanalyzer) | [ValleySoft](https://github.com/valley-soft) | Scan folders, find the largest files, and view drive space usage. |
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
</Project>
|
||||
<Project Path="../src/common/Telemetry/EtwTrace/EtwTrace.vcxproj" Id="8f021b46-362b-485c-bfba-ccf83e820cbd" />
|
||||
<Project Path="../src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
||||
<Project Path="../src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f">
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="PowerToysSetupCustomActionsVNext/PowerToysSetupCustomActionsVNext.vcxproj" Id="b3a354b0-1e54-4b55-a962-fb5af9330c19">
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
|
||||
@@ -2,39 +2,26 @@
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define ShortcutGuideAssetsFiles=?>
|
||||
<?define ShortcutGuideAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ShortcutGuide\?>
|
||||
<?define ShortcutGuideManifestsFiles=?>
|
||||
<?define ShortcutGuideManifestsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ShortcutGuide\Manifests\?>
|
||||
<?define ShortcutGuideSvgFiles=?>
|
||||
<?define ShortcutGuideSvgFilesPath=$(var.BinDir)\Assets\ShortcutGuide\?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="ShortcutGuideAssetsFolder" Name="ShortcutGuide">
|
||||
<Directory Id="ShortcutGuideManifestsFolder" Name="Manifests" />
|
||||
</Directory>
|
||||
<!-- Shortcut guide files -->
|
||||
<DirectoryRef Id="BaseApplicationsAssetsFolder">
|
||||
<Directory Id="ShortcutGuideSvgsInstallFolder" Name="ShortcutGuide" />
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="ShortcutGuideAssetsFolder" FileSource="$(var.ShortcutGuideAssetsFilesPath)">
|
||||
<DirectoryRef Id="ShortcutGuideSvgsInstallFolder" FileSource="$(var.ShortcutGuideSvgFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--ShortcutGuideAssetsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="ShortcutGuideManifestsFolder" FileSource="$(var.ShortcutGuideManifestsFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--ShortcutGuideManifestsFiles_Component_Def-->
|
||||
<!--ShortcutGuideSvgFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- Shortcut guide -->
|
||||
<ComponentGroup Id="ShortcutGuideComponentGroup" >
|
||||
<Component Id="RemoveShortcutGuideFolder" Guid="AD1ABC55-B593-4A60-A86A-BA8C0ED493A5" Directory="ShortcutGuideAssetsFolder" >
|
||||
<ComponentGroup Id="ShortcutGuideComponentGroup">
|
||||
<Component Id="RemoveShortcutGuideFolder" Guid="AD1ABC55-B593-4A60-A86A-BA8C0ED493A5" Directory="ShortcutGuideSvgsInstallFolder">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemoveShortcutGuideFolder" Value="" KeyPath="yes"/>
|
||||
<RegistryValue Type="string" Name="RemoveShortcutGuideFolder" Value="" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveFolderShortcutGuideAssetsInstallFolder" Directory="ShortcutGuideAssetsFolder" On="uninstall"/>
|
||||
</Component>
|
||||
<Component Id="RemoveShortcutGuideManifestsFolder" Guid="F47E2C3A-8D91-4B6F-A2E5-9C8D7F6A1B3E" Directory="ShortcutGuideManifestsFolder" >
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemoveShortcutGuideManifestsFolder" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveFolderShortcutGuideManifestsInstallFolder" Directory="ShortcutGuideManifestsFolder" On="uninstall"/>
|
||||
<RemoveFolder Id="RemoveFolderShortcutGuideSvgsInstallFolder" Directory="ShortcutGuideSvgsInstallFolder" On="uninstall" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Function Generate-FileList() {
|
||||
|
||||
$fileExclusionList = @("*.pdb", "*.lastcodeanalysissucceeded", "createdump.exe", "powertoys.exe")
|
||||
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "srt.js", "monacoSpecialLanguages.js", "customTokenThemeRules.js", "*.pri", "*.yml")
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "srt.js", "monacoSpecialLanguages.js", "customTokenThemeRules.js", "*.pri")
|
||||
|
||||
# MFC DLLs leak into the output via WindowsAppSDKSelfContained but no PowerToys binary imports them.
|
||||
# Verified with dumpbin /dependents across all 2176 binaries — zero consumers.
|
||||
@@ -112,8 +112,6 @@ Function Generate-FileComponents() {
|
||||
|
||||
foreach ($file in $fileList) {
|
||||
$fileTmp = $file -replace "-", "_"
|
||||
$fileTmp = $fileTmp -replace "[^A-Za-z0-9_.]", "_"
|
||||
if ($fileTmp -match "^[^A-Za-z_]") { $fileTmp = "_$fileTmp" }
|
||||
$componentDefs +=
|
||||
@"
|
||||
<File Id="$($fileListName)_File_$($fileTmp)" Source="`$(var.$($fileListName)Path)\$($file)" />`r`n
|
||||
@@ -399,24 +397,8 @@ Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePat
|
||||
## Plugins
|
||||
|
||||
#ShortcutGuide
|
||||
# Ensure manifest yml files are in the build output (the Build target's CopyToOutputDirectory
|
||||
# may not run reliably under -graph mode in solution builds).
|
||||
$sgManifestsSrc = "$PSScriptRoot..\..\..\src\modules\ShortcutGuide\ShortcutGuide.Ui\Assets\ShortcutGuide\Manifests"
|
||||
$sgManifestsDst = "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\Manifests"
|
||||
Write-Host "ShortcutGuide manifests: src=$sgManifestsSrc exists=$(Test-Path $sgManifestsSrc)"
|
||||
Write-Host "ShortcutGuide manifests: dst=$sgManifestsDst exists=$(Test-Path $sgManifestsDst)"
|
||||
if (Test-Path $sgManifestsSrc) {
|
||||
New-Item -Path $sgManifestsDst -ItemType Directory -Force | Out-Null
|
||||
Copy-Item "$sgManifestsSrc\*.yml" -Destination $sgManifestsDst -Force
|
||||
$copied = (Get-ChildItem "$sgManifestsDst\*.yml" -ErrorAction SilentlyContinue).Count
|
||||
Write-Host "ShortcutGuide manifests: copied $copied yml files to build output"
|
||||
} else {
|
||||
Write-Host "WARNING: ShortcutGuide manifest source not found at $sgManifestsSrc"
|
||||
}
|
||||
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideAssetsFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\"
|
||||
Generate-FileComponents -fileListName "ShortcutGuideAssetsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
|
||||
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideManifestsFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\Manifests\"
|
||||
Generate-FileComponents -fileListName "ShortcutGuideManifestsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
|
||||
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideSvgFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ShortcutGuide\"
|
||||
Generate-FileComponents -fileListName "ShortcutGuideSvgFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
|
||||
|
||||
#Settings
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="$(RepoRoot)deps\expected.props" />
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include <common/updating/updating.h>
|
||||
#include <common/updating/updateState.h>
|
||||
#include <common/updating/installer.h>
|
||||
#include <common/updating/configBackup.h>
|
||||
#include <common/updating/updateLifecycle.h>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/HttpClient.h>
|
||||
@@ -23,8 +21,6 @@
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/timeutil.h>
|
||||
|
||||
#include <wil/resource.h>
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
@@ -40,59 +36,17 @@ using namespace cmdArg;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
void CleanupStaleTempUpdaters()
|
||||
{
|
||||
// Remove orphaned PowerToys.Update.*.exe files from previous runs
|
||||
try
|
||||
{
|
||||
std::error_code ec;
|
||||
const auto tempDir = fs::temp_directory_path();
|
||||
for (const auto& entry : fs::directory_iterator(tempDir, ec))
|
||||
{
|
||||
if (ec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!entry.is_regular_file())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto filename = entry.path().filename().wstring();
|
||||
if (filename.starts_with(L"PowerToys.Update.") && filename.ends_with(L".exe"))
|
||||
{
|
||||
// Skip our own file (current PID)
|
||||
const auto ownFilename = L"PowerToys.Update." + std::to_wstring(GetCurrentProcessId()) + L".exe";
|
||||
if (filename == ownFilename)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fs::remove(entry.path(), ec);
|
||||
// Failure to delete is expected if another updater is still running
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Best-effort cleanup; don't block the update
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<fs::path> CopySelfToTempDir()
|
||||
{
|
||||
CleanupStaleTempUpdaters();
|
||||
|
||||
std::error_code error;
|
||||
auto dst_path = fs::temp_directory_path() / (L"PowerToys.Update." + std::to_wstring(GetCurrentProcessId()) + L".exe");
|
||||
auto dst_path = fs::temp_directory_path() / "PowerToys.Update.exe";
|
||||
fs::copy_file(get_module_filename(), dst_path, fs::copy_options::overwrite_existing, error);
|
||||
if (error)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return dst_path;
|
||||
return std::move(dst_path);
|
||||
}
|
||||
|
||||
std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
@@ -103,9 +57,34 @@ std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
|
||||
auto state = UpdateState::read();
|
||||
|
||||
// Handle readyToInstall first — the installer is already on disk,
|
||||
// so we don't need a GitHub API call (which may fail if offline).
|
||||
if (state.state == UpdateState::readyToInstall)
|
||||
const auto new_version_info = std::move(get_github_version_info_async()).get();
|
||||
if (std::holds_alternative<version_up_to_date>(*new_version_info))
|
||||
{
|
||||
isUpToDate = true;
|
||||
Logger::error("Invoked with -update_now argument, but no update was available");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
|
||||
{
|
||||
if (!new_version_info)
|
||||
{
|
||||
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Cleanup old updates before downloading the latest
|
||||
updating::cleanup_updates();
|
||||
|
||||
auto downloaded_installer = std::move(download_new_version_async(std::get<new_version_download_info>(*new_version_info))).get();
|
||||
if (!downloaded_installer)
|
||||
{
|
||||
Logger::error("Couldn't download new installer");
|
||||
}
|
||||
|
||||
return downloaded_installer;
|
||||
}
|
||||
else if (state.state == UpdateState::readyToInstall)
|
||||
{
|
||||
fs::path installer{ get_pending_updates_path() / state.downloadedInstallerFilename };
|
||||
if (fs::is_regular_file(installer))
|
||||
@@ -118,44 +97,12 @@ std::optional<fs::path> ObtainInstaller(bool& isUpToDate)
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.state == UpdateState::upToDate)
|
||||
else if (state.state == UpdateState::upToDate)
|
||||
{
|
||||
isUpToDate = true;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto new_version_info = std::move(get_github_version_info_async()).get();
|
||||
|
||||
// Check for error BEFORE dereferencing — the old code crashed here
|
||||
// when GitHub API was unreachable (new_version_info held an error string).
|
||||
if (!new_version_info)
|
||||
{
|
||||
Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error());
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (std::holds_alternative<version_up_to_date>(*new_version_info))
|
||||
{
|
||||
isUpToDate = true;
|
||||
Logger::error("Invoked with -update_now argument, but no update was available");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading)
|
||||
{
|
||||
// Cleanup old updates before downloading the latest
|
||||
updating::cleanup_updates();
|
||||
|
||||
auto downloaded_installer = std::move(download_new_version_async(std::get<new_version_download_info>(*new_version_info))).get();
|
||||
if (!downloaded_installer)
|
||||
{
|
||||
Logger::error("Couldn't download new installer");
|
||||
}
|
||||
|
||||
return downloaded_installer;
|
||||
}
|
||||
|
||||
Logger::error("Invoked with -update_now argument, but update state was invalid");
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -169,32 +116,13 @@ bool InstallNewVersionStage1(fs::path installer)
|
||||
|
||||
if (pt_main_window != nullptr)
|
||||
{
|
||||
// Get the process that owns the tray window so we can wait for it to exit
|
||||
DWORD ptProcessId = 0;
|
||||
GetWindowThreadProcessId(pt_main_window, &ptProcessId);
|
||||
|
||||
// Use SendMessageTimeoutW to avoid blocking indefinitely if the
|
||||
// tray window thread is hung or unresponsive.
|
||||
DWORD_PTR result = 0;
|
||||
SendMessageTimeoutW(pt_main_window, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 5000, &result);
|
||||
|
||||
// Wait for PT to actually exit before launching installer.
|
||||
// Without this, the installer may find PT files locked.
|
||||
if (ptProcessId != 0)
|
||||
{
|
||||
wil::unique_handle ptProcess{ OpenProcess(SYNCHRONIZE, FALSE, ptProcessId) };
|
||||
if (ptProcess)
|
||||
{
|
||||
WaitForSingleObject(ptProcess.get(), 10000); // 10 second timeout
|
||||
}
|
||||
}
|
||||
SendMessageW(pt_main_window, WM_CLOSE, 0, 0);
|
||||
}
|
||||
|
||||
// Pass the install directory so Stage 2 can relaunch PowerToys after install
|
||||
const std::wstring installDir = get_module_folderpath();
|
||||
|
||||
std::wstring arguments = updating::BuildStage2Arguments(
|
||||
UPDATE_NOW_LAUNCH_STAGE2, installer, fs::path(installDir));
|
||||
std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 };
|
||||
arguments += L" \"";
|
||||
arguments += installer.c_str();
|
||||
arguments += L"\"";
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
|
||||
sei.lpFile = copy_in_temp->c_str();
|
||||
@@ -262,16 +190,9 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
LPWSTR* args = CommandLineToArgvW(GetCommandLineW(), &nArgs);
|
||||
if (!args || nArgs < 2)
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
LocalFree(args);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// D3 fix: ensure args is freed on all exit paths
|
||||
auto freeArgs = wil::scope_exit([&] { LocalFree(args); });
|
||||
|
||||
std::wstring_view action{ args[1] };
|
||||
|
||||
std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location());
|
||||
@@ -280,11 +201,6 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
|
||||
if (action == UPDATE_NOW_LAUNCH_STAGE1)
|
||||
{
|
||||
// Backup config files before the update to protect against corruption
|
||||
Logger::info("Backing up config files before update");
|
||||
auto backupResult = updating::BackupConfigFiles(fs::path(PTSettingsHelper::get_root_save_folder_location()));
|
||||
Logger::info("Config backup complete: {} files backed up, {} errors", backupResult.filesBackedUp, backupResult.errors);
|
||||
|
||||
bool isUpToDate = false;
|
||||
auto installerPath = ObtainInstaller(isUpToDate);
|
||||
bool failed = !installerPath.has_value();
|
||||
@@ -301,12 +217,6 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
}
|
||||
else if (action == UPDATE_NOW_LAUNCH_STAGE2)
|
||||
{
|
||||
if (nArgs < 3)
|
||||
{
|
||||
Logger::error("Stage 2 invoked without installer path argument");
|
||||
return 1;
|
||||
}
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
const bool failed = !InstallNewVersionStage2(args[2]);
|
||||
if (failed)
|
||||
@@ -317,39 +227,6 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||
state.state = UpdateState::errorDownloading;
|
||||
});
|
||||
}
|
||||
|
||||
// Always check for corrupted configs after Stage 2, regardless
|
||||
// of install success/failure. A failed install may still corrupt configs.
|
||||
Logger::info("Checking for corrupted config files after update");
|
||||
auto restoreResult = updating::RestoreCorruptedConfigs(fs::path(PTSettingsHelper::get_root_save_folder_location()));
|
||||
Logger::info("Config restore check complete: {}/{} files restored, {} errors",
|
||||
restoreResult.filesRestored, restoreResult.filesChecked, restoreResult.errors);
|
||||
|
||||
if (!failed)
|
||||
{
|
||||
// Relaunch PowerToys from the install directory
|
||||
if (updating::CanRelaunchAfterUpdate(nArgs))
|
||||
{
|
||||
std::wstring ptExePath = updating::BuildPowerToysExePath(args[3]);
|
||||
|
||||
Logger::info(L"Relaunching PowerToys after update: {}", ptExePath);
|
||||
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC };
|
||||
sei.lpFile = ptExePath.c_str();
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = UPDATE_REPORT_SUCCESS;
|
||||
|
||||
if (!ShellExecuteExW(&sei))
|
||||
{
|
||||
Logger::error(L"Failed to relaunch PowerToys after update");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::warn("Install directory not provided to Stage 2 - cannot relaunch PowerToys");
|
||||
}
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<Import Project="$(RepoRoot)deps\expected.props" />
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -73,8 +73,7 @@
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
||||
<!-- TODO: _SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS: suppress VS 2026 STL hard error for <experimental/coroutine> until the code is ported to <coroutine> -->
|
||||
<PreprocessorDefinitions>_WINRT_DLL;WINRT_LEAN_AND_MEAN;_SILENCE_EXPERIMENTAL_COROUTINE_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Composition;
|
||||
using Microsoft.UI.Composition.SystemBackdrops;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Microsoft.PowerToys.Common.UI.Controls.Backdrops;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="SystemBackdrop"/> that renders desktop acrylic and stays in
|
||||
/// the active visual state even when the hosting window is not activated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The built-in <see cref="DesktopAcrylicBackdrop"/> tracks the host window's
|
||||
/// <c>IsInputActive</c> state and falls back to a solid color whenever the
|
||||
/// window is not the foreground window. That makes it unusable for transient,
|
||||
/// non-activating surfaces such as toasts or popups created with
|
||||
/// <c>SW_SHOWNA</c> / <c>WS_EX_TRANSPARENT</c>, where the window is never
|
||||
/// activated by design.
|
||||
///
|
||||
/// This backdrop drives a <see cref="DesktopAcrylicController"/> with a
|
||||
/// <see cref="SystemBackdropConfiguration"/> whose <c>IsInputActive</c> is
|
||||
/// permanently <see langword="true"/>, so the native acrylic effect is always
|
||||
/// rendered.
|
||||
/// </remarks>
|
||||
public sealed partial class AlwaysActiveDesktopAcrylicBackdrop : SystemBackdrop
|
||||
{
|
||||
private readonly Dictionary<ICompositionSupportsSystemBackdrop, BackdropTarget> _targets = new();
|
||||
|
||||
protected override void OnTargetConnected(ICompositionSupportsSystemBackdrop connectedTarget, XamlRoot xamlRoot)
|
||||
{
|
||||
base.OnTargetConnected(connectedTarget, xamlRoot);
|
||||
|
||||
var configuration = new SystemBackdropConfiguration
|
||||
{
|
||||
IsInputActive = true,
|
||||
Theme = ResolveTheme(xamlRoot),
|
||||
};
|
||||
|
||||
var controller = new DesktopAcrylicController();
|
||||
controller.SetSystemBackdropConfiguration(configuration);
|
||||
controller.AddSystemBackdropTarget(connectedTarget);
|
||||
|
||||
var target = new BackdropTarget(controller, configuration, xamlRoot);
|
||||
_targets[connectedTarget] = target;
|
||||
|
||||
if (xamlRoot.Content is FrameworkElement rootElement)
|
||||
{
|
||||
rootElement.ActualThemeChanged += target.OnActualThemeChanged;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetDisconnected(ICompositionSupportsSystemBackdrop disconnectedTarget)
|
||||
{
|
||||
base.OnTargetDisconnected(disconnectedTarget);
|
||||
|
||||
if (_targets.Remove(disconnectedTarget, out var target))
|
||||
{
|
||||
if (target.XamlRoot.Content is FrameworkElement rootElement)
|
||||
{
|
||||
rootElement.ActualThemeChanged -= target.OnActualThemeChanged;
|
||||
}
|
||||
|
||||
target.Controller.RemoveSystemBackdropTarget(disconnectedTarget);
|
||||
target.Controller.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static SystemBackdropTheme ResolveTheme(XamlRoot xamlRoot) =>
|
||||
xamlRoot.Content is FrameworkElement rootElement
|
||||
? rootElement.ActualTheme switch
|
||||
{
|
||||
ElementTheme.Dark => SystemBackdropTheme.Dark,
|
||||
ElementTheme.Light => SystemBackdropTheme.Light,
|
||||
_ => SystemBackdropTheme.Default,
|
||||
}
|
||||
: SystemBackdropTheme.Default;
|
||||
|
||||
private sealed class BackdropTarget
|
||||
{
|
||||
public BackdropTarget(DesktopAcrylicController controller, SystemBackdropConfiguration configuration, XamlRoot xamlRoot)
|
||||
{
|
||||
Controller = controller;
|
||||
Configuration = configuration;
|
||||
XamlRoot = xamlRoot;
|
||||
}
|
||||
|
||||
public DesktopAcrylicController Controller { get; }
|
||||
|
||||
public SystemBackdropConfiguration Configuration { get; }
|
||||
|
||||
public XamlRoot XamlRoot { get; }
|
||||
|
||||
public void OnActualThemeChanged(FrameworkElement sender, object args)
|
||||
{
|
||||
Configuration.Theme = ResolveTheme(XamlRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.Common.UI.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// A floating "card" surface for transient PowerToys overlays (toasts,
|
||||
/// banners, indicators). Provides the PowerToys-standard chrome — 1 px
|
||||
/// border in <c>SurfaceStrokeColorDefaultBrush</c>, 8 px corner radius,
|
||||
/// a <c>ThemeShadow</c>, and an always-active desktop acrylic backdrop —
|
||||
/// via a default <see cref="Microsoft.UI.Xaml.Controls.ControlTemplate"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Lives inside a <see cref="Window.TransparentWindow"/>. Apps that want a
|
||||
/// different look supply their own <c>Style TargetType="TransparentCard"</c>
|
||||
/// in resources — the standard WinUI restyle path.
|
||||
/// </remarks>
|
||||
public sealed partial class TransparentCard : ContentControl
|
||||
{
|
||||
public TransparentCard()
|
||||
{
|
||||
DefaultStyleKey = typeof(TransparentCard);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:backdrops="using:Microsoft.PowerToys.Common.UI.Controls.Backdrops"
|
||||
xmlns:local="using:Microsoft.PowerToys.Common.UI.Controls">
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultTransparentCardStyle}" TargetType="local:TransparentCard" />
|
||||
|
||||
<Style x:Key="DefaultTransparentCardStyle" TargetType="local:TransparentCard">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SurfaceStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:TransparentCard">
|
||||
<Grid
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Translation="0,0,24">
|
||||
<Grid.Shadow>
|
||||
<ThemeShadow />
|
||||
</Grid.Shadow>
|
||||
<SystemBackdropElement CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<SystemBackdropElement.SystemBackdrop>
|
||||
<backdrops:AlwaysActiveDesktopAcrylicBackdrop />
|
||||
</SystemBackdropElement.SystemBackdrop>
|
||||
</SystemBackdropElement>
|
||||
<ContentPresenter
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -4,6 +4,5 @@
|
||||
<ResourceDictionary Source="ms-appx:///PowerToys.Common.UI.Controls/Controls/KeyVisual/KeyCharPresenter.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///PowerToys.Common.UI.Controls/Controls/IsEnabledTextBlock/IsEnabledTextBlock.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///PowerToys.Common.UI.Controls/Controls/ShortcutWithTextLabelControl/ShortcutWithTextLabelControl.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///PowerToys.Common.UI.Controls/Controls/TransparentCard/TransparentCard.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -1,290 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using CommunityToolkit.WinUI;
|
||||
using CommunityToolkit.WinUI.Animations;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
using WinUIEx;
|
||||
|
||||
namespace Microsoft.PowerToys.Common.UI.Controls.Window;
|
||||
|
||||
/// <summary>
|
||||
/// Reusable transparent host window for transient overlays
|
||||
/// (toasts, banners, indicators) that should not steal foreground.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The constructor applies all of the boilerplate that PowerToys overlays
|
||||
/// currently hand-roll:</para>
|
||||
/// <list type="bullet">
|
||||
/// <item>Strip the native frame and caption (<c>WS_THICKFRAME</c> etc.).</item>
|
||||
/// <item>Disable the Win11 1-pixel DWM border and corner rounding.</item>
|
||||
/// <item>Mark the window as a tool window so it stays out of the taskbar and Alt-Tab.</item>
|
||||
/// <item>Extend content into the title bar and collapse the title bar.</item>
|
||||
/// </list>
|
||||
/// <para>The visible chrome (acrylic + border + corner radius + shadow) lives
|
||||
/// in a <see cref="TransparentCard"/> that the constructor assigns to
|
||||
/// <see cref="Microsoft.UI.Xaml.Window.Content"/>. Consumers supply their own
|
||||
/// UI via <see cref="InnerContent"/> — which is the XAML default-content slot
|
||||
/// thanks to <see cref="ContentPropertyAttribute"/> — so a derived window can
|
||||
/// be written as <c><common:TransparentWindow><TextBlock/></common:TransparentWindow></c>.</para>
|
||||
/// <para>Transparency is achieved with a <see cref="TransparentTintBackdrop"/>
|
||||
/// system backdrop so the area outside the <see cref="TransparentCard"/> is
|
||||
/// fully see-through. That buffer area is NOT click-through, so consumers
|
||||
/// should keep it as small as possible (just enough to give the card's
|
||||
/// shadow + slide animation room to breathe — roughly 24 px on each side).</para>
|
||||
/// <para><see cref="Show"/> and <see cref="Hide"/> coordinate <c>SW_SHOWNA</c>
|
||||
/// (no-activate), the <see cref="Microsoft.UI.Xaml.UIElement.Visibility"/>
|
||||
/// toggle on the card, and a debounced
|
||||
/// <see cref="Microsoft.UI.Windowing.AppWindow.Hide"/> sized from the longest
|
||||
/// animation in <see cref="HideAnimations"/>. Animations target the card so
|
||||
/// the entire surface (border, acrylic, shadow, inner content) slides as one.</para>
|
||||
/// </remarks>
|
||||
[ContentProperty(Name = nameof(InnerContent))]
|
||||
public partial class TransparentWindow : WinUIEx.WindowEx
|
||||
{
|
||||
private const uint DwmwaColorNone = 0xFFFFFFFE;
|
||||
private const int DwmwaWindowCornerPreference = 33;
|
||||
private const int DwmwaBorderColor = 34;
|
||||
private const int DwmwcpDoNotRound = 1;
|
||||
|
||||
private const int GwlExStyle = -20;
|
||||
private const int WsExToolWindow = 0x00000080;
|
||||
|
||||
private const int SwShowNa = 8;
|
||||
|
||||
private readonly DispatcherQueueTimer _hideCloseTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
|
||||
private readonly nint _hwnd;
|
||||
private readonly TransparentCard _card;
|
||||
|
||||
private ImplicitAnimationSet _showAnimations;
|
||||
private ImplicitAnimationSet _hideAnimations;
|
||||
|
||||
public TransparentWindow()
|
||||
{
|
||||
AppWindow.Hide();
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Collapsed;
|
||||
|
||||
_hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
||||
|
||||
HwndExtensions.ToggleWindowStyle(_hwnd, false, WindowStyle.TiledWindow);
|
||||
|
||||
unsafe
|
||||
{
|
||||
uint borderColor = DwmwaColorNone;
|
||||
_ = DwmSetWindowAttribute(_hwnd, DwmwaBorderColor, &borderColor, sizeof(uint));
|
||||
|
||||
int cornerPref = DwmwcpDoNotRound;
|
||||
_ = DwmSetWindowAttribute(_hwnd, DwmwaWindowCornerPreference, &cornerPref, sizeof(int));
|
||||
}
|
||||
|
||||
ApplyExStyleBit(WsExToolWindow, true);
|
||||
|
||||
_showAnimations = BuildDefaultShowAnimations();
|
||||
_hideAnimations = BuildDefaultHideAnimations();
|
||||
|
||||
_card = new TransparentCard();
|
||||
Content = _card;
|
||||
|
||||
SystemBackdrop = new TransparentTintBackdrop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="TransparentCard"/> that provides the window's
|
||||
/// visible chrome (acrylic + border + shadow). Consumers can configure
|
||||
/// its layout (e.g. <c>HorizontalAlignment</c>, <c>VerticalAlignment</c>,
|
||||
/// <c>MaxWidth</c>, <c>Margin</c>) to position the card inside the
|
||||
/// window, or apply a custom <c>Style</c> to change its look.
|
||||
/// </summary>
|
||||
public TransparentCard Card => _card;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual hosted inside the window's
|
||||
/// <see cref="TransparentCard"/>. This is the XAML default-content slot:
|
||||
/// child elements declared between the opening and closing
|
||||
/// <c>TransparentWindow</c> tags in a derived .xaml are routed here.
|
||||
/// </summary>
|
||||
public object? InnerContent
|
||||
{
|
||||
get => _card.Content;
|
||||
set => _card.Content = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the animations played against
|
||||
/// <see cref="Microsoft.UI.Xaml.Window.Content"/> when <see cref="Show"/>
|
||||
/// flips it to <see cref="Visibility.Visible"/>. Defaults to a 200 ms
|
||||
/// fade-in plus a 250 ms slide-up of 24 px.
|
||||
/// </summary>
|
||||
public ImplicitAnimationSet ShowAnimations
|
||||
{
|
||||
get => _showAnimations;
|
||||
set => _showAnimations = value ?? new ImplicitAnimationSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the animations played against
|
||||
/// <see cref="Microsoft.UI.Xaml.Window.Content"/> when <see cref="Hide"/>
|
||||
/// flips it to <see cref="Visibility.Collapsed"/>. Defaults to a 180 ms
|
||||
/// fade-out plus a 180 ms slide-down of 12 px.
|
||||
/// </summary>
|
||||
public ImplicitAnimationSet HideAnimations
|
||||
{
|
||||
get => _hideAnimations;
|
||||
set => _hideAnimations = value ?? new ImplicitAnimationSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the window without activation (<c>SW_SHOWNA</c>) and flips
|
||||
/// <see cref="Microsoft.UI.Xaml.Window.Content"/> to
|
||||
/// <see cref="Visibility.Visible"/> so <see cref="ShowAnimations"/> plays.
|
||||
/// Repeated calls reset the content to its hidden pose first so the show
|
||||
/// animation re-triggers cleanly. Any pending hide is cancelled.
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(
|
||||
DispatcherQueuePriority.Low,
|
||||
() =>
|
||||
{
|
||||
_hideCloseTimer.Stop();
|
||||
|
||||
if (Content is UIElement content)
|
||||
{
|
||||
// Re-apply each call so swapping animation collections at
|
||||
// runtime takes effect on the next show/hide cycle.
|
||||
Implicit.SetShowAnimations(content, _showAnimations);
|
||||
Implicit.SetHideAnimations(content, _hideAnimations);
|
||||
|
||||
// Reset to the hidden pose so the show animation always
|
||||
// animates from the configured starting frame.
|
||||
content.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
_ = ShowWindow(_hwnd, SwShowNa);
|
||||
|
||||
if (Content is UIElement c2)
|
||||
{
|
||||
c2.Visibility = Visibility.Visible;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flips <see cref="Microsoft.UI.Xaml.Window.Content"/> to
|
||||
/// <see cref="Visibility.Collapsed"/> so <see cref="HideAnimations"/>
|
||||
/// plays, then hides the underlying
|
||||
/// <see cref="Microsoft.UI.Windowing.AppWindow"/> once the longest
|
||||
/// animation in <see cref="HideAnimations"/> (delay + duration) has
|
||||
/// completed.
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(
|
||||
DispatcherQueuePriority.Low,
|
||||
() =>
|
||||
{
|
||||
if (Content is UIElement content)
|
||||
{
|
||||
content.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
_hideCloseTimer.Debounce(
|
||||
AppWindow.Hide,
|
||||
interval: GetAnimationSetTotalDuration(_hideAnimations),
|
||||
immediate: false);
|
||||
});
|
||||
}
|
||||
|
||||
private static TimeSpan GetAnimationSetTotalDuration(ImplicitAnimationSet set)
|
||||
{
|
||||
TimeSpan longest = TimeSpan.Zero;
|
||||
foreach (var animation in set)
|
||||
{
|
||||
if (animation is Animation anim)
|
||||
{
|
||||
var total = (anim.Delay ?? TimeSpan.Zero) + (anim.Duration ?? TimeSpan.Zero);
|
||||
if (total > longest)
|
||||
{
|
||||
longest = total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return longest;
|
||||
}
|
||||
|
||||
private void ApplyExStyleBit(int bit, bool set)
|
||||
{
|
||||
if (_hwnd == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nint exStyle = GetWindowLongPtr(_hwnd, GwlExStyle);
|
||||
nint updated = set ? exStyle | bit : exStyle & ~(nint)bit;
|
||||
if (updated != exStyle)
|
||||
{
|
||||
_ = SetWindowLongPtr(_hwnd, GwlExStyle, updated);
|
||||
}
|
||||
}
|
||||
|
||||
private static ImplicitAnimationSet BuildDefaultShowAnimations() => new()
|
||||
{
|
||||
new OpacityAnimation
|
||||
{
|
||||
From = 0,
|
||||
To = 1.0,
|
||||
Duration = TimeSpan.FromMilliseconds(200),
|
||||
EasingMode = Microsoft.UI.Xaml.Media.Animation.EasingMode.EaseOut,
|
||||
EasingType = EasingType.Cubic,
|
||||
},
|
||||
new TranslationAnimation
|
||||
{
|
||||
From = "0,24,32",
|
||||
To = "0,0,32",
|
||||
Duration = TimeSpan.FromMilliseconds(250),
|
||||
EasingMode = Microsoft.UI.Xaml.Media.Animation.EasingMode.EaseOut,
|
||||
EasingType = EasingType.Cubic,
|
||||
},
|
||||
};
|
||||
|
||||
private static ImplicitAnimationSet BuildDefaultHideAnimations() => new()
|
||||
{
|
||||
new OpacityAnimation
|
||||
{
|
||||
From = 1.0,
|
||||
To = 0,
|
||||
Duration = TimeSpan.FromMilliseconds(180),
|
||||
EasingMode = Microsoft.UI.Xaml.Media.Animation.EasingMode.EaseIn,
|
||||
EasingType = EasingType.Cubic,
|
||||
},
|
||||
new TranslationAnimation
|
||||
{
|
||||
From = "0,0,32",
|
||||
To = "0,12,32",
|
||||
Duration = TimeSpan.FromMilliseconds(180),
|
||||
EasingMode = Microsoft.UI.Xaml.Media.Animation.EasingMode.EaseIn,
|
||||
EasingType = EasingType.Cubic,
|
||||
},
|
||||
};
|
||||
|
||||
[LibraryImport("user32.dll", EntryPoint = "GetWindowLongPtrW")]
|
||||
private static partial nint GetWindowLongPtr(nint hWnd, int nIndex);
|
||||
|
||||
[LibraryImport("user32.dll", EntryPoint = "SetWindowLongPtrW")]
|
||||
private static partial nint SetWindowLongPtr(nint hWnd, int nIndex, nint dwNewLong);
|
||||
|
||||
[LibraryImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool ShowWindow(nint hWnd, int nCmdShow);
|
||||
|
||||
[LibraryImport("dwmapi.dll")]
|
||||
private static unsafe partial int DwmSetWindowAttribute(nint hwnd, int dwAttribute, void* pvAttribute, int cbAttribute);
|
||||
}
|
||||
@@ -2,35 +2,43 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ManagedCommon
|
||||
{
|
||||
public static class IdRecoveryHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures that all items in the provided list have unique IDs. Duplicate IDs are replaced
|
||||
/// with the next available unique ID.
|
||||
/// Fixes invalid IDs in the given list by assigning unique values.
|
||||
/// It ensures that all IDs are non-empty and unique, correcting any duplicates or empty IDs.
|
||||
/// </summary>
|
||||
/// <param name="items">The list of items that may contain duplicate IDs.</param>
|
||||
/// <param name="items">The list of items that may contain invalid IDs.</param>
|
||||
public static void RecoverInvalidIds<T>(IEnumerable<T> items)
|
||||
where T : class, IHasId
|
||||
{
|
||||
var seenIds = new HashSet<int>();
|
||||
int nextAvailableId = 0;
|
||||
var idSet = new HashSet<int>();
|
||||
int newId = 0;
|
||||
var sortedItems = items.OrderBy(i => i.Id).ToList(); // Sort items by ID for consistent processing
|
||||
|
||||
foreach (var item in items)
|
||||
// Iterate through the list and fix invalid IDs
|
||||
foreach (var item in sortedItems)
|
||||
{
|
||||
// If this ID is already used, assign a new unique ID.
|
||||
if (!seenIds.Add(item.Id))
|
||||
// If the ID is invalid or already exists in the set (duplicate), assign a new unique ID
|
||||
if (!idSet.Add(item.Id))
|
||||
{
|
||||
// Find the next unused ID.
|
||||
while (!seenIds.Add(nextAvailableId))
|
||||
// Find the next available unique ID
|
||||
while (idSet.Contains(newId))
|
||||
{
|
||||
nextAvailableId++;
|
||||
newId++;
|
||||
}
|
||||
|
||||
item.Id = nextAvailableId;
|
||||
item.Id = newId;
|
||||
idSet.Add(newId); // Add the newly assigned ID to the set
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\;..\utils;..\Telemetry;..\..\;..\..\..\deps\;..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\;..\utils;..\Telemetry;..\..\;..\..\..\deps\;..\..\..\deps\spdlog\include;..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp23</LanguageStandard>
|
||||
<PreprocessorDefinitions>SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_HEADER_ONLY;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
|
||||
@@ -259,10 +259,6 @@ namespace winrt::PowerToys::Interop::implementation
|
||||
{
|
||||
return CommonSharedConstants::TERMINATE_POWER_DISPLAY_EVENT;
|
||||
}
|
||||
hstring Constants::AutoDisablePowerDisplayEvent()
|
||||
{
|
||||
return CommonSharedConstants::POWER_DISPLAY_AUTO_DISABLE_EVENT;
|
||||
}
|
||||
hstring Constants::RefreshPowerDisplayMonitorsEvent()
|
||||
{
|
||||
return CommonSharedConstants::REFRESH_POWER_DISPLAY_MONITORS_EVENT;
|
||||
|
||||