mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-29 16:36:40 +01:00
Compare commits
35 Commits
yuleng/cmd
...
user/yeela
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d868a85b87 | ||
|
|
abc5c3e249 | ||
|
|
ce058f1dc7 | ||
|
|
2d1676b7df | ||
|
|
8506b47544 | ||
|
|
2b40c4d2f3 | ||
|
|
38cae3ead8 | ||
|
|
e5b2b7fe82 | ||
|
|
a2c9517bed | ||
|
|
e9dbcbaebb | ||
|
|
6e0f1819d5 | ||
|
|
3f834d7a6b | ||
|
|
e9a79f5d6f | ||
|
|
a9c5117f61 | ||
|
|
b9aac70de5 | ||
|
|
55b9b52349 | ||
|
|
13a7ceba6d | ||
|
|
e14ace4bfc | ||
|
|
549ce60483 | ||
|
|
51b6e41d93 | ||
|
|
0d29f6aca6 | ||
|
|
edffb99073 | ||
|
|
310186c44c | ||
|
|
6d303af726 | ||
|
|
84296b0d89 | ||
|
|
7417b857e8 | ||
|
|
4f3f7d649f | ||
|
|
96c5cf1897 | ||
|
|
a1cf836c6d | ||
|
|
c1e49ba915 | ||
|
|
309582795c | ||
|
|
2aad949c9e | ||
|
|
bf9217ec24 | ||
|
|
78b29c5b66 | ||
|
|
dd2e7d17f9 |
@@ -2,14 +2,14 @@
|
||||
# Reference: https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/readme.md#compiling-powertoys
|
||||
properties:
|
||||
resources:
|
||||
- resource: Microsoft.Windows.Developer/DeveloperMode
|
||||
- resource: Microsoft.Windows.Settings/WindowsSettings
|
||||
directives:
|
||||
description: Enable Developer Mode
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
Ensure: Present
|
||||
DeveloperMode: true
|
||||
- resource: Microsoft.WinGet.DSC/WinGetPackage
|
||||
id: vsPackage
|
||||
directives:
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
# Reference: https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/readme.md#compiling-powertoys
|
||||
properties:
|
||||
resources:
|
||||
- resource: Microsoft.Windows.Developer/DeveloperMode
|
||||
- resource: Microsoft.Windows.Settings/WindowsSettings
|
||||
directives:
|
||||
description: Enable Developer Mode
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
Ensure: Present
|
||||
DeveloperMode: true
|
||||
- resource: Microsoft.WinGet.DSC/WinGetPackage
|
||||
id: vsPackage
|
||||
directives:
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
# Reference: https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/readme.md#compiling-powertoys
|
||||
properties:
|
||||
resources:
|
||||
- resource: Microsoft.Windows.Developer/DeveloperMode
|
||||
- resource: Microsoft.Windows.Settings/WindowsSettings
|
||||
directives:
|
||||
description: Enable Developer Mode
|
||||
allowPrerelease: true
|
||||
# Requires elevation for the set operation
|
||||
securityContext: elevated
|
||||
settings:
|
||||
Ensure: Present
|
||||
DeveloperMode: true
|
||||
- resource: Microsoft.WinGet.DSC/WinGetPackage
|
||||
id: vsPackage
|
||||
directives:
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -12,7 +12,7 @@ body:
|
||||
attributes:
|
||||
label: Microsoft PowerToys version
|
||||
placeholder: X.XX.X
|
||||
description: Hover over system tray icon or look at Settings
|
||||
description: Hover over the system tray icon or look at Settings
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -20,7 +20,7 @@ body:
|
||||
type: dropdown
|
||||
attributes:
|
||||
label: Installation method
|
||||
description: How / Where was PowerToys installed from?
|
||||
description: How / where was PowerToys installed from?
|
||||
multiple: true
|
||||
options:
|
||||
- GitHub
|
||||
|
||||
@@ -6,7 +6,7 @@ labels:
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Provide a description of requested docs changes
|
||||
label: Describe the requested doc changes
|
||||
placeholder: Briefly describe which document needs to be corrected and why.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -13,7 +13,7 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Scenario when this would be used?
|
||||
placeholder: What is the scenario this would be used? Why is this important to your workflow as a power user?
|
||||
placeholder: What is the scenario this would be used in? Why is this important to your workflow as a power user?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
4
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
@@ -14,7 +14,7 @@ body:
|
||||
attributes:
|
||||
label: Microsoft PowerToys version
|
||||
placeholder: 0.70.0
|
||||
description: Hover over system tray icon or look at Settings
|
||||
description: Hover over the system tray icon or look at Settings
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
@@ -65,7 +65,7 @@ body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: ❌ Actual phrase(s)
|
||||
placeholder: What is there? Please include a screenshot as that is extremely helpful.
|
||||
placeholder: What is there? Please include a screenshot, as that is extremely helpful.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
17
.github/actions/spell-check/allow/names.txt
vendored
17
.github/actions/spell-check/allow/names.txt
vendored
@@ -46,8 +46,8 @@ betsegaw
|
||||
bricelam
|
||||
bsky
|
||||
CCcat
|
||||
chenmy
|
||||
chemwolf
|
||||
chenmy
|
||||
Chinh
|
||||
chrdavis
|
||||
Chrzan
|
||||
@@ -65,8 +65,8 @@ Deondre
|
||||
DHowett
|
||||
ductdo
|
||||
Essey
|
||||
Feng
|
||||
ethanfangg
|
||||
Feng
|
||||
ferraridavide
|
||||
foxmsft
|
||||
frankychen
|
||||
@@ -77,6 +77,7 @@ Galaxi
|
||||
Garside
|
||||
Gershaft
|
||||
Giordani
|
||||
Gleb
|
||||
Gokce
|
||||
gordon
|
||||
Griese
|
||||
@@ -90,12 +91,15 @@ Hemmerlein
|
||||
hlaueriksson
|
||||
Horvalds
|
||||
Howett
|
||||
hotkidfamily
|
||||
htcfreek
|
||||
Huynh
|
||||
Ionut
|
||||
jamrobot
|
||||
Jaswal
|
||||
Jaylyn
|
||||
jefflord
|
||||
Jeremic
|
||||
Jordi
|
||||
jyuwono
|
||||
kai
|
||||
@@ -105,6 +109,7 @@ Kantarci
|
||||
Karthick
|
||||
kaylacinnamon
|
||||
kevinguo
|
||||
Khmyznikov
|
||||
Krigun
|
||||
Lambson
|
||||
Laute
|
||||
@@ -148,11 +153,13 @@ ricardosantos
|
||||
riri
|
||||
ritchielawrence
|
||||
robmikh
|
||||
ruslanlap
|
||||
Russinovich
|
||||
Rutkas
|
||||
ryanbodrug
|
||||
saahmedm
|
||||
sachaple
|
||||
Sameerjs
|
||||
Santossio
|
||||
Schoen
|
||||
Sekan
|
||||
@@ -168,9 +175,11 @@ Tadele
|
||||
talynone
|
||||
Taras
|
||||
TBM
|
||||
Teutsch
|
||||
tilovell
|
||||
Triet
|
||||
urnotdfs
|
||||
vednig
|
||||
waaverecords
|
||||
wang
|
||||
Whuihuan
|
||||
@@ -189,9 +198,6 @@ zhaopy
|
||||
zhaoqpcn
|
||||
Zoltan
|
||||
Zykova
|
||||
Sameerjs
|
||||
ruslanlap
|
||||
vednig
|
||||
|
||||
# OTHERS
|
||||
|
||||
@@ -218,6 +224,7 @@ openai
|
||||
Quickime
|
||||
regedit
|
||||
roslyn
|
||||
Skia
|
||||
Spotify
|
||||
Vanara
|
||||
wangyi
|
||||
|
||||
3
.github/actions/spell-check/excludes.txt
vendored
3
.github/actions/spell-check/excludes.txt
vendored
@@ -92,6 +92,7 @@
|
||||
^\.github/actions/spell-check/
|
||||
^\.gitmodules$
|
||||
^\Q.github/workflows/spelling2.yml\E$
|
||||
^\Q.pipelines/272MSSharedLibSN2048.snk\E$
|
||||
^\Q.pipelines/ESRPSigning_core.json\E$
|
||||
^\Qdoc/devdocs/localization.md\E$
|
||||
^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$
|
||||
@@ -120,7 +121,9 @@
|
||||
^src/modules/MouseWithoutBorders/App/Form/.*\.resx$
|
||||
^src/modules/MouseWithoutBorders/App/Helper/.*\.resx$
|
||||
^src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag\.txt$
|
||||
^src/modules/ZoomIt/ZoomIt/ZoomIt\.idc$
|
||||
^src/Monaco/
|
||||
^src/common/sysinternals/Eula/
|
||||
^tools/Verification scripts/Check preview handler registration\.ps1$
|
||||
ignore$
|
||||
^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
|
||||
|
||||
30
.github/actions/spell-check/expect.txt
vendored
30
.github/actions/spell-check/expect.txt
vendored
@@ -69,6 +69,7 @@ appwiz
|
||||
APSTUDIO
|
||||
AQS
|
||||
ARandom
|
||||
Arash
|
||||
ARCHITEW
|
||||
ARemapped
|
||||
ARPINSTALLLOCATION
|
||||
@@ -328,7 +329,6 @@ DEFAULTTONULL
|
||||
DEFAULTTOPRIMARY
|
||||
DEFERERASE
|
||||
DEFPUSHBUTTON
|
||||
DEFT
|
||||
deinitialization
|
||||
DELA
|
||||
DELETEDKEYIMAGE
|
||||
@@ -470,6 +470,7 @@ EXPCMDFLAGS
|
||||
EXPCMDSTATE
|
||||
explr
|
||||
exppowertoys
|
||||
exprtk
|
||||
exptas
|
||||
exsb
|
||||
exstyle
|
||||
@@ -670,7 +671,6 @@ IBeam
|
||||
icf
|
||||
ICONERROR
|
||||
ICONLOCATION
|
||||
idc
|
||||
IDCANCEL
|
||||
IDD
|
||||
idk
|
||||
@@ -681,7 +681,6 @@ IDR
|
||||
IDXGI
|
||||
ietf
|
||||
IEXPLORE
|
||||
iextn
|
||||
IFACEMETHOD
|
||||
IFACEMETHODIMP
|
||||
IFile
|
||||
@@ -720,7 +719,6 @@ INPUTMOUSE
|
||||
INPUTSINK
|
||||
INPUTTYPE
|
||||
INSTALLDESKTOPSHORTCUT
|
||||
INSTALLDIR
|
||||
installdir
|
||||
INSTALLFOLDER
|
||||
INSTALLFOLDERTOBOOTSTRAPPERINSTALLFOLDER
|
||||
@@ -756,6 +754,7 @@ iwr
|
||||
jfif
|
||||
jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi
|
||||
jjw
|
||||
JLO
|
||||
jobject
|
||||
jpe
|
||||
jpnime
|
||||
@@ -789,6 +788,7 @@ LCIDTo
|
||||
Lclean
|
||||
Ldone
|
||||
Ldr
|
||||
LEFTALIGN
|
||||
LEFTSCROLLBAR
|
||||
LEFTTEXT
|
||||
LError
|
||||
@@ -811,7 +811,6 @@ LMENU
|
||||
lnks
|
||||
LOADFROMFILE
|
||||
LOBYTE
|
||||
localappdata
|
||||
LOCALDISPLAY
|
||||
localpackage
|
||||
LOCALSYSTEM
|
||||
@@ -911,6 +910,7 @@ metafile
|
||||
mfc
|
||||
Mgmt
|
||||
Microwaved
|
||||
middleclickaction
|
||||
midl
|
||||
mii
|
||||
mindaro
|
||||
@@ -976,7 +976,6 @@ msrc
|
||||
msstore
|
||||
mst
|
||||
msvcp
|
||||
msvsmon
|
||||
MTND
|
||||
MULTIPLEUSE
|
||||
multizone
|
||||
@@ -1154,6 +1153,7 @@ PARTIALCONFIRMATIONDIALOGTITLE
|
||||
PATCOPY
|
||||
PATHMUSTEXIST
|
||||
PATINVERT
|
||||
partow
|
||||
PATPAINT
|
||||
pbc
|
||||
pbi
|
||||
@@ -1252,6 +1252,7 @@ prg
|
||||
prgh
|
||||
prgms
|
||||
pri
|
||||
primaryclickaction
|
||||
PRINTCLIENT
|
||||
printmanagement
|
||||
prm
|
||||
@@ -1283,7 +1284,6 @@ pstm
|
||||
PStr
|
||||
pstream
|
||||
pstrm
|
||||
pswd
|
||||
PSYSTEM
|
||||
psz
|
||||
ptb
|
||||
@@ -1428,6 +1428,7 @@ SDKDDK
|
||||
sdns
|
||||
searchterm
|
||||
SEARCHUI
|
||||
secondaryclickaction
|
||||
SECONDARYDISPLAY
|
||||
secpol
|
||||
securestring
|
||||
@@ -1475,16 +1476,12 @@ SHELLDLL
|
||||
shellex
|
||||
SHELLEXECUTEINFO
|
||||
SHELLEXECUTEINFOW
|
||||
SHELLEXTENSION
|
||||
SHELLICONSIZE
|
||||
SHELLNEWVALUE
|
||||
SHFILEINFO
|
||||
SHFILEOPSTRUCT
|
||||
SHGDN
|
||||
SHGDNF
|
||||
SHGFI
|
||||
SHGFIICON
|
||||
SHGFILARGEICON
|
||||
SHIL
|
||||
shinfo
|
||||
shlwapi
|
||||
@@ -1516,9 +1513,9 @@ SICHINT
|
||||
SIDs
|
||||
siex
|
||||
sigdn
|
||||
Signedness
|
||||
SIGNINGSCENARIO
|
||||
signtool
|
||||
Signtool
|
||||
SINGLEKEY
|
||||
sipolicy
|
||||
SIZEBOX
|
||||
@@ -1694,7 +1691,6 @@ TLayout
|
||||
tlb
|
||||
tlbimp
|
||||
tlc
|
||||
TGM
|
||||
TNP
|
||||
Toolhelp
|
||||
toolkitconverters
|
||||
@@ -1782,7 +1778,6 @@ uxtheme
|
||||
vabdq
|
||||
validmodulename
|
||||
valuegenerator
|
||||
VARENUM
|
||||
variantassignment
|
||||
vcamp
|
||||
VCENTER
|
||||
@@ -2002,11 +1997,6 @@ CLSCTXINPROCALL
|
||||
IIDI
|
||||
irow
|
||||
lcid
|
||||
OTHERUNZOOM
|
||||
OTHERZOOM
|
||||
PARENTCLOSING
|
||||
PARENTOPENING
|
||||
ppwsz
|
||||
rguid
|
||||
SCROLLCHILDREN
|
||||
VARTYPE
|
||||
VARTYPE
|
||||
|
||||
2
.github/actions/spell-check/patterns.txt
vendored
2
.github/actions/spell-check/patterns.txt
vendored
@@ -243,4 +243,4 @@ Process Process
|
||||
|
||||
# ZoomIt menu items with accelerator keys
|
||||
E&xit
|
||||
St&yle
|
||||
St&yle
|
||||
|
||||
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
@@ -5,9 +5,9 @@
|
||||
## PR Checklist
|
||||
|
||||
- [ ] **Closes:** #xxx
|
||||
- [ ] **Communication:** I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
|
||||
- [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
|
||||
- [ ] **Tests:** Added/updated and all pass
|
||||
- [ ] **Localization:** All end user facing strings can be localized
|
||||
- [ ] **Localization:** All end-user-facing strings can be localized
|
||||
- [ ] **Dev docs:** Added/updated
|
||||
- [ ] **New binaries:** Added on the required places
|
||||
- [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries
|
||||
@@ -16,7 +16,7 @@
|
||||
- [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
|
||||
- [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx
|
||||
|
||||
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
|
||||
<!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here -->
|
||||
## Detailed Description of the Pull Request / Additional comments
|
||||
|
||||
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
|
||||
|
||||
39
.github/workflows/package-submissions.yml
vendored
39
.github/workflows/package-submissions.yml
vendored
@@ -1,5 +1,4 @@
|
||||
name: WinGet submission on release
|
||||
# based off of https://github.com/nushell/nushell/blob/main/.github/workflows/winget-submission.yml
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -9,23 +8,31 @@ on:
|
||||
jobs:
|
||||
winget:
|
||||
name: Publish winget package
|
||||
|
||||
# winget-create is only supported on Windows
|
||||
runs-on: windows-latest
|
||||
|
||||
# winget-create will read the following environment variable to access the GitHub token needed for submitting a PR
|
||||
# See https://aka.ms/winget-create-token
|
||||
env:
|
||||
WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.PT_WINGET }}
|
||||
|
||||
# Only submit stable releases
|
||||
if: ${{ !github.event.release.prerelease }}
|
||||
steps:
|
||||
- name: Submit Microsoft.PowerToys package to Windows Package Manager Community Repository
|
||||
run: |
|
||||
# Get installer info from GitHub release event
|
||||
$assets = '${{ toJSON(github.event.release.assets) }}' | ConvertFrom-Json
|
||||
$x64UserInstallerUrl = $assets | Where-Object -Property name -match 'PowerToysUserSetup.*x64' | Select -ExpandProperty browser_download_url
|
||||
$x64MachineInstallerUrl = $assets | Where-Object -Property name -match 'PowerToysSetup.*x64' | Select -ExpandProperty browser_download_url
|
||||
$arm64UserInstallerUrl = $assets | Where-Object -Property name -match 'PowerToysUserSetup.*arm64' | Select -ExpandProperty browser_download_url
|
||||
$arm64MachineInstallerUrl = $assets | Where-Object -Property name -match 'PowerToysSetup.*arm64' | Select -ExpandProperty browser_download_url
|
||||
$packageVersion = (${{ toJSON(github.event.release.tag_name) }}).Trim('v')
|
||||
|
||||
$wingetPackage = "Microsoft.PowerToys"
|
||||
$gitToken = "${{ secrets.PT_WINGET }}"
|
||||
|
||||
$github = Invoke-RestMethod -uri "https://api.github.com/repos/Microsoft/PowerToys/releases"
|
||||
|
||||
$targetRelease = $github | Where-Object -Property name -match 'Release'| Select -First 1
|
||||
$installerUserX64Url = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysUserSetup.*x64' | Select -ExpandProperty browser_download_url
|
||||
$installerMachineX64Url = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*x64' | Select -ExpandProperty browser_download_url
|
||||
$installerUserArmUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysUserSetup.*arm64' | Select -ExpandProperty browser_download_url
|
||||
$installerMachineArmUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*arm64' | Select -ExpandProperty browser_download_url
|
||||
$ver = $targetRelease.tag_name -ireplace '^v'
|
||||
|
||||
# getting latest wingetcreate file
|
||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||
.\wingetcreate.exe update $wingetPackage -s -v $ver -u "$installerUserX64Url|user" "$installerMachineX64Url|machine" "$installerUserArmUrl|user" "$installerMachineArmUrl|machine" -t $gitToken
|
||||
# Update package using wingetcreate
|
||||
curl.exe -JLO https://aka.ms/wingetcreate/latest
|
||||
.\wingetcreate.exe update Microsoft.PowerToys `
|
||||
--version $packageVersion `
|
||||
--urls "$x64UserInstallerUrl|user" "$x64MachineInstallerUrl|machine" "$arm64UserInstallerUrl|user" "$arm64MachineInstallerUrl|machine" `
|
||||
--submit
|
||||
|
||||
8
.github/workflows/spelling2.yml
vendored
8
.github/workflows/spelling2.yml
vendored
@@ -93,7 +93,7 @@ jobs:
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
@@ -175,7 +175,7 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: apply spelling updates
|
||||
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
|
||||
uses: check-spelling/check-spelling@c635c2f3f714eec2fcf27b643a1919b9a811ef2e # v0.0.25
|
||||
with:
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
checkout: true
|
||||
|
||||
@@ -3,226 +3,227 @@
|
||||
"UseMinimatch": false,
|
||||
"SignBatches": [
|
||||
{
|
||||
"MatchedPath": [
|
||||
"*.resources.dll",
|
||||
|
||||
"WinUI3Apps\\Assets\\Settings\\Scripts\\*.ps1",
|
||||
"MatchedPath": [
|
||||
"*.resources.dll",
|
||||
|
||||
"PowerToys.ActionRunner.exe",
|
||||
"PowerToys.Update.exe",
|
||||
"PowerToys.BackgroundActivatorDLL.dll",
|
||||
"Notifications.dll",
|
||||
"os-detection.dll",
|
||||
"PowerToys.exe",
|
||||
"PowerToys.FilePreviewCommon.dll",
|
||||
"PowerToys.Interop.dll",
|
||||
"Tools\\PowerToys.BugReportTool.exe",
|
||||
"StylesReportTool\\PowerToys.StylesReportTool.exe",
|
||||
"Telemetry.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.ManagedCommon.dll",
|
||||
"PowerToys.Common.UI.dll",
|
||||
"PowerToys.Settings.UI.Lib.dll",
|
||||
"PowerToys.GPOWrapper.dll",
|
||||
"PowerToys.GPOWrapperProjection.dll",
|
||||
"PowerToys.AllExperiments.dll",
|
||||
"WinUI3Apps\\Assets\\Settings\\Scripts\\*.ps1",
|
||||
|
||||
"PowerToys.AlwaysOnTop.exe",
|
||||
"PowerToys.AlwaysOnTopModuleInterface.dll",
|
||||
"PowerToys.ActionRunner.exe",
|
||||
"PowerToys.Update.exe",
|
||||
"PowerToys.BackgroundActivatorDLL.dll",
|
||||
"Notifications.dll",
|
||||
"os-detection.dll",
|
||||
"PowerToys.exe",
|
||||
"PowerToys.FilePreviewCommon.dll",
|
||||
"PowerToys.Interop.dll",
|
||||
"Tools\\PowerToys.BugReportTool.exe",
|
||||
"StylesReportTool\\PowerToys.StylesReportTool.exe",
|
||||
"Telemetry.dll",
|
||||
"CalculatorEngineCommon.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.ManagedCommon.dll",
|
||||
"PowerToys.Common.UI.dll",
|
||||
"PowerToys.Settings.UI.Lib.dll",
|
||||
"PowerToys.GPOWrapper.dll",
|
||||
"PowerToys.GPOWrapperProjection.dll",
|
||||
"PowerToys.AllExperiments.dll",
|
||||
|
||||
"PowerToys.CmdNotFoundModuleInterface.dll",
|
||||
"PowerToys.CmdNotFound.dll",
|
||||
"PowerToys.AlwaysOnTop.exe",
|
||||
"PowerToys.AlwaysOnTopModuleInterface.dll",
|
||||
|
||||
"PowerToys.ColorPicker.dll",
|
||||
"PowerToys.ColorPickerUI.dll",
|
||||
"PowerToys.ColorPickerUI.exe",
|
||||
"PowerToys.CmdNotFoundModuleInterface.dll",
|
||||
"PowerToys.CmdNotFound.dll",
|
||||
|
||||
"PowerToys.CropAndLockModuleInterface.dll",
|
||||
"PowerToys.CropAndLock.exe",
|
||||
"PowerToys.ColorPicker.dll",
|
||||
"PowerToys.ColorPickerUI.dll",
|
||||
"PowerToys.ColorPickerUI.exe",
|
||||
|
||||
"PowerToys.PowerOCRModuleInterface.dll",
|
||||
"PowerToys.PowerOCR.dll",
|
||||
"PowerToys.PowerOCR.exe",
|
||||
"PowerToys.CropAndLockModuleInterface.dll",
|
||||
"PowerToys.CropAndLock.exe",
|
||||
|
||||
"PowerToys.AdvancedPasteModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.exe",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.dll",
|
||||
"PowerToys.PowerOCRModuleInterface.dll",
|
||||
"PowerToys.PowerOCR.dll",
|
||||
"PowerToys.PowerOCR.exe",
|
||||
|
||||
"PowerToys.AwakeModuleInterface.dll",
|
||||
"PowerToys.Awake.exe",
|
||||
"PowerToys.Awake.dll",
|
||||
"PowerToys.AdvancedPasteModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.exe",
|
||||
"WinUI3Apps\\PowerToys.AdvancedPaste.dll",
|
||||
|
||||
"fancyzones.dll",
|
||||
"PowerToys.FancyZonesEditor.exe",
|
||||
"PowerToys.FancyZonesEditor.dll",
|
||||
"PowerToys.FancyZonesEditorCommon.dll",
|
||||
"PowerToys.FancyZonesModuleInterface.dll",
|
||||
"PowerToys.FancyZones.exe",
|
||||
"PowerToys.AwakeModuleInterface.dll",
|
||||
"PowerToys.Awake.exe",
|
||||
"PowerToys.Awake.dll",
|
||||
|
||||
"PowerToys.GcodePreviewHandler.dll",
|
||||
"PowerToys.GcodePreviewHandler.exe",
|
||||
"PowerToys.GcodePreviewHandlerCpp.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.exe",
|
||||
"PowerToys.GcodeThumbnailProviderCpp.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.exe",
|
||||
"PowerToys.MarkdownPreviewHandlerCpp.dll",
|
||||
"PowerToys.MonacoPreviewHandler.dll",
|
||||
"PowerToys.MonacoPreviewHandler.exe",
|
||||
"PowerToys.MonacoPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfPreviewHandler.dll",
|
||||
"PowerToys.PdfPreviewHandler.exe",
|
||||
"PowerToys.PdfPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfThumbnailProvider.dll",
|
||||
"PowerToys.PdfThumbnailProvider.exe",
|
||||
"PowerToys.PdfThumbnailProviderCpp.dll",
|
||||
"PowerToys.powerpreview.dll",
|
||||
"PowerToys.PreviewHandlerCommon.dll",
|
||||
"PowerToys.QoiPreviewHandler.dll",
|
||||
"PowerToys.QoiPreviewHandler.exe",
|
||||
"PowerToys.QoiPreviewHandlerCpp.dll",
|
||||
"PowerToys.QoiThumbnailProvider.dll",
|
||||
"PowerToys.QoiThumbnailProvider.exe",
|
||||
"PowerToys.QoiThumbnailProviderCpp.dll",
|
||||
"PowerToys.StlThumbnailProvider.dll",
|
||||
"PowerToys.StlThumbnailProvider.exe",
|
||||
"PowerToys.StlThumbnailProviderCpp.dll",
|
||||
"PowerToys.SvgPreviewHandler.dll",
|
||||
"PowerToys.SvgPreviewHandler.exe",
|
||||
"PowerToys.SvgPreviewHandlerCpp.dll",
|
||||
"PowerToys.SvgThumbnailProvider.dll",
|
||||
"PowerToys.SvgThumbnailProvider.exe",
|
||||
"PowerToys.SvgThumbnailProviderCpp.dll",
|
||||
"fancyzones.dll",
|
||||
"PowerToys.FancyZonesEditor.exe",
|
||||
"PowerToys.FancyZonesEditor.dll",
|
||||
"PowerToys.FancyZonesEditorCommon.dll",
|
||||
"PowerToys.FancyZonesModuleInterface.dll",
|
||||
"PowerToys.FancyZones.exe",
|
||||
|
||||
"WinUI3Apps\\PowerToys.HostsModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.HostsUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.exe",
|
||||
"PowerToys.GcodePreviewHandler.dll",
|
||||
"PowerToys.GcodePreviewHandler.exe",
|
||||
"PowerToys.GcodePreviewHandlerCpp.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.dll",
|
||||
"PowerToys.GcodeThumbnailProvider.exe",
|
||||
"PowerToys.GcodeThumbnailProviderCpp.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.dll",
|
||||
"PowerToys.MarkdownPreviewHandler.exe",
|
||||
"PowerToys.MarkdownPreviewHandlerCpp.dll",
|
||||
"PowerToys.MonacoPreviewHandler.dll",
|
||||
"PowerToys.MonacoPreviewHandler.exe",
|
||||
"PowerToys.MonacoPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfPreviewHandler.dll",
|
||||
"PowerToys.PdfPreviewHandler.exe",
|
||||
"PowerToys.PdfPreviewHandlerCpp.dll",
|
||||
"PowerToys.PdfThumbnailProvider.dll",
|
||||
"PowerToys.PdfThumbnailProvider.exe",
|
||||
"PowerToys.PdfThumbnailProviderCpp.dll",
|
||||
"PowerToys.powerpreview.dll",
|
||||
"PowerToys.PreviewHandlerCommon.dll",
|
||||
"PowerToys.QoiPreviewHandler.dll",
|
||||
"PowerToys.QoiPreviewHandler.exe",
|
||||
"PowerToys.QoiPreviewHandlerCpp.dll",
|
||||
"PowerToys.QoiThumbnailProvider.dll",
|
||||
"PowerToys.QoiThumbnailProvider.exe",
|
||||
"PowerToys.QoiThumbnailProviderCpp.dll",
|
||||
"PowerToys.StlThumbnailProvider.dll",
|
||||
"PowerToys.StlThumbnailProvider.exe",
|
||||
"PowerToys.StlThumbnailProviderCpp.dll",
|
||||
"PowerToys.SvgPreviewHandler.dll",
|
||||
"PowerToys.SvgPreviewHandler.exe",
|
||||
"PowerToys.SvgPreviewHandlerCpp.dll",
|
||||
"PowerToys.SvgThumbnailProvider.dll",
|
||||
"PowerToys.SvgThumbnailProvider.exe",
|
||||
"PowerToys.SvgThumbnailProviderCpp.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithLib.Interop.dll",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithExt.dll",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithUI.exe",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithUI.dll",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithContextMenu.dll",
|
||||
"FileLocksmithContextMenuPackage.msix",
|
||||
"WinUI3Apps\\PowerToys.HostsModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.HostsUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.dll",
|
||||
"WinUI3Apps\\PowerToys.Hosts.exe",
|
||||
|
||||
"WinUI3Apps\\Peek.Common.dll",
|
||||
"WinUI3Apps\\Peek.FilePreviewer.dll",
|
||||
"WinUI3Apps\\Powertoys.Peek.UI.dll",
|
||||
"WinUI3Apps\\Powertoys.Peek.UI.exe",
|
||||
"WinUI3Apps\\Powertoys.Peek.dll",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithLib.Interop.dll",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithExt.dll",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithUI.exe",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithUI.dll",
|
||||
"WinUI3Apps\\PowerToys.FileLocksmithContextMenu.dll",
|
||||
"FileLocksmithContextMenuPackage.msix",
|
||||
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.exe",
|
||||
"WinUI3Apps\\Peek.Common.dll",
|
||||
"WinUI3Apps\\Peek.FilePreviewer.dll",
|
||||
"WinUI3Apps\\Powertoys.Peek.UI.dll",
|
||||
"WinUI3Apps\\Powertoys.Peek.UI.exe",
|
||||
"WinUI3Apps\\Powertoys.Peek.dll",
|
||||
|
||||
"PowerToys.ImageResizer.exe",
|
||||
"PowerToys.ImageResizer.dll",
|
||||
"PowerToys.ImageResizerExt.dll",
|
||||
"PowerToys.ImageResizerContextMenu.dll",
|
||||
"ImageResizerContextMenuPackage.msix",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariablesUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.dll",
|
||||
"WinUI3Apps\\PowerToys.EnvironmentVariables.exe",
|
||||
|
||||
"PowerToys.KeyboardManager.dll",
|
||||
"KeyboardManagerEditor\\PowerToys.KeyboardManagerEditor.exe",
|
||||
"KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe",
|
||||
"PowerToys.KeyboardManagerEditorLibraryWrapper.dll",
|
||||
"PowerToys.ImageResizer.exe",
|
||||
"PowerToys.ImageResizer.dll",
|
||||
"PowerToys.ImageResizerExt.dll",
|
||||
"PowerToys.ImageResizerContextMenu.dll",
|
||||
"ImageResizerContextMenuPackage.msix",
|
||||
|
||||
"PowerToys.Launcher.dll",
|
||||
"PowerToys.PowerLauncher.dll",
|
||||
"PowerToys.PowerLauncher.exe",
|
||||
"PowerToys.PowerLauncher.Telemetry.dll",
|
||||
"Wox.dll",
|
||||
"Wox.Infrastructure.dll",
|
||||
"Wox.Plugin.dll",
|
||||
"RunPlugins\\Calculator\\Microsoft.PowerToys.Run.Plugin.Calculator.dll",
|
||||
"RunPlugins\\Folder\\Microsoft.Plugin.Folder.dll",
|
||||
"RunPlugins\\Indexer\\Microsoft.Plugin.Indexer.dll",
|
||||
"RunPlugins\\OneNote\\Microsoft.PowerToys.Run.Plugin.OneNote.dll",
|
||||
"RunPlugins\\History\\Microsoft.PowerToys.Run.Plugin.History.dll",
|
||||
"RunPlugins\\PowerToys\\Microsoft.PowerToys.Run.Plugin.PowerToys.dll",
|
||||
"RunPlugins\\Program\\Microsoft.Plugin.Program.dll",
|
||||
"RunPlugins\\Registry\\Microsoft.PowerToys.Run.Plugin.Registry.dll",
|
||||
"RunPlugins\\WindowsSettings\\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll",
|
||||
"RunPlugins\\Shell\\Microsoft.Plugin.Shell.dll",
|
||||
"RunPlugins\\Uri\\Microsoft.Plugin.Uri.dll",
|
||||
"RunPlugins\\WindowWalker\\Microsoft.Plugin.WindowWalker.dll",
|
||||
"RunPlugins\\UnitConverter\\Community.PowerToys.Run.Plugin.UnitConverter.dll",
|
||||
"RunPlugins\\VSCodeWorkspaces\\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll",
|
||||
"RunPlugins\\Service\\Microsoft.PowerToys.Run.Plugin.Service.dll",
|
||||
"RunPlugins\\System\\Microsoft.PowerToys.Run.Plugin.System.dll",
|
||||
"RunPlugins\\TimeDate\\Microsoft.PowerToys.Run.Plugin.TimeDate.dll",
|
||||
"RunPlugins\\ValueGenerator\\Community.PowerToys.Run.Plugin.ValueGenerator.dll",
|
||||
"RunPlugins\\WebSearch\\Community.PowerToys.Run.Plugin.WebSearch.dll",
|
||||
"RunPlugins\\WindowsTerminal\\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.MeasureToolModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolCore.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.exe",
|
||||
"PowerToys.KeyboardManager.dll",
|
||||
"KeyboardManagerEditor\\PowerToys.KeyboardManagerEditor.exe",
|
||||
"KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe",
|
||||
"PowerToys.KeyboardManagerEditorLibraryWrapper.dll",
|
||||
|
||||
"PowerToys.FindMyMouse.dll",
|
||||
"PowerToys.MouseHighlighter.dll",
|
||||
"PowerToys.MouseJump.dll",
|
||||
"PowerToys.MouseJump.Common.dll",
|
||||
"PowerToys.MousePointerCrosshairs.dll",
|
||||
"PowerToys.MouseJumpUI.dll",
|
||||
"PowerToys.MouseJumpUI.exe",
|
||||
"PowerToys.Launcher.dll",
|
||||
"PowerToys.PowerLauncher.dll",
|
||||
"PowerToys.PowerLauncher.exe",
|
||||
"PowerToys.PowerLauncher.Telemetry.dll",
|
||||
"Wox.dll",
|
||||
"Wox.Infrastructure.dll",
|
||||
"Wox.Plugin.dll",
|
||||
"RunPlugins\\Calculator\\Microsoft.PowerToys.Run.Plugin.Calculator.dll",
|
||||
"RunPlugins\\Folder\\Microsoft.Plugin.Folder.dll",
|
||||
"RunPlugins\\Indexer\\Microsoft.Plugin.Indexer.dll",
|
||||
"RunPlugins\\OneNote\\Microsoft.PowerToys.Run.Plugin.OneNote.dll",
|
||||
"RunPlugins\\History\\Microsoft.PowerToys.Run.Plugin.History.dll",
|
||||
"RunPlugins\\PowerToys\\Microsoft.PowerToys.Run.Plugin.PowerToys.dll",
|
||||
"RunPlugins\\Program\\Microsoft.Plugin.Program.dll",
|
||||
"RunPlugins\\Registry\\Microsoft.PowerToys.Run.Plugin.Registry.dll",
|
||||
"RunPlugins\\WindowsSettings\\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll",
|
||||
"RunPlugins\\Shell\\Microsoft.Plugin.Shell.dll",
|
||||
"RunPlugins\\Uri\\Microsoft.Plugin.Uri.dll",
|
||||
"RunPlugins\\WindowWalker\\Microsoft.Plugin.WindowWalker.dll",
|
||||
"RunPlugins\\UnitConverter\\Community.PowerToys.Run.Plugin.UnitConverter.dll",
|
||||
"RunPlugins\\VSCodeWorkspaces\\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll",
|
||||
"RunPlugins\\Service\\Microsoft.PowerToys.Run.Plugin.Service.dll",
|
||||
"RunPlugins\\System\\Microsoft.PowerToys.Run.Plugin.System.dll",
|
||||
"RunPlugins\\TimeDate\\Microsoft.PowerToys.Run.Plugin.TimeDate.dll",
|
||||
"RunPlugins\\ValueGenerator\\Community.PowerToys.Run.Plugin.ValueGenerator.dll",
|
||||
"RunPlugins\\WebSearch\\Community.PowerToys.Run.Plugin.WebSearch.dll",
|
||||
"RunPlugins\\WindowsTerminal\\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll",
|
||||
|
||||
"PowerToys.MouseWithoutBorders.dll",
|
||||
"PowerToys.MouseWithoutBorders.exe",
|
||||
"PowerToys.MouseWithoutBordersModuleInterface.dll",
|
||||
"PowerToys.MouseWithoutBordersService.dll",
|
||||
"PowerToys.MouseWithoutBordersService.exe",
|
||||
"PowerToys.MouseWithoutBordersHelper.dll",
|
||||
"PowerToys.MouseWithoutBordersHelper.exe",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolCore.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.dll",
|
||||
"WinUI3Apps\\PowerToys.MeasureToolUI.exe",
|
||||
|
||||
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.dll",
|
||||
"WinUI3Apps\\NewPlusPackage.msix",
|
||||
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.win10.dll",
|
||||
"PowerToys.FindMyMouse.dll",
|
||||
"PowerToys.MouseHighlighter.dll",
|
||||
"PowerToys.MouseJump.dll",
|
||||
"PowerToys.MouseJump.Common.dll",
|
||||
"PowerToys.MousePointerCrosshairs.dll",
|
||||
"PowerToys.MouseJumpUI.dll",
|
||||
"PowerToys.MouseJumpUI.exe",
|
||||
|
||||
"PowerAccent.Core.dll",
|
||||
"PowerToys.PowerAccent.dll",
|
||||
"PowerToys.PowerAccent.exe",
|
||||
"PowerToys.PowerAccentModuleInterface.dll",
|
||||
"PowerToys.PowerAccentKeyboardService.dll",
|
||||
"PowerToys.MouseWithoutBorders.dll",
|
||||
"PowerToys.MouseWithoutBorders.exe",
|
||||
"PowerToys.MouseWithoutBordersModuleInterface.dll",
|
||||
"PowerToys.MouseWithoutBordersService.dll",
|
||||
"PowerToys.MouseWithoutBordersService.exe",
|
||||
"PowerToys.MouseWithoutBordersHelper.dll",
|
||||
"PowerToys.MouseWithoutBordersHelper.exe",
|
||||
|
||||
"WinUI3Apps\\PowerToys.PowerRenameExt.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerRename.exe",
|
||||
"WinUI3Apps\\PowerToys.PowerRenameContextMenu.dll",
|
||||
"WinUI3Apps\\PowerRenameContextMenuPackage.msix",
|
||||
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.dll",
|
||||
"WinUI3Apps\\NewPlusPackage.msix",
|
||||
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.win10.dll",
|
||||
|
||||
"PowerToys.WorkspacesSnapshotTool.exe",
|
||||
"PowerToys.WorkspacesLauncher.exe",
|
||||
"PowerToys.WorkspacesWindowArranger.exe",
|
||||
"PowerToys.WorkspacesEditor.exe",
|
||||
"PowerToys.WorkspacesEditor.dll",
|
||||
"PowerToys.WorkspacesLauncherUI.exe",
|
||||
"PowerToys.WorkspacesLauncherUI.dll",
|
||||
"PowerToys.WorkspacesModuleInterface.dll",
|
||||
"PowerToys.WorkspacesCsharpLibrary.dll",
|
||||
"PowerAccent.Core.dll",
|
||||
"PowerToys.PowerAccent.dll",
|
||||
"PowerToys.PowerAccent.exe",
|
||||
"PowerToys.PowerAccentModuleInterface.dll",
|
||||
"PowerToys.PowerAccentKeyboardService.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewExt.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
"WinUI3Apps\\PowerToys.PowerRenameExt.dll",
|
||||
"WinUI3Apps\\PowerToys.PowerRename.exe",
|
||||
"WinUI3Apps\\PowerToys.PowerRenameContextMenu.dll",
|
||||
"WinUI3Apps\\PowerRenameContextMenuPackage.msix",
|
||||
|
||||
"PowerToys.ShortcutGuide.exe",
|
||||
"PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
"PowerToys.WorkspacesSnapshotTool.exe",
|
||||
"PowerToys.WorkspacesLauncher.exe",
|
||||
"PowerToys.WorkspacesWindowArranger.exe",
|
||||
"PowerToys.WorkspacesEditor.exe",
|
||||
"PowerToys.WorkspacesEditor.dll",
|
||||
"PowerToys.WorkspacesLauncherUI.exe",
|
||||
"PowerToys.WorkspacesLauncherUI.dll",
|
||||
"PowerToys.WorkspacesModuleInterface.dll",
|
||||
"PowerToys.WorkspacesCsharpLibrary.dll",
|
||||
|
||||
"PowerToys.ZoomIt.exe",
|
||||
"PowerToys.ZoomItModuleInterface.dll",
|
||||
"PowerToys.ZoomItSettingsInterop.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewExt.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewUILib.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
|
||||
"WinUI3Apps\\PowerToys.Settings.dll",
|
||||
"WinUI3Apps\\PowerToys.Settings.exe",
|
||||
"PowerToys.ShortcutGuide.exe",
|
||||
"PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
|
||||
"PowerToys.CmdPalModuleInterface.dll",
|
||||
"CmdPalKeyboardService.dll",
|
||||
"*Microsoft.CmdPal.UI_*.msix"
|
||||
],
|
||||
"PowerToys.ZoomIt.exe",
|
||||
"PowerToys.ZoomItModuleInterface.dll",
|
||||
"PowerToys.ZoomItSettingsInterop.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.Settings.dll",
|
||||
"WinUI3Apps\\PowerToys.Settings.exe",
|
||||
|
||||
"PowerToys.CmdPalModuleInterface.dll",
|
||||
"CmdPalKeyboardService.dll",
|
||||
"*Microsoft.CmdPal.UI_*.msix"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
|
||||
@@ -41,6 +41,9 @@ Write-Output ""
|
||||
Write-Output "Restoring dotnet tools..."
|
||||
dotnet tool restore --disable-parallel --no-cache
|
||||
|
||||
# Use Regex syntax
|
||||
$PathExcludes = "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)|(\\RegistryPreviewUILib\\Controls\\HexBox\\)"
|
||||
|
||||
if (-not $Passive)
|
||||
{
|
||||
# Look for unstaged changed files by default
|
||||
@@ -87,7 +90,7 @@ if (-not $Passive)
|
||||
}
|
||||
|
||||
Write-Output "Running Git Diff: $gitDiffCommand"
|
||||
$files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$"
|
||||
$files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$" | Where-Object { $_ -notmatch $PathExcludes }
|
||||
|
||||
if (-not $Passive -and -not $Main -and -not $Unstaged -and -not $Staged -and -not $LastCommit)
|
||||
{
|
||||
@@ -107,7 +110,7 @@ if (-not $Passive)
|
||||
else
|
||||
{
|
||||
Write-Output "Checking all files (passively)"
|
||||
$files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)" }
|
||||
$files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch $PathExcludes }
|
||||
|
||||
if ($files.count -gt 0)
|
||||
{
|
||||
|
||||
@@ -397,6 +397,7 @@ jobs:
|
||||
**\UnitTests-CommonLib.dll
|
||||
**\PowerRenameUnitTests.dll
|
||||
**\UnitTests-FancyZones.dll
|
||||
**\\WorkspacesLibUnitTests.dll
|
||||
!**\obj\**
|
||||
|
||||
- pwsh: |-
|
||||
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
pwsh: true
|
||||
ScriptType: InlineScript
|
||||
Inline: |-
|
||||
$AzToken = (Get-AzAccessToken -ResourceUrl api://30471ccf-0966-45b9-a979-065dbedb24c1).Token
|
||||
$AzToken = (Get-AzAccessToken -AsSecureString -ResourceUrl api://30471ccf-0966-45b9-a979-065dbedb24c1).Token | ConvertFrom-SecureString -AsPlainText
|
||||
Write-Host "##vso[task.setvariable variable=SymbolAccessToken;issecret=true]$AzToken"
|
||||
|
||||
|
||||
|
||||
@@ -72,9 +72,57 @@ $returnList = [System.Collections.Generic.HashSet[string]]($totalList) -join "`r
|
||||
|
||||
Write-Host $returnList
|
||||
|
||||
# Extract the current package list from NOTICE.md
|
||||
$noticePattern = "## NuGet Packages used by PowerToys\s*((?:\r?\n- .+)+)"
|
||||
$noticeMatch = [regex]::Match($noticeFile, $noticePattern)
|
||||
|
||||
if ($noticeMatch.Success) {
|
||||
$currentNoticePackageList = $noticeMatch.Groups[1].Value.Trim()
|
||||
} else {
|
||||
Write-Warning "Warning: Could not find 'NuGet Packages used by PowerToys' section in NOTICE.md"
|
||||
$currentNoticePackageList = ""
|
||||
}
|
||||
|
||||
if (!$noticeFile.Trim().EndsWith($returnList.Trim()))
|
||||
{
|
||||
Write-Host -ForegroundColor Red "Notice.md does not match NuGet list."
|
||||
|
||||
# Show detailed differences
|
||||
$generatedPackages = $returnList -split "`r`n|`n" | Where-Object { $_.Trim() -ne "" } | Sort-Object
|
||||
$noticePackages = $currentNoticePackageList -split "`r`n|`n" | Where-Object { $_.Trim() -ne "" } | ForEach-Object { $_.Trim() } | Sort-Object
|
||||
|
||||
Write-Host ""
|
||||
Write-Host -ForegroundColor Cyan "=== DETAILED DIFFERENCE ANALYSIS ==="
|
||||
Write-Host ""
|
||||
|
||||
# Find packages in proj file list but not in NOTICE.md
|
||||
$missingFromNotice = $generatedPackages | Where-Object { $noticePackages -notcontains $_ }
|
||||
if ($missingFromNotice.Count -gt 0) {
|
||||
Write-Host -ForegroundColor Red "MissingFromNotice:"
|
||||
foreach ($pkg in $missingFromNotice) {
|
||||
Write-Host -ForegroundColor Red " $pkg"
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Find packages in NOTICE.md but not in proj file list
|
||||
$extraInNotice = $noticePackages | Where-Object { $generatedPackages -notcontains $_ }
|
||||
if ($extraInNotice.Count -gt 0) {
|
||||
Write-Host -ForegroundColor Yellow "ExtraInNotice:"
|
||||
foreach ($pkg in $extraInNotice) {
|
||||
Write-Host -ForegroundColor Yellow " $pkg"
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Show counts for summary
|
||||
Write-Host -ForegroundColor Cyan "Summary:"
|
||||
Write-Host " Proj file list has $($generatedPackages.Count) packages"
|
||||
Write-Host " NOTICE.md has $($noticePackages.Count) packages"
|
||||
Write-Host " MissingFromNotice: $($missingFromNotice.Count) packages"
|
||||
Write-Host " ExtraInNotice: $($extraInNotice.Count) packages"
|
||||
Write-Host ""
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
16
COMMUNITY.md
16
COMMUNITY.md
@@ -21,7 +21,7 @@ Connor was the creator of Workspaces and helped create Command Palette (PowerToy
|
||||
### [@damienleroy](https://github.com/damienleroy) - [Damien Leroy](https://www.linkedin.com/in/Damien-Leroy-b2734416a/)
|
||||
Damien has helped out by developing and contributing the Quick Accent utility.
|
||||
|
||||
### [@daverayment ](https://github.com/daverayment) - [David Rayment](https://www.linkedin.com/in/david-rayment-168b5251/)
|
||||
### [@daverayment](https://github.com/daverayment) - [David Rayment](https://www.linkedin.com/in/david-rayment-168b5251/)
|
||||
Dave has helped improve the experience inside of Peek by adding in new features and fixing bugs.
|
||||
|
||||
### [@davidegiacometti](https://github.com/davidegiacometti) - [Davide Giacometti](https://www.linkedin.com/in/davidegiacometti/)
|
||||
@@ -117,10 +117,6 @@ PowerRename is from Chris's SmartRename and icon rendering for SVGs in File Expl
|
||||
|
||||
PowerToys Awake is a tool to keep your computer awake.
|
||||
|
||||
### [@Niels9001](https://github.com/niels9001/) - [Niels Laute](https://nielslaute.com/)
|
||||
|
||||
Niels has helped drive large sums of our update toward a new [consistent and modern UX](https://github.com/microsoft/PowerToys/issues/891). This includes the [launcher work](https://github.com/microsoft/PowerToys/issues/44), color picker UX update and [icon design](https://github.com/microsoft/PowerToys/issues/1118).
|
||||
|
||||
### [@randyrants](https://github.com/randyrants) - [Randy Santossio](https://www.randyrants.com)
|
||||
|
||||
Randy contributed Registry Preview and some very early conversations about keyboard remapping.
|
||||
@@ -184,11 +180,10 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
|
||||
|
||||
## PowerToys core team
|
||||
|
||||
- [@crutkas](https://github.com/crutkas/) - Clint Rutkas - Lead
|
||||
- [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Lead
|
||||
- [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager
|
||||
- [@craigloewen-msft](https://github.com/craigloewen-msft) - Craig Loewen - Product Manager
|
||||
- [@zhiwei-ms](https://github.com/zhiwei-ms) - Zhiwei Yu - Product Manager
|
||||
- [@niels9001](https://github.com/niels9001/) - Niels Laute - Product Manager
|
||||
- [@dhowett](https://github.com/dhowett) - Dustin Howett - Dev lead
|
||||
- [@yeelam-gordon](https://github.com/yeelam-gordon) - Gordon Lam - Dev lead
|
||||
- [@jamrobot](https://github.com/jamrobot) - Jerry Xu - Dev lead
|
||||
@@ -204,6 +199,13 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
|
||||
- [@zhaopy536](https://github.com/zhaopy536) - Peiyao Zhao - Dev
|
||||
- [@wang563681252](https://github.com/wang563681252) - Zhaopeng Wang - Dev
|
||||
- [@vanzue](https://github.com/vanzue) - Kai Tao - Dev
|
||||
- [@zadjii-msft](https://github.com/zadjii-msft) - Mike Griese - Dev
|
||||
- [@khmyznikov](https://github.com/khmyznikov) - Gleb Khmyznikov - Dev
|
||||
- [@chatasweetie](https://github.com/chatasweetie) - Jessica Earley-Cha - Dev
|
||||
- [@MichaelJolley](https://github.com/MichaelJolley) - Michael Jolley - Dev
|
||||
- [@Jaylyn-Barbee](https://github.com/Jaylyn-Barbee) - Jaylyn Barbee - Dev
|
||||
- [@zateutsch](https://github.com/zateutsch) - Zach Teutsch - Dev
|
||||
- [@crutkas](https://github.com/crutkas/) - Clint Rutkas - Overhead
|
||||
|
||||
## Former PowerToys core team members
|
||||
|
||||
|
||||
@@ -31,22 +31,22 @@
|
||||
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
||||
<PackageVersion Include="MessagePack" Version="3.1.3" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.6" />
|
||||
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.15.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
|
||||
<!-- 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="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.5" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<!-- 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. -->
|
||||
<!--
|
||||
@@ -69,31 +69,33 @@
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.37.2" />
|
||||
<!-- Don't update SkiaSharp.Views.WinUI to version 3.* branch as this brakes the HexBox control in Registry Preview. -->
|
||||
<PackageVersion Include="SkiaSharp.Views.WinUI" Version="2.88.9" />
|
||||
<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="9.0.5" />
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.6" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.5" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.6" />
|
||||
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.9.0" />
|
||||
<!-- 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="9.0.5" />
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.6" />
|
||||
<!-- 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="9.0.5" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.6" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.5" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.6" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.6" />
|
||||
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
||||
|
||||
151
NOTICE.md
151
NOTICE.md
@@ -79,6 +79,43 @@ For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
### Calculator
|
||||
|
||||
#### exprtk
|
||||
|
||||
We use the exprtk library (exprtk.hpp) to evaluate mathematical expressions.
|
||||
|
||||
**Source**: [https://github.com/ArashPartow/exprtk](https://github.com/ArashPartow/exprtk)
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 1999-2024 Arash Partow
|
||||
|
||||
https://www.partow.net/programming/exprtk/index.html
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
|
||||
## Utility: PowerToys Run Built-in Extensions
|
||||
|
||||
### Calculator
|
||||
|
||||
#### Mages
|
||||
|
||||
We use the Mages NuGet package for calculating the result of expression.
|
||||
@@ -807,30 +844,25 @@ DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**Source**: https://github.com/kuba--/zip
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
All Rights Reserved.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## Utility: Measure tool
|
||||
|
||||
@@ -1395,6 +1427,37 @@ EXHIBIT A -Mozilla Public License.
|
||||
|
||||
## Utility: Registry Preview
|
||||
|
||||
### HexBox.WinUI
|
||||
|
||||
We use HexBox.WinUI to show a preview of binary values.
|
||||
|
||||
**Source**: https://github.com/hotkidfamily/HexBox.WinUI
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Filip Jeremic
|
||||
Copyright (c) 2024~2025 hotkidfamily@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
@@ -1425,6 +1488,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
|
||||
## NuGet Packages used by PowerToys
|
||||
|
||||
- AdaptiveCards.ObjectModel.WinUI3 2.0.0-beta
|
||||
@@ -1453,22 +1517,22 @@ SOFTWARE.
|
||||
- Mages 3.0.0
|
||||
- Markdig.Signed 0.34.0
|
||||
- MessagePack 3.1.3
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.5
|
||||
- Microsoft.Bcl.AsyncInterfaces 9.0.6
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
|
||||
- Microsoft.Data.Sqlite 9.0.5
|
||||
- Microsoft.Data.Sqlite 9.0.6
|
||||
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
|
||||
- Microsoft.DotNet.ILCompiler (A)
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.5
|
||||
- Microsoft.Extensions.Hosting 9.0.5
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.5
|
||||
- Microsoft.Extensions.Logging 9.0.5
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.5
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.6
|
||||
- Microsoft.Extensions.Hosting 9.0.6
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.6
|
||||
- Microsoft.Extensions.Logging 9.0.6
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.6
|
||||
- Microsoft.NET.ILLink.Tasks (A)
|
||||
- Microsoft.SemanticKernel 1.15.0
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2903.40
|
||||
- Microsoft.Win32.SystemEvents 9.0.5
|
||||
- Microsoft.Windows.Compatibility 9.0.5
|
||||
- Microsoft.Win32.SystemEvents 9.0.6
|
||||
- Microsoft.Windows.Compatibility 9.0.6
|
||||
- Microsoft.Windows.CsWin32 0.2.46-beta
|
||||
- Microsoft.Windows.CsWinRT 2.2.0
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
|
||||
@@ -1485,27 +1549,28 @@ SOFTWARE.
|
||||
- ReverseMarkdown 4.1.0
|
||||
- ScipBe.Common.Office.OneNote 3.0.1
|
||||
- SharpCompress 0.37.2
|
||||
- SkiaSharp.Views.WinUI 2.88.9
|
||||
- StreamJsonRpc 2.21.69
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 9.0.5
|
||||
- System.CodeDom 9.0.6
|
||||
- System.CommandLine 2.0.0-beta4.22272.1
|
||||
- System.ComponentModel.Composition 9.0.5
|
||||
- System.Configuration.ConfigurationManager 9.0.5
|
||||
- System.Data.OleDb 9.0.5
|
||||
- System.Data.SqlClient 4.8.6
|
||||
- System.Diagnostics.EventLog 9.0.5
|
||||
- System.Diagnostics.PerformanceCounter 9.0.5
|
||||
- System.Drawing.Common 9.0.5
|
||||
- System.ComponentModel.Composition 9.0.6
|
||||
- System.Configuration.ConfigurationManager 9.0.6
|
||||
- System.Data.OleDb 9.0.6
|
||||
- System.Data.SqlClient 4.9.0
|
||||
- System.Diagnostics.EventLog 9.0.6
|
||||
- System.Diagnostics.PerformanceCounter 9.0.6
|
||||
- System.Drawing.Common 9.0.6
|
||||
- System.IO.Abstractions 22.0.13
|
||||
- System.IO.Abstractions.TestingHelpers 22.0.13
|
||||
- System.Management 9.0.5
|
||||
- System.Management 9.0.6
|
||||
- System.Net.Http 4.3.4
|
||||
- System.Private.Uri 4.3.2
|
||||
- System.Reactive 6.0.1
|
||||
- System.Runtime.Caching 9.0.5
|
||||
- System.ServiceProcess.ServiceController 9.0.5
|
||||
- System.Text.Encoding.CodePages 9.0.5
|
||||
- System.Text.Json 9.0.5
|
||||
- System.Runtime.Caching 9.0.6
|
||||
- System.ServiceProcess.ServiceController 9.0.6
|
||||
- System.Text.Encoding.CodePages 9.0.6
|
||||
- System.Text.Json 9.0.6
|
||||
- System.Text.RegularExpressions 4.3.1
|
||||
- UnicodeInformation 2.6.0
|
||||
- UnitsNet 5.56.0
|
||||
|
||||
@@ -604,6 +604,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WindowProperties", "WindowP
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesLib", "src\modules\Workspaces\WorkspacesLib\WorkspacesLib.vcxproj", "{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesLibUnitTests", "src\modules\Workspaces\WorkspacesLib.UnitTests\WorkspacesLibUnitTests.vcxproj", "{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332} = {B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkspacesLauncherUI", "src\modules\Workspaces\WorkspacesLauncherUI\WorkspacesLauncherUI.csproj", "{9C53CC25-0623-4569-95BC-B05410675EE3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorkspacesModuleInterface", "src\modules\Workspaces\WorkspacesModuleInterface\WorkspacesModuleInterface.vcxproj", "{45285DF2-9742-4ECA-9AC9-58951FC26489}"
|
||||
@@ -712,6 +717,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "sr
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzingTest", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalculatorEngineCommon", "src\common\CalculatorEngineCommon\CalculatorEngineCommon.vcxproj", "{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@@ -2200,6 +2207,14 @@ Global
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Release|x64.ActiveCfg = Release|x64
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Release|x64.Build.0 = Release|x64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Debug|x64.Build.0 = Debug|x64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|x64.ActiveCfg = Release|x64
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}.Release|x64.Build.0 = Release|x64
|
||||
{9C53CC25-0623-4569-95BC-B05410675EE3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{9C53CC25-0623-4569-95BC-B05410675EE3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{9C53CC25-0623-4569-95BC-B05410675EE3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2584,6 +2599,14 @@ Global
|
||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.ActiveCfg = Release|x64
|
||||
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.Build.0 = Release|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.Build.0 = Debug|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.ActiveCfg = Release|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.Build.0 = Release|x64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2598,14 +2621,14 @@ Global
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.ActiveCfg = Release|x64
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}.Release|x64.Build.0 = Release|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Debug|x64.Build.0 = Debug|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.ActiveCfg = Release|x64
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A}.Release|x64.Build.0 = Release|x64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Debug|x64.Build.0 = Debug|x64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|x64.ActiveCfg = Release|x64
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -2825,6 +2848,7 @@ Global
|
||||
{BE126CBB-AE12-406A-9837-A05ACFCA57A7} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{14CB58B7-D280-4A7A-95DE-4B2DF14EA000} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{9C53CC25-0623-4569-95BC-B05410675EE3} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{45285DF2-9742-4ECA-9AC9-58951FC26489} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{3D63307B-9D27-44FD-B033-B26F39245B85} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
@@ -2879,6 +2903,7 @@ Global
|
||||
{0217E86E-3476-9946-DE8E-9D200CEBD47A} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
|
||||
{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||
{2CF78CF7-8FEB-4BE1-9591-55FA25B48FC6} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
||||
28
README.md
28
README.md
@@ -53,10 +53,10 @@ This is our preferred method.
|
||||
|
||||
### Via Microsoft Store
|
||||
|
||||
Install from the [Microsoft Store's PowerToys page][microsoft-store-link]. You must be using the [new Microsoft Store](https://blogs.windows.com/windowsExperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/) which is available for both Windows 11 and Windows 10.
|
||||
Install from the [Microsoft Store's PowerToys page][microsoft-store-link]. You must be using the [new Microsoft Store](https://blogs.windows.com/windowsExperience/2021/06/24/building-a-new-open-microsoft-store-on-windows-11/), which is available for both Windows 11 and Windows 10.
|
||||
|
||||
### Via WinGet
|
||||
Download PowerToys from [WinGet][winget-link]. Updating PowerToys via winget will respect current PowerToys installation scope. To install PowerToys, run the following command from the command line / PowerShell:
|
||||
Download PowerToys from [WinGet][winget-link]. Updating PowerToys via winget will respect the current PowerToys installation scope. To install PowerToys, run the following command from the command line / PowerShell:
|
||||
|
||||
#### User scope installer [default]
|
||||
```powershell
|
||||
@@ -79,7 +79,7 @@ There is a collection of [third-party plugins](./doc/thirdPartyRunPlugins.md) cr
|
||||
|
||||
## Contributing
|
||||
|
||||
This project welcomes contributions of all types. Besides coding features / bug fixes, other ways to assist include spec writing, design, documentation, and finding bugs. We are excited to work with the power user community to build a set of tools for helping you get the most out of Windows.
|
||||
This project welcomes contributions of all types. Besides coding features / bug fixes, other ways to assist include spec writing, design, documentation, and finding bugs. We are excited to work with the power user community to build a set of tools for helping you get the most out of Windows.
|
||||
|
||||
We ask that **before you start work on a feature that you would like to contribute**, please read our [Contributor's Guide](CONTRIBUTING.md). We would be happy to work with you to figure out the best approach, provide guidance and mentorship throughout feature development, and help avoid any wasted or duplicate effort.
|
||||
|
||||
@@ -99,7 +99,7 @@ In this release, we focused on new features, stability, and automation.
|
||||
|
||||
**✨Highlights**
|
||||
|
||||
- We focused on greatly improving Command Palette's performance and fixing a large amount of bugs. Some new features we've added are:
|
||||
- We focused on greatly improving the Command Palette's performance and fixing a large number of bugs. Some new features we've added are:
|
||||
- Added the ability for Command Palette to search any file using a fallback command.
|
||||
- Added the ability to make the Command Palette global hotkey a low-level keyboard hook.
|
||||
- Added open URL fallback command for the WebSearch extension, enabling users to directly open URLs in the browser from Command Palette.
|
||||
@@ -117,17 +117,17 @@ In this release, we focused on new features, stability, and automation.
|
||||
|
||||
### Command Not Found
|
||||
|
||||
- Updated the WinGet Command Not Found script to only enable the experimental features if they actually exist.
|
||||
- Updated the WinGet Command Not Found script to only enable the experimental features if they exist.
|
||||
|
||||
### Command Palette
|
||||
|
||||
- Updated bug template to include Command Palette module.
|
||||
- Fixed an issue where the toast window was not scaled for DPI, causing layout issues under display scaling.
|
||||
- Fixed an issue where Up/Down keyboard navigation didn't move selection when caret was at position 0, and add continuous navigation like PT Run v1. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed an issue where Up/Down keyboard navigation didn't move selection when the caret was at position 0, and added continuous navigation like PT Run v1. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Updated the Time and Date extension code to simplify it and improve clarity.
|
||||
- Fixed an issue where capitalization in the command causes failure when trying to go to the mouse pointer, resolved by adjusting the command to lowercase.
|
||||
- Added open URL fallback command for the WebSearch extension, enabling users to directly open URLs in the browser from Command Palette. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added setting to enable/disable system tray icon in CmdPal and align terminology with Windows 11. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Added open URL fallback command for the WebSearch extension, enabling users to directly open URLs in the browser from the Command Palette. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added setting to enable/disable system tray icon in CmdPal and aligned terminology with Windows 11. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed an alias update issue by removing the old alias when a new one is set.
|
||||
- Resolved GitHub casing conflict by migrating Exts and exts into a new ext directory, ensuring consistent structure across platforms and preventing path fragmentation.
|
||||
- Fix an issue where the 'Create New Extension' command generated empty file names.
|
||||
@@ -155,9 +155,9 @@ In this release, we focused on new features, stability, and automation.
|
||||
- Refactored CmdPal classes to improve JSON serialization and introduced new serialization contexts for better performance and maintainability.
|
||||
- Added support for ahead-of-time (AoT) compilation.
|
||||
- Added retry mechanism for CmdPal launch.
|
||||
- Removed some unused files from CmdPal.Common to simplify codebase and facilitate marking it as AoT-compatible.
|
||||
- Removed some unused files from CmdPal.Common to simplify the codebase and facilitate marking it as AoT-compatible.
|
||||
- Fixed a bug where a race condition in the update of SearchText caused the cursor in the input box to automatically jump to the end of the line, ensuring SearchText is only updated after it has actually been changed.
|
||||
- Added support for searching any file in fallback command.
|
||||
- Added support for searching any file in the fallback command.
|
||||
- Cleaned up AoT-related code to prevent duplicate operations during testing.
|
||||
- Reduced CmdPal load time by parallelizing extension startup and adding timeouts to prevent misbehaving extensions from blocking others.
|
||||
- Enhanced UI behavior by dismissing the details pane when the list gets emptied, avoiding inconsistent visual states.
|
||||
@@ -179,7 +179,7 @@ In this release, we focused on new features, stability, and automation.
|
||||
|
||||
### Keyboard Manager
|
||||
|
||||
- Fixed an issue where a modifier key, when set without specifying left or right, would get stuck due to incorrect key handling, by tracking the pressed keys and sending the correct key accordingly. Thanks [@mantaionut](https://github.com/mantaionut)!
|
||||
- Fixed an issue where a modifier key, when set without specifying left or right, would get stuck due to incorrect key handling by tracking the pressed keys and sending the correct key accordingly. Thanks [@mantaionut](https://github.com/mantaionut)!
|
||||
|
||||
### PowerRename
|
||||
|
||||
@@ -187,7 +187,7 @@ In this release, we focused on new features, stability, and automation.
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
- Added support for custom formats in the "Time and Date" plugin and improves error messages for invalid input formats. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added support for custom formats in the "Time and Date" plugin and improved error messages for invalid input formats. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fix two crashes: one for WFT on very early dates and another for calculating the week of the month on very late dates (e.g., 31.12.9999), and reorder UI settings. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fix an issue where capitalization in the command causes failure when trying to go to the mouse pointer, resolved by adjusting the command to lowercase.
|
||||
- Added version details to plugin error messages for 'Loading error' and 'Init error'. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
@@ -254,7 +254,7 @@ For [v0.92][github-next-release-work], we'll work on the items below:
|
||||
- New UI Automation tests
|
||||
- Working on installer upgrades
|
||||
- Upgrading Keyboard Manager's editor UI
|
||||
- Stability / bug fixes
|
||||
- Stability, bug fixes
|
||||
|
||||
## PowerToys Community
|
||||
|
||||
@@ -266,7 +266,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct][oss-conduct
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
The application logs basic diagnostic data (telemetry). For more information on privacy and what we collect, see our [PowerToys Data and Privacy documentation](https://aka.ms/powertoys-data-and-privacy-documentation).
|
||||
The application logs basic diagnostic data (telemetry). For more privacy information and what we collect, see our [PowerToys Data and Privacy documentation](https://aka.ms/powertoys-data-and-privacy-documentation).
|
||||
|
||||
[oss-CLA]: https://cla.opensource.microsoft.com
|
||||
[oss-conduct-code]: CODE_OF_CONDUCT.md
|
||||
|
||||
2
deps/cziplib
vendored
2
deps/cziplib
vendored
Submodule deps/cziplib updated: 7a57414261...81314fff0a
@@ -46,6 +46,7 @@ Contact the developers of a plugin directly for assistance with a specific plugi
|
||||
| [QuickNotes](https://github.com/ruslanlap/CommunityPowerToysRunPlugin-QuickNotes) | [ruslanlap](https://github.com/ruslanlap) | Create, manage, and search notes directly from PowerToys Run. |
|
||||
| [Weather](https://github.com/ruslanlap/PowerToysRun-Weather) | [ruslanlap](https://github.com/ruslanlap) | Get real-time weather information directly from PowerToys Run. |
|
||||
| [Pomodoro](https://github.com/ruslanlap/PowerToysRun-Pomodoro) | [ruslanlap](https://github.com/ruslanlap) | Manage Pomodoro productivity sessions directly from PowerToys Run. |
|
||||
| [Definition](https://github.com/ruslanlap/PowerToysRun-Definition) | [ruslanlap](https://github.com/ruslanlap) | Lookup word definitions, phonetics, and synonyms directly in PowerToys Run. |
|
||||
|
||||
## Extending software plugins
|
||||
|
||||
@@ -68,4 +69,5 @@ Below are community created plugins that target a website or software. They are
|
||||
| [Bilibili](https://github.com/Whuihuan/PowerToysRun-Bilibili) | [Whuihuan](https://github.com/Whuihuan) | Use AVID or BVID to parse and jump to Bilibili |
|
||||
| [YubicoOauthOTP](https://github.com/dlnilsson/Community.PowerToys.Run.Plugin.YubicoOauthOTP) | [dlnilsson](https://github.com/dlnilsson) | Display generated codes from OATH accounts stored on the YubiKey in powerToys Run |
|
||||
| [Firefox Bookmark](https://github.com/8LWXpg/PowerToysRun-FirefoxBookmark) | [8LWXpg](https://github.com/8LWXpg) | Open bookmarks in Firefox based browser |
|
||||
[Linear](https://github.com/vednig/powertoys-linear) | [vednig](https://github.com/vednig) | Create Linear Issues directly from Powertoys Run |
|
||||
| [Linear](https://github.com/vednig/powertoys-linear) | [vednig](https://github.com/vednig) | Create Linear Issues directly from Powertoys Run |
|
||||
| [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. |
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -43,4 +43,4 @@
|
||||
<Analyzer Remove="@(Analyzer)" Condition="%(Analyzer.NuGetPackageId) == 'Microsoft.Windows.CsWinRT'" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -76,3 +76,47 @@ using System.Diagnostics.CodeAnalysis;
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.INotifyPropertyChangedGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "type", Target = "~T:Peek.UI.Views.TitleBar")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")]
|
||||
|
||||
// HexBox control in RegistryPreviewUILib (We decided to copy the original code and not fix all theses problems for easier updating.)
|
||||
[assembly: SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Naming", "CA1720:Identifiers should not contain type names", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Performance", "CA1805:Do not initialize unnecessarily", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1642:Constructor summary documentation should begin with standard text", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1648:<inheritdoc> has been used on an element that doesn't inherit from a base class or implement an interface.", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1500:Braces for multi-line statements should not share line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1502:Element should not be on a single line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1505:Opening braces should not be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1507:Code should not contain multiple blank lines in a row", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1508:Closing braces should not be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1509:Opening braces should not be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:Single-line comments should not be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1514:Element documentation header should be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment should be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1119:Statement should not use unnecessary parenthesis", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1407:Arithmetic expressions should declare precedence", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1413:Use trailing comma in multi-line initializers", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1312:Variable names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives should be placed correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1108:Block statements should not contain embedded comments", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1129:Do not use default value type constructor", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1000:Keywords should be spaced correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:Symbols should be spaced correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:Single line comments should begin with single space", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1024:Colons Should Be Spaced Correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1028:Code should not contain trailing whitespace", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Usage", "CsWinRT1028:Class is not marked partial", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
|
||||
24
src/common/CalculatorEngineCommon/Calculator.cpp
Normal file
24
src/common/CalculatorEngineCommon/Calculator.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "pch.h"
|
||||
#include "Calculator.h"
|
||||
#include "Calculator.g.cpp"
|
||||
#include "ExprtkEvaluator.h"
|
||||
|
||||
namespace winrt::CalculatorEngineCommon::implementation
|
||||
{
|
||||
Calculator::Calculator(winrt::Windows::Foundation::Collections::IPropertySet const& constants)
|
||||
{
|
||||
for (auto const& pair : constants)
|
||||
{
|
||||
auto key = pair.Key();
|
||||
auto value = winrt::unbox_value<double>(pair.Value());
|
||||
m_constants.emplace(winrt::to_string(key), value);
|
||||
}
|
||||
}
|
||||
|
||||
hstring Calculator::EvaluateExpression(hstring const& expression)
|
||||
{
|
||||
auto result = ExprtkCalculator::internal::EvaluateExpression(winrt::to_string(expression), m_constants);
|
||||
|
||||
return hstring(result);
|
||||
}
|
||||
}
|
||||
25
src/common/CalculatorEngineCommon/Calculator.h
Normal file
25
src/common/CalculatorEngineCommon/Calculator.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Calculator.g.h"
|
||||
|
||||
namespace winrt::CalculatorEngineCommon::implementation
|
||||
{
|
||||
struct Calculator : CalculatorT<Calculator>
|
||||
{
|
||||
Calculator() = default;
|
||||
|
||||
Calculator(winrt::Windows::Foundation::Collections::IPropertySet const& constants);
|
||||
|
||||
winrt::hstring EvaluateExpression(winrt::hstring const& expression);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, double> m_constants;
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::CalculatorEngineCommon::factory_implementation
|
||||
{
|
||||
struct Calculator : CalculatorT<Calculator, implementation::Calculator>
|
||||
{
|
||||
};
|
||||
}
|
||||
10
src/common/CalculatorEngineCommon/Calculator.idl
Normal file
10
src/common/CalculatorEngineCommon/Calculator.idl
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CalculatorEngineCommon
|
||||
{
|
||||
[default_interface]
|
||||
runtimeclass Calculator
|
||||
{
|
||||
Calculator();
|
||||
Calculator(Windows.Foundation.Collections.IPropertySet constants);
|
||||
String EvaluateExpression(String expression);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||
186
src/common/CalculatorEngineCommon/CalculatorEngineCommon.vcxproj
Normal file
186
src/common/CalculatorEngineCommon/CalculatorEngineCommon.vcxproj
Normal file
@@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
|
||||
<ProjectGuid>{2cf78cf7-8feb-4be1-9591-55fa25b48fc6}</ProjectGuid>
|
||||
<ProjectName>CalculatorEngineCommon</ProjectName>
|
||||
<RootNamespace>CalculatorEngineCommon</RootNamespace>
|
||||
<AppxPackage>false</AppxPackage>
|
||||
</PropertyGroup>
|
||||
<!-- BEGIN common.build.pre.props -->
|
||||
<PropertyGroup Label="Configuration">
|
||||
<EnableHybridCRT>true</EnableHybridCRT>
|
||||
<UseCrtSDKReferenceStaticWarning Condition="'$(EnableHybridCRT)'=='true'">false</UseCrtSDKReferenceStaticWarning>
|
||||
</PropertyGroup>
|
||||
<!-- END common.build.pre.props -->
|
||||
<!-- BEGIN cppwinrt.build.pre.props -->
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTEnabled>true</CppWinRTEnabled>
|
||||
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<MinimalCoreWin>true</MinimalCoreWin>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<WindowsStoreApp>true</WindowsStoreApp>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<UseCrtSDKReference Condition="'$(EnableHybridCRT)'=='true'">false</UseCrtSDKReference>
|
||||
<!-- The SDK reference breaks the Hybrid CRT -->
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- We have to use the Desktop platform for Hybrid CRT to work. -->
|
||||
<_VC_Target_Library_Platform>Desktop</_VC_Target_Library_Platform>
|
||||
<_NoWinAPIFamilyApp>true</_NoWinAPIFamilyApp>
|
||||
</PropertyGroup>
|
||||
<!-- END cppwinrt.build.pre.props -->
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="PropertySheet.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup>
|
||||
<TargetName>CalculatorEngineCommon</TargetName>
|
||||
<OutDir>..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>../../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
<ModuleDefinitionFile>CalculatorEngineCommon.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>Shell32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ExprtkEvaluator.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="exprtk.hpp" />
|
||||
<ClInclude Include="Calculator.h">
|
||||
<DependentUpon>Calculator.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ExprtkEvaluator.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Calculator.cpp">
|
||||
<DependentUpon>Calculator.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="Calculator.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="CalculatorEngineCommon.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\version\version.vcxproj">
|
||||
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
<!-- BEGIN common.build.post.props -->
|
||||
<!--
|
||||
The Hybrid CRT model statically links the runtime and STL and dynamically
|
||||
links the UCRT instead of the VC++ CRT. The UCRT ships with Windows.
|
||||
WinAppSDK asserts that this is "supported according to the CRT maintainer."
|
||||
|
||||
This must come before Microsoft.Cpp.targets because it manipulates ClCompile.RuntimeLibrary.
|
||||
-->
|
||||
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and '$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<!-- We use MultiThreadedDebug, rather than MultiThreadedDebugDLL, to avoid DLL dependencies on VCRUNTIME140d.dll and MSVCP140d.dll. -->
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrtd.lib</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrtd.lib</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and ('$(Configuration)'=='Release' or '$(Configuration)'=='AuditMode')">
|
||||
<ClCompile>
|
||||
<!-- We use MultiThreaded, rather than MultiThreadedDLL, to avoid DLL dependencies on VCRUNTIME140.dll and MSVCP140.dll. -->
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<!-- Link statically against the runtime and STL, but link dynamically against the CRT by ignoring the static CRT
|
||||
lib and instead linking against the Universal CRT DLL import library. This "hybrid" linking mechanism is
|
||||
supported according to the CRT maintainer. Dynamic linking against the CRT makes the binaries a bit smaller
|
||||
than they would otherwise be if the CRT, runtime, and STL were all statically linked in. -->
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries);libucrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrt.lib</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<!-- END common.build.post.props -->
|
||||
</Project>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Resources">
|
||||
<UniqueIdentifier>accd3aa8-1ba0-4223-9bbe-0c431709210b</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{926ab91d-31b4-48c3-b9a4-e681349f27f0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="Calculator.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CalculatorEngineCommon.def" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
50
src/common/CalculatorEngineCommon/ExprtkEvaluator.cpp
Normal file
50
src/common/CalculatorEngineCommon/ExprtkEvaluator.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "ExprtkEvaluator.h"
|
||||
#include "exprtk.hpp"
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace ExprtkCalculator::internal
|
||||
{
|
||||
|
||||
std::wstring ToWStringFullPrecision(double value)
|
||||
{
|
||||
std::wostringstream oss;
|
||||
oss << std::fixed << std::setprecision(15) << value;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::wstring EvaluateExpression(
|
||||
const std::string& expressionText,
|
||||
const std::unordered_map<std::string, double>& constants)
|
||||
{
|
||||
exprtk::symbol_table<double> symbol_table;
|
||||
|
||||
for (auto const& [name, value] : constants)
|
||||
{
|
||||
symbol_table.add_constant(name, value);
|
||||
}
|
||||
|
||||
exprtk::expression<double> expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
exprtk::parser<double> parser;
|
||||
|
||||
// Enable all base functions and arithmetic operators
|
||||
parser.settings().enable_all_base_functions(); // Enable all base functions like sin, cos, log, etc.
|
||||
parser.settings().enable_all_arithmetic_ops(); // Enable all arithmetic operators like +, -, *, /, etc.
|
||||
|
||||
// Disable all control structures and assignment operators to ensure only expressions are evaluated
|
||||
parser.settings().disable_all_control_structures(); // Disable control structures like if, for, while, etc.
|
||||
parser.settings().disable_all_assignment_ops(); // Disable assignment operators like =, +=, -=, etc.
|
||||
|
||||
// Disabled for now, but can be enabled later for enhanced functionality
|
||||
parser.settings().disable_all_logic_ops(); // Disable logical operators like &&, ||, !, etc.
|
||||
parser.settings().disable_all_inequality_ops(); // Disable inequality operators like <, >, <=, >=, !=, etc.
|
||||
|
||||
if (!parser.compile(expressionText, expression))
|
||||
return L"NaN";
|
||||
|
||||
return ToWStringFullPrecision(expression.value());
|
||||
}
|
||||
}
|
||||
10
src/common/CalculatorEngineCommon/ExprtkEvaluator.h
Normal file
10
src/common/CalculatorEngineCommon/ExprtkEvaluator.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ExprtkCalculator::internal
|
||||
{
|
||||
std::wstring EvaluateExpression(
|
||||
const std::string& expression,
|
||||
const std::unordered_map<std::string, double>& constants);
|
||||
}
|
||||
16
src/common/CalculatorEngineCommon/PropertySheet.props
Normal file
16
src/common/CalculatorEngineCommon/PropertySheet.props
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<!--
|
||||
To customize common C++/WinRT project properties:
|
||||
* right-click the project node
|
||||
* expand the Common Properties item
|
||||
* select the C++/WinRT property page
|
||||
|
||||
For more advanced scenarios, and complete documentation, please see:
|
||||
https://github.com/Microsoft/cppwinrt/tree/master/nuget
|
||||
-->
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup />
|
||||
</Project>
|
||||
46251
src/common/CalculatorEngineCommon/exprtk.hpp
Normal file
46251
src/common/CalculatorEngineCommon/exprtk.hpp
Normal file
File diff suppressed because it is too large
Load Diff
4
src/common/CalculatorEngineCommon/packages.config
Normal file
4
src/common/CalculatorEngineCommon/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
</packages>
|
||||
1
src/common/CalculatorEngineCommon/pch.cpp
Normal file
1
src/common/CalculatorEngineCommon/pch.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
||||
4
src/common/CalculatorEngineCommon/pch.h
Normal file
4
src/common/CalculatorEngineCommon/pch.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <unknwn.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
29
src/common/CalculatorEngineCommon/readme.md
Normal file
29
src/common/CalculatorEngineCommon/readme.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# C++/WinRT CalculatorEngine Project Overview
|
||||
|
||||
This project wraps the exprtk expression parsing library with a C++/WinRT component,
|
||||
making advanced mathematical evaluation capabilities available to Windows applications.
|
||||
It is designed specifically to provide calculation support for the CmdPal calculator extension.
|
||||
|
||||
## Using exprtk
|
||||
|
||||
This project uses [exprtk](https://github.com/ArashPartow/exprtk) as the
|
||||
expression parsing and evaluation engine.
|
||||
|
||||
How to use exprtk in this project:
|
||||
- The exprtk header file (`exprtk.hpp`) is included in the project source.
|
||||
- You can use exprtk to parse and evaluate mathematical expressions in your
|
||||
C++ code. For example:
|
||||
|
||||
```cpp
|
||||
#include "exprtk.hpp"
|
||||
exprtk::expression<double> expression;
|
||||
exprtk::parser<double> parser;
|
||||
std::string formula = "3 + 4 * 2";
|
||||
parser.compile(formula, expression);
|
||||
double result = expression.value();
|
||||
```
|
||||
|
||||
How to update exprtk:
|
||||
1. Download the latest `exprtk.hpp` from the [official repository](https://github.com/ArashPartow/exprtk).
|
||||
2. Replace the existing `exprtk.hpp` file in the project with the new version.
|
||||
3. Rebuild the project to ensure compatibility and take advantage of any updates.
|
||||
@@ -20,7 +20,7 @@
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
|
||||
"IterationPath": "OS\\Future"
|
||||
},
|
||||
"jobNotificationEmail": "leilzh@microsoft.com",
|
||||
"jobNotificationEmail": "PowerToys@microsoft.com",
|
||||
"skip": false,
|
||||
"rebootAfterSetup": false,
|
||||
"oneFuzzJobs": [
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
|
||||
"IterationPath": "OS\\Future"
|
||||
},
|
||||
"jobNotificationEmail": "mengyuanchen@microsoft.com",
|
||||
"jobNotificationEmail": "PowerToys@microsoft.com",
|
||||
"skip": false,
|
||||
"rebootAfterSetup": false,
|
||||
"oneFuzzJobs": [
|
||||
|
||||
@@ -193,27 +193,29 @@ namespace WorkspacesEditor.ViewModels
|
||||
ApplyShortcut(editedProject);
|
||||
}
|
||||
|
||||
private string GetDesktopShortcutAddress(Project project) => Path.Combine(FolderUtils.Desktop(), project.Name + ".lnk");
|
||||
|
||||
private string GetShortcutStoreAddress(Project project)
|
||||
{
|
||||
var dataFolder = FolderUtils.DataFolder();
|
||||
Directory.CreateDirectory(dataFolder);
|
||||
var shortcutStoreFolder = Path.Combine(dataFolder, "WorkspacesIcons");
|
||||
Directory.CreateDirectory(shortcutStoreFolder);
|
||||
return Path.Combine(shortcutStoreFolder, project.Id + ".ico");
|
||||
}
|
||||
|
||||
private void ApplyShortcut(Project project)
|
||||
{
|
||||
string basePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string shortcutAddress = Path.Combine(FolderUtils.Desktop(), project.Name + ".lnk");
|
||||
string shortcutIconFilename = Path.Combine(FolderUtils.Temp(), project.Id + ".ico");
|
||||
|
||||
if (!project.IsShortcutNeeded)
|
||||
{
|
||||
if (File.Exists(shortcutIconFilename))
|
||||
{
|
||||
File.Delete(shortcutIconFilename);
|
||||
}
|
||||
|
||||
if (File.Exists(shortcutAddress))
|
||||
{
|
||||
File.Delete(shortcutAddress);
|
||||
}
|
||||
|
||||
RemoveShortcut(project);
|
||||
return;
|
||||
}
|
||||
|
||||
var basePath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var shortcutAddress = GetDesktopShortcutAddress(project);
|
||||
var shortcutIconFilename = GetShortcutStoreAddress(project);
|
||||
|
||||
Bitmap icon = WorkspacesIcon.DrawIcon(WorkspacesIcon.IconTextFromProjectName(project.Name), App.ThemeManager.GetCurrentTheme());
|
||||
WorkspacesIcon.SaveIcon(icon, shortcutIconFilename);
|
||||
|
||||
@@ -360,8 +362,8 @@ namespace WorkspacesEditor.ViewModels
|
||||
|
||||
private void RemoveShortcut(Project selectedProject)
|
||||
{
|
||||
string shortcutAddress = Path.Combine(FolderUtils.Desktop(), selectedProject.Name + ".lnk");
|
||||
string shortcutIconFilename = Path.Combine(FolderUtils.Temp(), selectedProject.Id + ".ico");
|
||||
string shortcutAddress = GetDesktopShortcutAddress(selectedProject);
|
||||
string shortcutIconFilename = GetShortcutStoreAddress(selectedProject);
|
||||
|
||||
if (File.Exists(shortcutIconFilename))
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">System</dpiAwareness>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
|
||||
|
||||
239
src/modules/Workspaces/WorkspacesLib.UnitTests/AppUtilsTests.cpp
Normal file
239
src/modules/Workspaces/WorkspacesLib.UnitTests/AppUtilsTests.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include "pch.h"
|
||||
#include <filesystem> // Add this line
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace WorkspacesLibUnitTests
|
||||
{
|
||||
TEST_CLASS(AppUtilsTests)
|
||||
{
|
||||
public:
|
||||
TEST_METHOD(GetCurrentFolder_ReturnsNonEmptyPath)
|
||||
{
|
||||
// Act
|
||||
const std::wstring& result = Utils::Apps::GetCurrentFolder();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result.empty());
|
||||
Assert::IsTrue(std::filesystem::exists(result));
|
||||
}
|
||||
|
||||
TEST_METHOD(GetCurrentFolderUpper_ReturnsUppercasePath)
|
||||
{
|
||||
// Act
|
||||
const std::wstring& currentFolder = Utils::Apps::GetCurrentFolder();
|
||||
const std::wstring& currentFolderUpper = Utils::Apps::GetCurrentFolderUpper();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(currentFolderUpper.empty());
|
||||
Assert::AreEqual(currentFolder.length(), currentFolderUpper.length());
|
||||
|
||||
// Verify it's actually uppercase
|
||||
std::wstring expectedUpper = currentFolder;
|
||||
std::transform(expectedUpper.begin(), expectedUpper.end(), expectedUpper.begin(), towupper);
|
||||
Assert::AreEqual(expectedUpper, currentFolderUpper);
|
||||
}
|
||||
|
||||
TEST_METHOD(GetCurrentFolder_ConsistentResults)
|
||||
{
|
||||
// Act
|
||||
const std::wstring& result1 = Utils::Apps::GetCurrentFolder();
|
||||
const std::wstring& result2 = Utils::Apps::GetCurrentFolder();
|
||||
|
||||
// Assert
|
||||
Assert::AreEqual(result1, result2);
|
||||
}
|
||||
|
||||
TEST_METHOD(GetCurrentFolderUpper_ConsistentResults)
|
||||
{
|
||||
// Act
|
||||
const std::wstring& result1 = Utils::Apps::GetCurrentFolderUpper();
|
||||
const std::wstring& result2 = Utils::Apps::GetCurrentFolderUpper();
|
||||
|
||||
// Assert
|
||||
Assert::AreEqual(result1, result2);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsEdge_EdgePath_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.installPath = L"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsEdge();
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsEdge_NonEdgePath_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.installPath = L"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsEdge();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsEdge_EmptyPath_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.installPath = L"";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsEdge();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsChrome_ChromePath_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.installPath = L"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsChrome();
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsChrome_NonChromePath_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.installPath = L"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsChrome();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsChrome_EmptyPath_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.installPath = L"";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsChrome();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsSteamGame_SteamProtocol_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.protocolPath = L"steam://run/123456";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsSteamGame();
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsSteamGame_NonSteamProtocol_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.protocolPath = L"https://example.com";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsSteamGame();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsSteamGame_EmptyProtocol_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.protocolPath = L"";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsSteamGame();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_IsSteamGame_PartialSteamString_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData appData;
|
||||
appData.protocolPath = L"http://run/123456";
|
||||
|
||||
// Act
|
||||
bool result = appData.IsSteamGame();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_DefaultValues)
|
||||
{
|
||||
// Arrange & Act
|
||||
Utils::Apps::AppData appData;
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(appData.name.empty());
|
||||
Assert::IsTrue(appData.installPath.empty());
|
||||
Assert::IsTrue(appData.packageFullName.empty());
|
||||
Assert::IsTrue(appData.appUserModelId.empty());
|
||||
Assert::IsTrue(appData.pwaAppId.empty());
|
||||
Assert::IsTrue(appData.protocolPath.empty());
|
||||
Assert::IsFalse(appData.canLaunchElevated);
|
||||
}
|
||||
|
||||
TEST_METHOD(AppData_MultipleBrowserDetection)
|
||||
{
|
||||
// Arrange
|
||||
Utils::Apps::AppData edgeApp;
|
||||
edgeApp.installPath = L"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
|
||||
|
||||
Utils::Apps::AppData chromeApp;
|
||||
chromeApp.installPath = L"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe";
|
||||
|
||||
Utils::Apps::AppData otherApp;
|
||||
otherApp.installPath = L"C:\\Program Files\\Firefox\\firefox.exe";
|
||||
|
||||
// Act & Assert
|
||||
Assert::IsTrue(edgeApp.IsEdge());
|
||||
Assert::IsFalse(edgeApp.IsChrome());
|
||||
Assert::IsFalse(edgeApp.IsSteamGame());
|
||||
|
||||
Assert::IsFalse(chromeApp.IsEdge());
|
||||
Assert::IsTrue(chromeApp.IsChrome());
|
||||
Assert::IsFalse(chromeApp.IsSteamGame());
|
||||
|
||||
Assert::IsFalse(otherApp.IsEdge());
|
||||
Assert::IsFalse(otherApp.IsChrome());
|
||||
Assert::IsFalse(otherApp.IsSteamGame());
|
||||
}
|
||||
|
||||
TEST_METHOD(GetAppsList_ReturnsAppList)
|
||||
{
|
||||
// Act
|
||||
Utils::Apps::AppList apps = Utils::Apps::GetAppsList();
|
||||
|
||||
// Assert
|
||||
// The list can be empty or non-empty depending on the system
|
||||
// But it should not crash and should return a valid list
|
||||
Assert::IsTrue(apps.size() >= 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
#include "pch.h"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace WorkspacesLibUnitTests
|
||||
{
|
||||
TEST_CLASS (JsonUtilsTests)
|
||||
{
|
||||
private:
|
||||
std::wstring CreateTempJsonFile(const std::wstring& content)
|
||||
{
|
||||
std::wstring tempPath = std::filesystem::temp_directory_path();
|
||||
tempPath += L"\\test_workspace_" + std::to_wstring(GetTickCount64()) + L".json";
|
||||
|
||||
std::wofstream file(tempPath);
|
||||
file << content;
|
||||
file.close();
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
void DeleteTempFile(const std::wstring& filePath)
|
||||
{
|
||||
if (std::filesystem::exists(filePath))
|
||||
{
|
||||
std::filesystem::remove(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
TEST_METHOD (ReadSingleWorkspace_NonExistentFile_ReturnsEmptyWorkspace)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring nonExistentFile = L"C:\\NonExistent\\File.json";
|
||||
|
||||
// Act
|
||||
auto result = JsonUtils::ReadSingleWorkspace(nonExistentFile);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result.isOk());
|
||||
auto workspace = result.value();
|
||||
Assert::IsTrue(workspace.name.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (ReadSingleWorkspace_InvalidJsonFile_ReturnsError)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring tempFile = CreateTempJsonFile(L"invalid json content {");
|
||||
|
||||
// Act
|
||||
auto result = JsonUtils::ReadSingleWorkspace(tempFile);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result.isError());
|
||||
Assert::AreEqual(static_cast<int>(JsonUtils::WorkspacesFileError::IncorrectFileError),
|
||||
static_cast<int>(result.error()));
|
||||
|
||||
// Cleanup
|
||||
DeleteTempFile(tempFile);
|
||||
}
|
||||
|
||||
TEST_METHOD (ReadWorkspaces_NonExistentFile_ReturnsEmptyVector)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring nonExistentFile = L"C:\\NonExistent\\File.json";
|
||||
|
||||
// Act
|
||||
auto result = JsonUtils::ReadWorkspaces(nonExistentFile);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result.isError());
|
||||
Assert::AreEqual(static_cast<int>(JsonUtils::WorkspacesFileError::IncorrectFileError),
|
||||
static_cast<int>(result.error()));
|
||||
}
|
||||
|
||||
TEST_METHOD (ReadWorkspaces_InvalidJsonFile_ReturnsError)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring tempFile = CreateTempJsonFile(L"invalid json content {");
|
||||
|
||||
// Act
|
||||
auto result = JsonUtils::ReadWorkspaces(tempFile);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result.isError());
|
||||
Assert::AreEqual(static_cast<int>(JsonUtils::WorkspacesFileError::IncorrectFileError),
|
||||
static_cast<int>(result.error()));
|
||||
|
||||
// Cleanup
|
||||
DeleteTempFile(tempFile);
|
||||
}
|
||||
|
||||
TEST_METHOD (Write_ValidWorkspace_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring tempPath = std::filesystem::temp_directory_path();
|
||||
tempPath += L"\\test_write_workspace_" + std::to_wstring(GetTickCount64()) + L".json";
|
||||
|
||||
WorkspacesData::WorkspacesProject workspace;
|
||||
workspace.name = L"Test Workspace";
|
||||
|
||||
// Convert string to time_t
|
||||
std::tm tm = {};
|
||||
workspace.creationTime = std::mktime(&tm);
|
||||
|
||||
// Act
|
||||
bool result = JsonUtils::Write(tempPath, workspace);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
Assert::IsTrue(std::filesystem::exists(tempPath));
|
||||
|
||||
// Cleanup
|
||||
DeleteTempFile(tempPath);
|
||||
}
|
||||
|
||||
TEST_METHOD (Write_ValidWorkspacesList_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring tempPath = std::filesystem::temp_directory_path();
|
||||
tempPath += L"\\test_write_workspaces_" + std::to_wstring(GetTickCount64()) + L".json";
|
||||
|
||||
std::vector<WorkspacesData::WorkspacesProject> workspaces;
|
||||
|
||||
WorkspacesData::WorkspacesProject workspace1;
|
||||
workspace1.name = L"Test Workspace 1";
|
||||
workspace1.creationTime = std::time(nullptr);
|
||||
|
||||
WorkspacesData::WorkspacesProject workspace2;
|
||||
workspace2.name = L"Test Workspace 2";
|
||||
workspace2.creationTime = std::time(nullptr);
|
||||
|
||||
workspaces.push_back(workspace1);
|
||||
workspaces.push_back(workspace2);
|
||||
|
||||
// Act
|
||||
bool result = JsonUtils::Write(tempPath, workspaces);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
Assert::IsTrue(std::filesystem::exists(tempPath));
|
||||
|
||||
// Cleanup
|
||||
DeleteTempFile(tempPath);
|
||||
}
|
||||
|
||||
TEST_METHOD (Write_EmptyWorkspacesList_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring tempPath = std::filesystem::temp_directory_path();
|
||||
tempPath += L"\\test_write_empty_" + std::to_wstring(GetTickCount64()) + L".json";
|
||||
|
||||
std::vector<WorkspacesData::WorkspacesProject> emptyWorkspaces;
|
||||
|
||||
// Act
|
||||
bool result = JsonUtils::Write(tempPath, emptyWorkspaces);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
Assert::IsTrue(std::filesystem::exists(tempPath));
|
||||
|
||||
// Cleanup
|
||||
DeleteTempFile(tempPath);
|
||||
}
|
||||
|
||||
/*
|
||||
TEST_METHOD(Write_InvalidPath_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring invalidPath = L"C:\\NonExistent\\Path\\workspace.json";
|
||||
|
||||
WorkspacesData::WorkspacesProject workspace;
|
||||
workspace.name = L"Test Workspace";
|
||||
workspace.creationTime = std::time(nullptr);
|
||||
|
||||
// Act
|
||||
bool result = JsonUtils::Write(invalidPath, workspace);
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
*/
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "pch.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace WorkspacesLibUnitTests
|
||||
{
|
||||
TEST_CLASS (PwaHelperTests)
|
||||
{
|
||||
public:
|
||||
TEST_METHOD (PwaHelper_Constructor_DoesNotThrow)
|
||||
{
|
||||
// Act & Assert - Constructor should not crash when called
|
||||
try
|
||||
{
|
||||
Utils::PwaHelper helper;
|
||||
// If we get here, the constructor didn't throw
|
||||
Assert::IsTrue(true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Assert::Fail(L"PwaHelper constructor should not throw exceptions");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_GetEdgeAppId_EmptyAumid_ReturnsEmpty)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
std::wstring emptyAumid = L"";
|
||||
|
||||
// Act
|
||||
auto result = helper.GetEdgeAppId(emptyAumid);
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result.has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_GetChromeAppId_EmptyAumid_ReturnsEmpty)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
std::wstring emptyAumid = L"";
|
||||
|
||||
// Act
|
||||
auto result = helper.GetChromeAppId(emptyAumid);
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result.has_value());
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_SearchPwaName_EmptyParameters_ReturnsEmpty)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
std::wstring emptyPwaAppId = L"";
|
||||
std::wstring emptyWindowAumid = L"";
|
||||
|
||||
// Act
|
||||
std::wstring result = helper.SearchPwaName(emptyPwaAppId, emptyWindowAumid);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_SearchPwaName_NonExistentIds_ReturnsEmpty)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
std::wstring nonExistentPwaAppId = L"nonexistent_app_id";
|
||||
std::wstring nonExistentWindowAumid = L"nonexistent_aumid";
|
||||
|
||||
// Act
|
||||
std::wstring result = helper.SearchPwaName(nonExistentPwaAppId, nonExistentWindowAumid);
|
||||
|
||||
// TODO: is it really expected?
|
||||
Assert::IsTrue(result == nonExistentWindowAumid);
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_GetAUMIDFromWindow_InvalidWindow_ReturnsEmpty)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
HWND invalidWindow = nullptr;
|
||||
|
||||
// Act
|
||||
std::wstring result = helper.GetAUMIDFromWindow(invalidWindow);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_GetEdgeAppId_ValidConstruction_DoesNotCrash)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
std::wstring testAumid = L"Microsoft.MicrosoftEdge_8wekyb3d8bbwe!App";
|
||||
|
||||
// Act & Assert - Should not crash
|
||||
auto result = helper.GetEdgeAppId(testAumid);
|
||||
// Result can be empty or have value, but should not crash
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_GetChromeAppId_ValidConstruction_DoesNotCrash)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
std::wstring testAumid = L"Chrome.App.TestId";
|
||||
|
||||
// Act & Assert - Should not crash
|
||||
auto result = helper.GetChromeAppId(testAumid);
|
||||
// Result can be empty or have value, but should not crash
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
#include "pch.h"
|
||||
#include <StringUtils.h>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace WorkspacesLibUnitTests
|
||||
{
|
||||
TEST_CLASS(StringUtilsTests)
|
||||
{
|
||||
public:
|
||||
TEST_METHOD(CaseInsensitiveEquals_SameStrings_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"test";
|
||||
std::wstring str2 = L"test";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseInsensitiveEquals_DifferentCase_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"Test";
|
||||
std::wstring str2 = L"TEST";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseInsensitiveEquals_MixedCase_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"TeSt StRiNg";
|
||||
std::wstring str2 = L"test STRING";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseInsensitiveEquals_DifferentStrings_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"test";
|
||||
std::wstring str2 = L"different";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseInsensitiveEquals_DifferentLengths_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"test";
|
||||
std::wstring str2 = L"testing";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseInsensitiveEquals_EmptyStrings_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"";
|
||||
std::wstring str2 = L"";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseInsensitiveEquals_OneEmpty_ReturnsFalse)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"test";
|
||||
std::wstring str2 = L"";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(CaseInsensitiveEquals_SpecialCharacters_ReturnsTrue)
|
||||
{
|
||||
// Arrange
|
||||
std::wstring str1 = L"Test-123_Special!";
|
||||
std::wstring str2 = L"test-123_special!";
|
||||
|
||||
// Act
|
||||
bool result = StringUtils::CaseInsensitiveEquals(str1, str2);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "pch.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace WorkspacesLibUnitTests
|
||||
{
|
||||
TEST_CLASS(WorkspacesDataTests)
|
||||
{
|
||||
public:
|
||||
TEST_METHOD(WorkspacesFile_ReturnsValidPath)
|
||||
{
|
||||
// Act
|
||||
std::wstring result = WorkspacesData::WorkspacesFile();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result.empty());
|
||||
Assert::IsTrue(result.find(L"workspaces.json") != std::wstring::npos);
|
||||
}
|
||||
|
||||
TEST_METHOD(TempWorkspacesFile_ReturnsValidPath)
|
||||
{
|
||||
// Act
|
||||
std::wstring result = WorkspacesData::TempWorkspacesFile();
|
||||
|
||||
// Assert
|
||||
Assert::IsFalse(result.empty());
|
||||
Assert::IsTrue(result.find(L"temp-workspaces.json") != std::wstring::npos);
|
||||
}
|
||||
|
||||
TEST_METHOD(WorkspacesFile_TempWorkspacesFile_DifferentPaths)
|
||||
{
|
||||
// Act
|
||||
std::wstring workspacesFile = WorkspacesData::WorkspacesFile();
|
||||
std::wstring tempWorkspacesFile = WorkspacesData::TempWorkspacesFile();
|
||||
|
||||
// Assert
|
||||
Assert::AreNotEqual(workspacesFile, tempWorkspacesFile);
|
||||
}
|
||||
|
||||
TEST_METHOD(Position_ToRect_ConvertsCorrectly)
|
||||
{
|
||||
// Arrange
|
||||
WorkspacesData::WorkspacesProject::Application::Position position;
|
||||
position.x = 100;
|
||||
position.y = 200;
|
||||
position.width = 800;
|
||||
position.height = 600;
|
||||
|
||||
// Act
|
||||
RECT rect = position.toRect();
|
||||
|
||||
// Assert
|
||||
Assert::AreEqual(100, static_cast<int>(rect.left));
|
||||
Assert::AreEqual(200, static_cast<int>(rect.top));
|
||||
Assert::AreEqual(900, static_cast<int>(rect.right)); // x + width
|
||||
Assert::AreEqual(800, static_cast<int>(rect.bottom)); // y + height
|
||||
}
|
||||
|
||||
TEST_METHOD(Position_ToRect_ZeroPosition)
|
||||
{
|
||||
// Arrange
|
||||
WorkspacesData::WorkspacesProject::Application::Position position;
|
||||
position.x = 0;
|
||||
position.y = 0;
|
||||
position.width = 0;
|
||||
position.height = 0;
|
||||
|
||||
// Act
|
||||
RECT rect = position.toRect();
|
||||
|
||||
// Assert
|
||||
Assert::AreEqual(0, static_cast<int>(rect.left));
|
||||
Assert::AreEqual(0, static_cast<int>(rect.top));
|
||||
Assert::AreEqual(0, static_cast<int>(rect.right));
|
||||
Assert::AreEqual(0, static_cast<int>(rect.bottom));
|
||||
}
|
||||
|
||||
TEST_METHOD(Position_ToRect_NegativeCoordinates)
|
||||
{
|
||||
// Arrange
|
||||
WorkspacesData::WorkspacesProject::Application::Position position;
|
||||
position.x = -100;
|
||||
position.y = -50;
|
||||
position.width = 200;
|
||||
position.height = 150;
|
||||
|
||||
// Act
|
||||
RECT rect = position.toRect();
|
||||
|
||||
// Assert
|
||||
Assert::AreEqual(-100, static_cast<int>(rect.left));
|
||||
Assert::AreEqual(-50, static_cast<int>(rect.top));
|
||||
Assert::AreEqual(100, static_cast<int>(rect.right)); // -100 + 200
|
||||
Assert::AreEqual(100, static_cast<int>(rect.bottom)); // -50 + 150
|
||||
}
|
||||
|
||||
TEST_METHOD(Application_DefaultValues)
|
||||
{
|
||||
// Arrange & Act
|
||||
WorkspacesData::WorkspacesProject::Application app;
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(app.id.empty());
|
||||
Assert::IsTrue(app.name.empty());
|
||||
Assert::IsTrue(app.title.empty());
|
||||
Assert::IsTrue(app.path.empty());
|
||||
Assert::IsTrue(app.packageFullName.empty());
|
||||
Assert::IsTrue(app.appUserModelId.empty());
|
||||
Assert::IsTrue(app.pwaAppId.empty());
|
||||
Assert::IsTrue(app.commandLineArgs.empty());
|
||||
Assert::IsFalse(app.isElevated);
|
||||
Assert::IsFalse(app.canLaunchElevated);
|
||||
Assert::IsFalse(app.isMinimized);
|
||||
Assert::IsFalse(app.isMaximized);
|
||||
Assert::AreEqual(0, static_cast<int>(app.position.x));
|
||||
Assert::AreEqual(0, static_cast<int>(app.position.y));
|
||||
Assert::AreEqual(0, static_cast<int>(app.position.width));
|
||||
Assert::AreEqual(0, static_cast<int>(app.position.height));
|
||||
Assert::AreEqual(0u, static_cast<unsigned int>(app.monitor));
|
||||
}
|
||||
|
||||
TEST_METHOD(Application_Comparison_EqualObjects)
|
||||
{
|
||||
// Arrange
|
||||
WorkspacesData::WorkspacesProject::Application app1;
|
||||
app1.id = L"test-id";
|
||||
app1.name = L"Test App";
|
||||
app1.position.x = 100;
|
||||
app1.position.y = 200;
|
||||
|
||||
WorkspacesData::WorkspacesProject::Application app2;
|
||||
app2.id = L"test-id";
|
||||
app2.name = L"Test App";
|
||||
app2.position.x = 100;
|
||||
app2.position.y = 200;
|
||||
|
||||
// Act & Assert
|
||||
Assert::IsTrue(app1 == app2);
|
||||
}
|
||||
|
||||
TEST_METHOD(Application_Comparison_DifferentObjects)
|
||||
{
|
||||
// Arrange
|
||||
WorkspacesData::WorkspacesProject::Application app1;
|
||||
app1.id = L"test-id-1";
|
||||
app1.name = L"Test App 1";
|
||||
|
||||
WorkspacesData::WorkspacesProject::Application app2;
|
||||
app2.id = L"test-id-2";
|
||||
app2.name = L"Test App 2";
|
||||
|
||||
// Act & Assert
|
||||
Assert::IsTrue(app1 != app2);
|
||||
}
|
||||
|
||||
TEST_METHOD(Position_Comparison_EqualPositions)
|
||||
{
|
||||
// Arrange
|
||||
WorkspacesData::WorkspacesProject::Application::Position pos1;
|
||||
pos1.x = 100;
|
||||
pos1.y = 200;
|
||||
pos1.width = 800;
|
||||
pos1.height = 600;
|
||||
|
||||
WorkspacesData::WorkspacesProject::Application::Position pos2;
|
||||
pos2.x = 100;
|
||||
pos2.y = 200;
|
||||
pos2.width = 800;
|
||||
pos2.height = 600;
|
||||
|
||||
// Act & Assert
|
||||
Assert::IsTrue(pos1 == pos2);
|
||||
}
|
||||
|
||||
TEST_METHOD(Position_Comparison_DifferentPositions)
|
||||
{
|
||||
// Arrange
|
||||
WorkspacesData::WorkspacesProject::Application::Position pos1;
|
||||
pos1.x = 100;
|
||||
pos1.y = 200;
|
||||
pos1.width = 800;
|
||||
pos1.height = 600;
|
||||
|
||||
WorkspacesData::WorkspacesProject::Application::Position pos2;
|
||||
pos2.x = 150;
|
||||
pos2.y = 200;
|
||||
pos2.width = 800;
|
||||
pos2.height = 600;
|
||||
|
||||
// Act & Assert
|
||||
Assert::IsTrue(pos1 != pos2);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A85D4D9F-9A39-4B5D-8B5A-9F2D5C9A8B4C}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>WorkspacesLibUnitTests</RootNamespace>
|
||||
<ProjectName>WorkspacesLibUnitTests</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\tests\Workspaces\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\;..\WorkspacesLib\;$(SolutionDir)src\;$(SolutionDir)src\common;$(SolutionDir)src\common\Telemetry;..\..\;..\..\..\;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\\lib;$(SolutionDir)$(Platform)\\$(Configuration)\\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>propsys.lib;comctl32.lib;pathcch.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Pathcch.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WorkspacesDataTests.cpp" />
|
||||
<ClCompile Include="StringUtilsTests.cpp" />
|
||||
<ClCompile Include="JsonUtilsTests.cpp" />
|
||||
<ClCompile Include="AppUtilsTests.cpp" />
|
||||
<ClCompile Include="PwaHelperTests.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WorkspacesLib\WorkspacesLib.vcxproj">
|
||||
<Project>{b31fcc55-b5a4-4ea7-b414-2dceae6af332}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WorkspacesDataTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringUtilsTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonUtilsTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AppUtilsTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PwaHelperTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
</packages>
|
||||
1
src/modules/Workspaces/WorkspacesLib.UnitTests/pch.cpp
Normal file
1
src/modules/Workspaces/WorkspacesLib.UnitTests/pch.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
||||
21
src/modules/Workspaces/WorkspacesLib.UnitTests/pch.h
Normal file
21
src/modules/Workspaces/WorkspacesLib.UnitTests/pch.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
// Headers for CppUnitTest
|
||||
#pragma warning(disable : 26466)
|
||||
#include "CppUnitTest.h"
|
||||
|
||||
// Windows headers
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
// Workspaces headers
|
||||
#include <WorkspacesLib/WorkspacesData.h>
|
||||
#include <WorkspacesLib/JsonUtils.h>
|
||||
#include <WorkspacesLib/Result.h>
|
||||
#include <WorkspacesLib/AppUtils.h>
|
||||
#include <WorkspacesLib/PwaHelper.h>
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace StringUtils
|
||||
{
|
||||
bool CaseInsensitiveEquals(const std::wstring& str1, const std::wstring& str2)
|
||||
inline bool CaseInsensitiveEquals(const std::wstring& str1, const std::wstring& str2)
|
||||
{
|
||||
if (str1.size() != str2.size())
|
||||
{
|
||||
|
||||
@@ -69,10 +69,10 @@ namespace WorkspacesData
|
||||
|
||||
std::wstring id;
|
||||
std::wstring name;
|
||||
time_t creationTime;
|
||||
time_t creationTime{};
|
||||
std::optional<time_t> lastLaunchedTime;
|
||||
bool isShortcutNeeded;
|
||||
bool moveExistingWindows;
|
||||
bool isShortcutNeeded{};
|
||||
bool moveExistingWindows{};
|
||||
std::vector<Monitor> monitors;
|
||||
std::vector<Application> apps;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
|
||||
<PackageVersion Include="Shmuelie.WinRTServer" Version="2.1.1" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.6" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -56,13 +56,35 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
|
||||
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
|
||||
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
|
||||
<!-- Suppress DynamicallyAccessedMemberTypes.PublicParameterlessConstructor in fallback code path of Windows SDK projection -->
|
||||
<WarningsNotAsErrors>IL2081</WarningsNotAsErrors>
|
||||
<WarningsNotAsErrors>IL2081;$(WarningsNotAsErrors)</WarningsNotAsErrors>
|
||||
|
||||
<!-- When publishing trimmed, make sure to treat trimming warnings as build errors -->
|
||||
<ILLinkTreatWarningsAsErrors>true</ILLinkTreatWarningsAsErrors>
|
||||
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<!-- In Debug builds, trimming is disabled by default, but all the trim &
|
||||
AOT warnings are enabled. This gives debug builds a tighter inner loop,
|
||||
while at least warning about future trim violations -->
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
|
||||
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
|
||||
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
|
||||
<EnableAotAnalyzer>true</EnableAotAnalyzer>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'!='Debug'">
|
||||
<!-- In Release builds, trimming is enabled by default.
|
||||
feel free to disable this if needed -->
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
||||
Binary file not shown.
@@ -79,6 +79,9 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
|
||||
throw;
|
||||
}
|
||||
|
||||
var oneContent = newContent.Count == 1;
|
||||
newContent.ForEach(c => c.OnlyControlOnPage = oneContent);
|
||||
|
||||
// Now, back to a UI thread to update the observable collection
|
||||
DoOnUiThread(
|
||||
() =>
|
||||
|
||||
@@ -7,4 +7,5 @@ namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
public abstract partial class ContentViewModel(WeakReference<IPageContext> context) :
|
||||
ExtensionObjectViewModel(context)
|
||||
{
|
||||
public bool OnlyControlOnPage { get; internal set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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.CmdPal.UI.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class DetailsCommandsViewModel(
|
||||
IDetailsElement _detailsElement,
|
||||
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
|
||||
{
|
||||
public List<CommandViewModel> Commands { get; private set; } = [];
|
||||
|
||||
public bool HasCommands => Commands.Count > 0;
|
||||
|
||||
private readonly ExtensionObject<IDetailsCommands> _dataModel =
|
||||
new(_detailsElement.Data as IDetailsCommands);
|
||||
|
||||
public override void InitializeProperties()
|
||||
{
|
||||
base.InitializeProperties();
|
||||
var model = _dataModel.Unsafe;
|
||||
if (model == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Commands = model
|
||||
.Commands?
|
||||
.Select(c =>
|
||||
{
|
||||
var vm = new CommandViewModel(c, PageContext);
|
||||
vm.InitializeProperties();
|
||||
return vm;
|
||||
})
|
||||
.ToList() ?? [];
|
||||
UpdateProperty(nameof(HasCommands));
|
||||
UpdateProperty(nameof(Commands));
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ public partial class DetailsViewModel(IDetails _details, WeakReference<IPageCont
|
||||
{
|
||||
IDetailsSeparator => new DetailsSeparatorViewModel(element, this.PageContext),
|
||||
IDetailsLink => new DetailsLinkViewModel(element, this.PageContext),
|
||||
IDetailsCommands => new DetailsCommandsViewModel(element, this.PageContext),
|
||||
IDetailsTags => new DetailsTagsViewModel(element, this.PageContext),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ using Microsoft.CmdPal.Common.Services;
|
||||
using Microsoft.CmdPal.Ext.Apps;
|
||||
using Microsoft.CmdPal.Ext.Bookmarks;
|
||||
using Microsoft.CmdPal.Ext.Calc;
|
||||
using Microsoft.CmdPal.Ext.ClipboardHistory;
|
||||
using Microsoft.CmdPal.Ext.Indexer;
|
||||
using Microsoft.CmdPal.Ext.Registry;
|
||||
using Microsoft.CmdPal.Ext.Shell;
|
||||
@@ -19,6 +20,7 @@ using Microsoft.CmdPal.Ext.WindowsSettings;
|
||||
using Microsoft.CmdPal.Ext.WindowsTerminal;
|
||||
using Microsoft.CmdPal.Ext.WindowWalker;
|
||||
using Microsoft.CmdPal.Ext.WinGet;
|
||||
using Microsoft.CmdPal.UI.Helpers;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Models;
|
||||
@@ -100,8 +102,7 @@ public partial class App : Application
|
||||
services.AddSingleton<ICommandProvider, IndexerCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, BookmarksCommandProvider>();
|
||||
|
||||
// TODO GH #527 re-enable the clipboard commands
|
||||
// services.AddSingleton<ICommandProvider, ClipboardHistoryCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, ClipboardHistoryCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, WindowWalkerCommandsProvider>();
|
||||
services.AddSingleton<ICommandProvider, WebSearchCommandsProvider>();
|
||||
|
||||
@@ -140,6 +141,7 @@ public partial class App : Application
|
||||
var state = AppStateModel.LoadState();
|
||||
services.AddSingleton(state);
|
||||
services.AddSingleton<IExtensionService, ExtensionService>();
|
||||
services.AddSingleton<TrayIconService>();
|
||||
|
||||
// ViewModels
|
||||
services.AddSingleton<ShellViewModel>();
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
using AdaptiveCards.ObjectModel.WinUI3;
|
||||
using AdaptiveCards.Rendering.WinUI3;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Controls;
|
||||
|
||||
@@ -16,7 +18,7 @@ public sealed partial class ContentFormControl : UserControl
|
||||
|
||||
// LOAD-BEARING: if you don't hang onto a reference to the RenderedAdaptiveCard
|
||||
// then the GC might clean it up sometime, even while the card is in the UI
|
||||
// tree. If this gets GC'd, then it'll revoke our Action handler, and the
|
||||
// tree. If this gets GC'ed, then it'll revoke our Action handler, and the
|
||||
// form will do seemingly nothing.
|
||||
private RenderedAdaptiveCard? _renderedCard;
|
||||
|
||||
@@ -96,11 +98,65 @@ public sealed partial class ContentFormControl : UserControl
|
||||
if (_renderedCard.FrameworkElement != null)
|
||||
{
|
||||
ContentGrid.Children.Add(_renderedCard.FrameworkElement);
|
||||
|
||||
// Use the Loaded event to ensure we focus after the card is in the visual tree
|
||||
_renderedCard.FrameworkElement.Loaded += OnFrameworkElementLoaded;
|
||||
}
|
||||
|
||||
_renderedCard.Action += Rendered_Action;
|
||||
}
|
||||
|
||||
private void OnFrameworkElementLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Unhook the event handler to avoid multiple registrations
|
||||
if (sender is FrameworkElement element)
|
||||
{
|
||||
element.Loaded -= OnFrameworkElementLoaded;
|
||||
|
||||
if (!ViewModel?.OnlyControlOnPage ?? true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Focus on the first focusable element asynchronously to ensure the visual tree is fully built
|
||||
element.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
|
||||
{
|
||||
var focusableElement = FindFirstFocusableElement(element);
|
||||
focusableElement?.Focus(FocusState.Programmatic);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Control? FindFirstFocusableElement(DependencyObject parent)
|
||||
{
|
||||
var childCount = VisualTreeHelper.GetChildrenCount(parent);
|
||||
|
||||
// Process children first (depth-first search)
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
|
||||
// If the child is a focusable control like TextBox, ComboBox, etc.
|
||||
if (child is Control control &&
|
||||
control.IsEnabled &&
|
||||
control.IsTabStop &&
|
||||
control.Visibility == Visibility.Visible &&
|
||||
control.AllowFocusOnInteraction)
|
||||
{
|
||||
return control;
|
||||
}
|
||||
|
||||
// Recursively check children
|
||||
var result = FindFirstFocusableElement(child);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Rendered_Action(RenderedAdaptiveCard sender, AdaptiveActionEventArgs args) =>
|
||||
ViewModel?.HandleSubmit(args.Action, args.Inputs.AsJson());
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ public partial class DetailsDataTemplateSelector : DataTemplateSelector
|
||||
|
||||
public DataTemplate? TagTemplate { get; set; }
|
||||
|
||||
public DataTemplate? CommandTemplate { get; set; }
|
||||
|
||||
protected override DataTemplate? SelectTemplateCore(object item)
|
||||
{
|
||||
if (item is DetailsElementViewModel element)
|
||||
@@ -27,6 +29,7 @@ public partial class DetailsDataTemplateSelector : DataTemplateSelector
|
||||
{
|
||||
DetailsSeparatorViewModel => SeparatorTemplate,
|
||||
DetailsLinkViewModel => LinkTemplate,
|
||||
DetailsCommandsViewModel => CommandTemplate,
|
||||
DetailsTagsViewModel => TagTemplate,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
// 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.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.CmdPal.UI.ViewModels;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Messages;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.Shell;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using WinRT.Interop;
|
||||
using RS_ = Microsoft.CmdPal.UI.Helpers.ResourceLoaderInstance;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.Helpers;
|
||||
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Stylistically, window messages are WM_*")]
|
||||
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Stylistically, window messages are WM_*")]
|
||||
internal sealed partial class TrayIconService
|
||||
{
|
||||
private const uint MY_NOTIFY_ID = 1000;
|
||||
private const uint WM_TRAY_ICON = PInvoke.WM_USER + 1;
|
||||
|
||||
private readonly SettingsModel _settingsModel;
|
||||
private readonly uint WM_TASKBAR_RESTART;
|
||||
|
||||
private Window? _window;
|
||||
private HWND _hwnd;
|
||||
private WNDPROC? _originalWndProc;
|
||||
private WNDPROC? _trayWndProc;
|
||||
private NOTIFYICONDATAW? _trayIconData;
|
||||
private DestroyIconSafeHandle? _largeIcon;
|
||||
private DestroyMenuSafeHandle? _popupMenu;
|
||||
|
||||
public TrayIconService(SettingsModel settingsModel)
|
||||
{
|
||||
_settingsModel = settingsModel;
|
||||
|
||||
// TaskbarCreated is the message that's broadcast when explorer.exe
|
||||
// restarts. We need to know when that happens to be able to bring our
|
||||
// notification area icon back
|
||||
WM_TASKBAR_RESTART = PInvoke.RegisterWindowMessage("TaskbarCreated");
|
||||
}
|
||||
|
||||
public void SetupTrayIcon(bool? showSystemTrayIcon = null)
|
||||
{
|
||||
if (showSystemTrayIcon ?? _settingsModel.ShowSystemTrayIcon)
|
||||
{
|
||||
if (_window == null)
|
||||
{
|
||||
_window = new Window();
|
||||
_hwnd = new HWND(WindowNative.GetWindowHandle(_window));
|
||||
|
||||
// LOAD BEARING: If you don't stick the pointer to HotKeyPrc into a
|
||||
// member (and instead like, use a local), then the pointer we marshal
|
||||
// into the WindowLongPtr will be useless after we leave this function,
|
||||
// and our **WindProc will explode**.
|
||||
_trayWndProc = WindowProc;
|
||||
var hotKeyPrcPointer = Marshal.GetFunctionPointerForDelegate(_trayWndProc);
|
||||
_originalWndProc = Marshal.GetDelegateForFunctionPointer<WNDPROC>(PInvoke.SetWindowLongPtr(_hwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, hotKeyPrcPointer));
|
||||
}
|
||||
|
||||
if (_trayIconData == null)
|
||||
{
|
||||
// We need to stash this handle, so it doesn't clean itself up. If
|
||||
// explorer restarts, we'll come back through here, and we don't
|
||||
// really need to re-load the icon in that case. We can just use
|
||||
// the handle from the first time.
|
||||
_largeIcon = GetAppIconHandle();
|
||||
_trayIconData = new NOTIFYICONDATAW()
|
||||
{
|
||||
cbSize = (uint)Marshal.SizeOf(typeof(NOTIFYICONDATAW)),
|
||||
hWnd = _hwnd,
|
||||
uID = MY_NOTIFY_ID,
|
||||
uFlags = NOTIFY_ICON_DATA_FLAGS.NIF_MESSAGE | NOTIFY_ICON_DATA_FLAGS.NIF_ICON | NOTIFY_ICON_DATA_FLAGS.NIF_TIP,
|
||||
uCallbackMessage = WM_TRAY_ICON,
|
||||
hIcon = (HICON)_largeIcon.DangerousGetHandle(),
|
||||
szTip = RS_.GetString("AppStoreName"),
|
||||
};
|
||||
}
|
||||
|
||||
var d = (NOTIFYICONDATAW)_trayIconData;
|
||||
|
||||
// Add the notification icon
|
||||
PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_ADD, in d);
|
||||
|
||||
if (_popupMenu == null)
|
||||
{
|
||||
_popupMenu = PInvoke.CreatePopupMenu_SafeHandle();
|
||||
PInvoke.InsertMenu(_popupMenu, 0, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING, PInvoke.WM_USER + 1, RS_.GetString("TrayMenu_Settings"));
|
||||
PInvoke.InsertMenu(_popupMenu, 1, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING, PInvoke.WM_USER + 2, RS_.GetString("TrayMenu_Exit"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
if (_trayIconData != null)
|
||||
{
|
||||
var d = (NOTIFYICONDATAW)_trayIconData;
|
||||
if (PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_DELETE, in d))
|
||||
{
|
||||
_trayIconData = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (_popupMenu != null)
|
||||
{
|
||||
_popupMenu.Close();
|
||||
_popupMenu = null;
|
||||
}
|
||||
|
||||
if (_largeIcon != null)
|
||||
{
|
||||
_largeIcon.Close();
|
||||
_largeIcon = null;
|
||||
}
|
||||
|
||||
if (_window != null)
|
||||
{
|
||||
_window.Close();
|
||||
_window = null;
|
||||
_hwnd = HWND.Null;
|
||||
}
|
||||
}
|
||||
|
||||
private DestroyIconSafeHandle GetAppIconHandle()
|
||||
{
|
||||
var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
||||
DestroyIconSafeHandle largeIcon;
|
||||
PInvoke.ExtractIconEx(exePath, 0, out largeIcon, out _, 1);
|
||||
return largeIcon;
|
||||
}
|
||||
|
||||
private LRESULT WindowProc(
|
||||
HWND hwnd,
|
||||
uint uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case PInvoke.WM_COMMAND:
|
||||
{
|
||||
if (wParam == PInvoke.WM_USER + 1)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<OpenSettingsMessage>();
|
||||
}
|
||||
else if (wParam == PInvoke.WM_USER + 2)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<QuitMessage>();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Shell_NotifyIcon can fail when we invoke it during the time explorer.exe isn't present/ready to handle it.
|
||||
// We'll also never receive WM_TASKBAR_RESTART message if the first call to Shell_NotifyIcon failed, so we use
|
||||
// WM_WINDOWPOSCHANGING which is always received on explorer startup sequence.
|
||||
case PInvoke.WM_WINDOWPOSCHANGING:
|
||||
{
|
||||
if (_trayIconData == null)
|
||||
{
|
||||
SetupTrayIcon();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// WM_TASKBAR_RESTART isn't a compile-time constant, so we can't
|
||||
// use it in a case label
|
||||
if (uMsg == WM_TASKBAR_RESTART)
|
||||
{
|
||||
// Handle the case where explorer.exe restarts.
|
||||
// Even if we created it before, do it again
|
||||
SetupTrayIcon();
|
||||
}
|
||||
else if (uMsg == WM_TRAY_ICON)
|
||||
{
|
||||
switch ((uint)lParam.Value)
|
||||
{
|
||||
case PInvoke.WM_RBUTTONUP:
|
||||
{
|
||||
if (_popupMenu != null)
|
||||
{
|
||||
PInvoke.GetCursorPos(out var cursorPos);
|
||||
PInvoke.SetForegroundWindow(_hwnd);
|
||||
PInvoke.TrackPopupMenuEx(_popupMenu, (uint)TRACK_POPUP_MENU_FLAGS.TPM_LEFTALIGN | (uint)TRACK_POPUP_MENU_FLAGS.TPM_BOTTOMALIGN, cursorPos.X, cursorPos.Y, _hwnd, null);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case PInvoke.WM_LBUTTONUP:
|
||||
case PInvoke.WM_LBUTTONDBLCLK:
|
||||
WeakReferenceMessenger.Default.Send<HotkeySummonMessage>(new(string.Empty, HWND.Null));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return PInvoke.CallWindowProc(_originalWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Dwm;
|
||||
using Windows.Win32.UI.Input.KeyboardAndMouse;
|
||||
using Windows.Win32.UI.Shell;
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
using WinRT;
|
||||
using WinUIEx;
|
||||
@@ -47,22 +46,8 @@ public sealed partial class MainWindow : WindowEx,
|
||||
private readonly WNDPROC? _hotkeyWndProc;
|
||||
private readonly WNDPROC? _originalWndProc;
|
||||
private readonly List<TopLevelHotkey> _hotkeys = [];
|
||||
private bool _ignoreHotKeyWhenFullScreen = true;
|
||||
|
||||
// Stylistically, window messages are WM_*
|
||||
#pragma warning disable SA1310 // Field names should not contain underscore
|
||||
#pragma warning disable SA1306 // Field names should begin with lower-case letter
|
||||
private const uint MY_NOTIFY_ID = 1000;
|
||||
private const uint WM_TRAY_ICON = PInvoke.WM_USER + 1;
|
||||
private readonly uint WM_TASKBAR_RESTART;
|
||||
#pragma warning restore SA1306 // Field names should begin with lower-case letter
|
||||
#pragma warning restore SA1310 // Field names should not contain underscore
|
||||
|
||||
private readonly KeyboardListener _keyboardListener;
|
||||
|
||||
// Notification Area ("Tray") icon data
|
||||
private NOTIFYICONDATAW? _trayIconData;
|
||||
private DestroyIconSafeHandle? _largeIcon;
|
||||
private bool _ignoreHotKeyWhenFullScreen = true;
|
||||
|
||||
private DesktopAcrylicController? _acrylicController;
|
||||
private SystemBackdropConfiguration? _configurationSource;
|
||||
@@ -79,11 +64,6 @@ public sealed partial class MainWindow : WindowEx,
|
||||
|
||||
_keyboardListener.SetProcessCommand(new CmdPalKeyboardService.ProcessCommand(HandleSummon));
|
||||
|
||||
// TaskbarCreated is the message that's broadcast when explorer.exe
|
||||
// restarts. We need to know when that happens to be able to bring our
|
||||
// notification area icon back
|
||||
WM_TASKBAR_RESTART = PInvoke.RegisterWindowMessage("TaskbarCreated");
|
||||
|
||||
this.SetIcon();
|
||||
AppWindow.Title = RS_.GetString("AppName");
|
||||
PositionCentered();
|
||||
@@ -159,7 +139,7 @@ public sealed partial class MainWindow : WindowEx,
|
||||
var settings = App.Current.Services.GetService<SettingsModel>()!;
|
||||
|
||||
SetupHotkey(settings);
|
||||
SetupTrayIcon(settings.ShowSystemTrayIcon);
|
||||
App.Current.Services.GetService<TrayIconService>()!.SetupTrayIcon(settings.ShowSystemTrayIcon);
|
||||
|
||||
_ignoreHotKeyWhenFullScreen = settings.IgnoreShortcutWhenFullscreen;
|
||||
|
||||
@@ -219,7 +199,7 @@ public sealed partial class MainWindow : WindowEx,
|
||||
|
||||
private void ShowHwnd(IntPtr hwndValue, MonitorBehavior target)
|
||||
{
|
||||
var hwnd = new HWND(hwndValue);
|
||||
var hwnd = new HWND(hwndValue != 0 ? hwndValue : _hwnd);
|
||||
|
||||
// Remember, IsIconic == "minimized", which is entirely different state
|
||||
// from "show/hide"
|
||||
@@ -332,7 +312,7 @@ public sealed partial class MainWindow : WindowEx,
|
||||
var extensionService = serviceProvider.GetService<IExtensionService>()!;
|
||||
extensionService.SignalStopExtensionsAsync();
|
||||
|
||||
RemoveTrayIcon();
|
||||
App.Current.Services.GetService<TrayIconService>()!.Destroy();
|
||||
|
||||
// WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592).
|
||||
// Workaround by turning it off before shutdown.
|
||||
@@ -340,6 +320,7 @@ public sealed partial class MainWindow : WindowEx,
|
||||
DisposeAcrylic();
|
||||
|
||||
_keyboardListener.Stop();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void DisposeAcrylic()
|
||||
@@ -515,18 +496,27 @@ public sealed partial class MainWindow : WindowEx,
|
||||
|
||||
if (key != null)
|
||||
{
|
||||
var vk = key.Code;
|
||||
var modifiers =
|
||||
(key.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
|
||||
(key.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
|
||||
(key.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
|
||||
(key.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
|
||||
;
|
||||
|
||||
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
|
||||
if (success)
|
||||
if (settings.UseLowLevelGlobalHotkey)
|
||||
{
|
||||
_hotkeys.Add(commandHotkey);
|
||||
_keyboardListener.SetHotkeyAction(key.Win, key.Ctrl, key.Shift, key.Alt, (byte)key.Code, commandHotkey.CommandId);
|
||||
|
||||
_hotkeys.Add(new(globalHotkey, string.Empty));
|
||||
}
|
||||
else
|
||||
{
|
||||
var vk = key.Code;
|
||||
var modifiers =
|
||||
(key.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
|
||||
(key.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
|
||||
(key.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
|
||||
(key.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
|
||||
;
|
||||
|
||||
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
|
||||
if (success)
|
||||
{
|
||||
_hotkeys.Add(commandHotkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -606,100 +596,8 @@ public sealed partial class MainWindow : WindowEx,
|
||||
|
||||
return (LRESULT)IntPtr.Zero;
|
||||
}
|
||||
|
||||
// Shell_NotifyIcon can fail when we invoke it during the time explorer.exe isn't present/ready to handle it.
|
||||
// We'll also never receive WM_TASKBAR_RESTART message if the first call to Shell_NotifyIcon failed, so we use
|
||||
// WM_WINDOWPOSCHANGING which is always received on explorer startup sequence.
|
||||
case PInvoke.WM_WINDOWPOSCHANGING:
|
||||
{
|
||||
if (_trayIconData == null)
|
||||
{
|
||||
SetupTrayIcon();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// WM_TASKBAR_RESTART isn't a compile-time constant, so we can't
|
||||
// use it in a case label
|
||||
if (uMsg == WM_TASKBAR_RESTART)
|
||||
{
|
||||
// Handle the case where explorer.exe restarts.
|
||||
// Even if we created it before, do it again
|
||||
SetupTrayIcon();
|
||||
}
|
||||
else if (uMsg == WM_TRAY_ICON)
|
||||
{
|
||||
switch ((uint)lParam.Value)
|
||||
{
|
||||
case PInvoke.WM_RBUTTONUP:
|
||||
case PInvoke.WM_LBUTTONUP:
|
||||
case PInvoke.WM_LBUTTONDBLCLK:
|
||||
Summon(string.Empty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return PInvoke.CallWindowProc(_originalWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
private void SetupTrayIcon(bool? showSystemTrayIcon = null)
|
||||
{
|
||||
if (showSystemTrayIcon ?? App.Current.Services.GetService<SettingsModel>()!.ShowSystemTrayIcon)
|
||||
{
|
||||
// We only need to build the tray data once.
|
||||
if (_trayIconData == null)
|
||||
{
|
||||
// We need to stash this handle, so it doesn't clean itself up. If
|
||||
// explorer restarts, we'll come back through here, and we don't
|
||||
// really need to re-load the icon in that case. We can just use
|
||||
// the handle from the first time.
|
||||
_largeIcon = GetAppIconHandle();
|
||||
_trayIconData = new NOTIFYICONDATAW()
|
||||
{
|
||||
cbSize = (uint)Marshal.SizeOf(typeof(NOTIFYICONDATAW)),
|
||||
hWnd = _hwnd,
|
||||
uID = MY_NOTIFY_ID,
|
||||
uFlags = NOTIFY_ICON_DATA_FLAGS.NIF_MESSAGE | NOTIFY_ICON_DATA_FLAGS.NIF_ICON | NOTIFY_ICON_DATA_FLAGS.NIF_TIP,
|
||||
uCallbackMessage = WM_TRAY_ICON,
|
||||
hIcon = (HICON)_largeIcon.DangerousGetHandle(),
|
||||
szTip = RS_.GetString("AppStoreName"),
|
||||
};
|
||||
}
|
||||
|
||||
var d = (NOTIFYICONDATAW)_trayIconData;
|
||||
|
||||
// Add the notification icon
|
||||
PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_ADD, in d);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveTrayIcon();
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveTrayIcon()
|
||||
{
|
||||
if (_trayIconData != null)
|
||||
{
|
||||
var d = (NOTIFYICONDATAW)_trayIconData;
|
||||
if (PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_DELETE, in d))
|
||||
{
|
||||
_trayIconData = null;
|
||||
}
|
||||
}
|
||||
|
||||
_largeIcon?.Close();
|
||||
}
|
||||
|
||||
private DestroyIconSafeHandle GetAppIconHandle()
|
||||
{
|
||||
var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
||||
DestroyIconSafeHandle largeIcon;
|
||||
PInvoke.ExtractIconEx(exePath, 0, out largeIcon, out _, 1);
|
||||
return largeIcon;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,14 @@ WM_WINDOWPOSCHANGING
|
||||
RegisterWindowMessageW
|
||||
GetModuleHandleW
|
||||
ExtractIconEx
|
||||
TRACK_POPUP_MENU_FLAGS
|
||||
WM_COMMAND
|
||||
WM_RBUTTONUP
|
||||
WM_LBUTTONUP
|
||||
WM_LBUTTONDBLCLK
|
||||
CreatePopupMenu
|
||||
TrackPopupMenuEx
|
||||
InsertMenu
|
||||
|
||||
MessageBox
|
||||
DwmGetWindowAttribute
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
<cmdpalUI:DetailsDataTemplateSelector
|
||||
x:Key="DetailsDataTemplateSelector"
|
||||
CommandTemplate="{StaticResource DetailsCommandsTemplate}"
|
||||
LinkTemplate="{StaticResource DetailsLinkTemplate}"
|
||||
SeparatorTemplate="{StaticResource DetailsSeparatorTemplate}"
|
||||
TagTemplate="{StaticResource DetailsTagsTemplate}" />
|
||||
@@ -50,6 +51,27 @@
|
||||
ToolTipService.ToolTip="{x:Bind ToolTip, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="CommandTemplate" x:DataType="viewModels:CommandViewModel">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Button
|
||||
Name="Command"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Left"
|
||||
Click="Command_Click"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
|
||||
<cpcontrols:IconBox
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="0,3,8,0"
|
||||
SourceKey="{x:Bind Icon, Mode=OneWay}"
|
||||
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}" />
|
||||
<TextBlock Text="{x:Bind Name}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="DetailsLinkTemplate" x:DataType="viewModels:DetailsLinkViewModel">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock
|
||||
@@ -71,6 +93,18 @@
|
||||
Visibility="{x:Bind IsLink, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="DetailsCommandsTemplate" x:DataType="viewModels:DetailsCommandsViewModel">
|
||||
<StackPanel Orientation="Vertical" Spacing="4">
|
||||
<TextBlock
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind Key, Mode=OneWay}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<ItemsControl
|
||||
ItemTemplate="{StaticResource CommandTemplate}"
|
||||
ItemsSource="{x:Bind Commands, Mode=OneWay}"
|
||||
Visibility="{x:Bind HasCommands, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="DetailsSeparatorTemplate" x:DataType="viewModels:DetailsSeparatorViewModel">
|
||||
<StackPanel Margin="0,8,8,0" Orientation="Vertical">
|
||||
<Border
|
||||
|
||||
@@ -629,4 +629,12 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
|
||||
return iconInfoVM?.HasIcon(requestedTheme == Microsoft.UI.Xaml.ElementTheme.Light) ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Command_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button && button.DataContext is CommandViewModel commandViewModel)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(commandViewModel.Model));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,4 +412,10 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<data name="MoreCommandsButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>More</value>
|
||||
</data>
|
||||
<data name="TrayMenu_Settings" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="TrayMenu_Exit" xml:space="preserve">
|
||||
<value>Exit</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -39,8 +39,8 @@ Projects of interest are:
|
||||
|
||||
|
||||
[Initial SDK Spec]: ./doc/initial-sdk-spec/initial-sdk-spec.md
|
||||
[generic samples]: ./Exts/SamplePagesExtension
|
||||
[real samples]: ./Exts/ProcessMonitorExtension
|
||||
[generic samples]: ./ext/SamplePagesExtension
|
||||
[real samples]: ./ext/ProcessMonitorExtension
|
||||
[real extensions that we've "shipped" already]: https://github.com/zadjii/CmdPalExtensions/blob/main/src/extensions
|
||||
|
||||
|
||||
|
||||
@@ -6,20 +6,20 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Mages.Core;
|
||||
using CalculatorEngineCommon;
|
||||
using Windows.Foundation.Collections;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Calc.Helper;
|
||||
|
||||
public static class CalculateEngine
|
||||
{
|
||||
private static readonly Engine _magesEngine = new Engine(new Configuration
|
||||
private static readonly PropertySet _constants = new()
|
||||
{
|
||||
Scope = new Dictionary<string, object>
|
||||
{
|
||||
{ "e", Math.E }, // e is not contained in the default mages engine
|
||||
},
|
||||
});
|
||||
{ "pi", Math.PI },
|
||||
{ "e", Math.E },
|
||||
};
|
||||
|
||||
private static readonly Calculator _calculator = new Calculator(_constants);
|
||||
|
||||
public const int RoundingDigits = 10;
|
||||
|
||||
@@ -68,28 +68,26 @@ public static class CalculateEngine
|
||||
// Expand conversions between trig units
|
||||
input = CalculateHelper.ExpandTrigConversions(input, trigMode);
|
||||
|
||||
var result = _magesEngine.Interpret(input);
|
||||
var result = _calculator.EvaluateExpression(input);
|
||||
|
||||
// This could happen for some incorrect queries, like pi(2)
|
||||
if (result == null)
|
||||
if (result == "NaN")
|
||||
{
|
||||
error = Properties.Resources.calculator_expression_not_complete;
|
||||
return default;
|
||||
}
|
||||
|
||||
result = TransformResult(result);
|
||||
if (result is string)
|
||||
{
|
||||
error = result as string;
|
||||
return default;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(result?.ToString()))
|
||||
if (string.IsNullOrEmpty(result))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var decimalResult = Convert.ToDecimal(result, cultureInfo);
|
||||
|
||||
// Remove trailing zeros from the decimal string representation (e.g., "1.2300" -> "1.23")
|
||||
// This is necessary because the value extracted from exprtk may contain unnecessary trailing zeros.
|
||||
var formatted = decimalResult.ToString("G29", cultureInfo);
|
||||
decimalResult = Convert.ToDecimal(formatted, cultureInfo);
|
||||
var roundedResult = Round(decimalResult);
|
||||
|
||||
return new CalculateResult()
|
||||
@@ -103,25 +101,4 @@ public static class CalculateEngine
|
||||
{
|
||||
return Math.Round(value, RoundingDigits, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
private static dynamic TransformResult(object result)
|
||||
{
|
||||
if (result.ToString() == "NaN")
|
||||
{
|
||||
return Properties.Resources.calculator_not_a_number;
|
||||
}
|
||||
|
||||
if (result is Function)
|
||||
{
|
||||
return Properties.Resources.calculator_expression_not_complete;
|
||||
}
|
||||
|
||||
if (result is double[,])
|
||||
{
|
||||
// '[10,10]' is interpreted as array by mages engine
|
||||
return Properties.Resources.calculator_double_array_returned;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -63,46 +64,61 @@ public class NumberTranslator
|
||||
return Translate(input, targetCulture, sourceCulture, splitRegexForTarget);
|
||||
}
|
||||
|
||||
private static string ConvertBaseLiteral(string token, CultureInfo cultureTo)
|
||||
{
|
||||
var prefixes = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "0x", 16 },
|
||||
{ "0b", 2 },
|
||||
{ "0o", 8 },
|
||||
};
|
||||
|
||||
foreach (var (prefix, numberBase) in prefixes)
|
||||
{
|
||||
if (token.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
try
|
||||
{
|
||||
var num = Convert.ToInt64(token.Substring(prefix.Length), numberBase);
|
||||
return num.ToString(cultureTo);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null; // fallback
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string Translate(string input, CultureInfo cultureFrom, CultureInfo cultureTo, Regex splitRegex)
|
||||
{
|
||||
var outputBuilder = new StringBuilder();
|
||||
var hexRegex = new Regex(@"(?:(0x[\da-fA-F]+))");
|
||||
|
||||
var hexTokens = hexRegex.Split(input);
|
||||
// Match numbers in hexadecimal (0x..), binary (0b..), or octal (0o..) format,
|
||||
// and convert them to decimal form for compatibility with ExprTk (which only supports decimal input).
|
||||
var baseNumberRegex = new Regex(@"(0[xX][\da-fA-F]+|0[bB][0-9]+|0[oO][0-9]+)");
|
||||
|
||||
foreach (var hexToken in hexTokens)
|
||||
var tokens = baseNumberRegex.Split(input);
|
||||
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
if (hexToken.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
// Mages engine has issues processing large hex number (larger than 7 hex digits + 0x prefix = 9 characters). So we convert it to decimal and pass it to the engine.
|
||||
if (hexToken.Length > 9)
|
||||
{
|
||||
try
|
||||
{
|
||||
var num = Convert.ToInt64(hexToken, 16);
|
||||
var numStr = num.ToString(cultureFrom);
|
||||
outputBuilder.Append(numStr);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
outputBuilder.Append(hexToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.Append(hexToken);
|
||||
}
|
||||
// Currently, we only convert base literals (hexadecimal, binary, octal) to decimal.
|
||||
var converted = ConvertBaseLiteral(token, cultureTo);
|
||||
|
||||
if (converted != null)
|
||||
{
|
||||
outputBuilder.Append(converted);
|
||||
continue;
|
||||
}
|
||||
|
||||
var tokens = splitRegex.Split(hexToken);
|
||||
foreach (var token in tokens)
|
||||
foreach (var inner in splitRegex.Split(token))
|
||||
{
|
||||
var leadingZeroCount = 0;
|
||||
|
||||
// Count leading zero characters.
|
||||
foreach (var c in token)
|
||||
foreach (var c in inner)
|
||||
{
|
||||
if (c != '0')
|
||||
{
|
||||
@@ -113,7 +129,7 @@ public class NumberTranslator
|
||||
}
|
||||
|
||||
// number is all zero characters. no need to add zero characters at the end.
|
||||
if (token.Length == leadingZeroCount)
|
||||
if (inner.Length == leadingZeroCount)
|
||||
{
|
||||
leadingZeroCount = 0;
|
||||
}
|
||||
@@ -121,9 +137,9 @@ public class NumberTranslator
|
||||
decimal number;
|
||||
|
||||
outputBuilder.Append(
|
||||
decimal.TryParse(token, NumberStyles.Number, cultureFrom, out number)
|
||||
decimal.TryParse(inner, NumberStyles.Number, cultureFrom, out number)
|
||||
? (new string('0', leadingZeroCount) + number.ToString(cultureTo))
|
||||
: token.Replace(cultureFrom.TextInfo.ListSeparator, cultureTo.TextInfo.ListSeparator));
|
||||
: inner.Replace(cultureFrom.TextInfo.ListSeparator, cultureTo.TextInfo.ListSeparator));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,11 +65,6 @@ public static partial class QueryHelper
|
||||
|
||||
return ResultHelper.CreateResult(result.RoundedResult, inputCulture, outputCulture, query, handleSave);
|
||||
}
|
||||
catch (Mages.Core.ParseException)
|
||||
{
|
||||
// Invalid input
|
||||
return ErrorHandler.OnError(isFallbackSearch, query, Properties.Resources.calculator_expression_not_complete);
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
// Result to big to convert to decimal
|
||||
|
||||
@@ -9,15 +9,25 @@
|
||||
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
|
||||
<ProjectPriFileName>Microsoft.CmdPal.Ext.Calc.pri</ProjectPriFileName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>CalculatorEngineCommon</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\common\CalculatorEngineCommon\CalculatorEngineCommon.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mages" />
|
||||
<CsWinRTInputs Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.winmd" />
|
||||
<Content Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.winmd" Link="CalculatorEngineCommon.winmd">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
|
||||
@@ -30,6 +30,8 @@ internal static class ClipboardHelper
|
||||
(StandardDataFormats.Bitmap, ClipboardFormat.Image),
|
||||
];
|
||||
|
||||
private static readonly ClipboardThreadQueue ClipboardThreadQueue = new ClipboardThreadQueue();
|
||||
|
||||
internal static async Task<ClipboardFormat> GetAvailableClipboardFormatsAsync(DataPackageView clipboardData)
|
||||
{
|
||||
var availableClipboardFormats = DataFormats.Aggregate(
|
||||
@@ -58,9 +60,12 @@ internal static class ClipboardHelper
|
||||
try
|
||||
{
|
||||
// Clipboard.SetContentWithOptions(output, null);
|
||||
Clipboard.SetContent(output);
|
||||
Flush();
|
||||
ExtensionHost.LogMessage(new LogMessage() { Message = "Copied text to clipboard" });
|
||||
ClipboardThreadQueue.EnqueueTask(() =>
|
||||
{
|
||||
Clipboard.SetContent(output);
|
||||
Flush();
|
||||
ExtensionHost.LogMessage(new LogMessage() { Message = "Copied text to clipboard" });
|
||||
});
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
@@ -74,27 +79,32 @@ internal static class ClipboardHelper
|
||||
// TODO(stefan): For some reason Flush() fails from time to time when directly activated via hotkey.
|
||||
// Calling inside a loop makes it work.
|
||||
// Exception is: The operation is not permitted because the calling application is not the owner of the data on the clipboard.
|
||||
const int maxAttempts = 5;
|
||||
for (var i = 1; i <= maxAttempts; i++)
|
||||
ClipboardThreadQueue.EnqueueTask(() =>
|
||||
{
|
||||
try
|
||||
const int maxAttempts = 5;
|
||||
|
||||
for (var i = 1; i <= maxAttempts; i++)
|
||||
{
|
||||
Task.Run(Clipboard.Flush).Wait();
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (i == maxAttempts)
|
||||
try
|
||||
{
|
||||
ExtensionHost.LogMessage(new LogMessage()
|
||||
Task.Run(Clipboard.Flush).Wait();
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (i == maxAttempts)
|
||||
{
|
||||
Message = $"{nameof(Clipboard)}.{nameof(Flush)}() failed: {ex}",
|
||||
});
|
||||
ExtensionHost.LogMessage(new LogMessage()
|
||||
{
|
||||
Message = $"{nameof(Clipboard)}.{nameof(Flush)}() failed: {ex}",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
// We cannot get the real result of the Flush() call here, as it is executed in a different thread.
|
||||
return true;
|
||||
}
|
||||
|
||||
private static async Task<bool> FlushAsync() => await Task.Run(Flush);
|
||||
@@ -105,7 +115,7 @@ internal static class ClipboardHelper
|
||||
|
||||
DataPackage output = new();
|
||||
output.SetStorageItems([storageFile]);
|
||||
Clipboard.SetContent(output);
|
||||
ClipboardThreadQueue.EnqueueTask(() => Clipboard.SetContent(output));
|
||||
|
||||
await FlushAsync();
|
||||
}
|
||||
@@ -118,7 +128,7 @@ internal static class ClipboardHelper
|
||||
{
|
||||
DataPackage output = new();
|
||||
output.SetBitmap(image);
|
||||
Clipboard.SetContentWithOptions(output, null);
|
||||
ClipboardThreadQueue.EnqueueTask(() => Clipboard.SetContentWithOptions(output, null));
|
||||
|
||||
Flush();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.ClipboardHistory.Helpers;
|
||||
|
||||
public partial class ClipboardThreadQueue : IDisposable
|
||||
{
|
||||
private readonly Thread _thread;
|
||||
private readonly ConcurrentQueue<Action> _taskQueue = new ConcurrentQueue<Action>();
|
||||
private readonly AutoResetEvent _taskAvailable = new AutoResetEvent(false);
|
||||
private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource();
|
||||
|
||||
public ClipboardThreadQueue()
|
||||
{
|
||||
_thread = new Thread(() =>
|
||||
{
|
||||
var hr = NativeMethods.CoInitialize(IntPtr.Zero);
|
||||
if (hr != 0)
|
||||
{
|
||||
ExtensionHost.LogMessage($"CoInitialize failed with HRESULT: {hr}");
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
_taskAvailable.WaitOne();
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
while (_taskQueue.TryDequeue(out var task))
|
||||
{
|
||||
try
|
||||
{
|
||||
task();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExtensionHost.LogMessage($"Error executing task in ClipboardThreadQueue: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NativeMethods.CoUninitialize();
|
||||
});
|
||||
|
||||
_thread.SetApartmentState(ApartmentState.STA);
|
||||
_thread.IsBackground = true;
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
public void EnqueueTask(Action task)
|
||||
{
|
||||
_taskQueue.Enqueue(task);
|
||||
_taskAvailable.Set();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
cancellationToken.Cancel();
|
||||
_taskAvailable.Set();
|
||||
_thread.Join(); // Wait for the thread to finish processing tasks
|
||||
|
||||
_taskAvailable.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using Windows.Foundation;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.ClipboardHistory.Helpers;
|
||||
|
||||
internal static class NativeMethods
|
||||
public static partial class NativeMethods
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
|
||||
@@ -98,4 +98,10 @@ internal static class NativeMethods
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern bool GetCursorPos(out PointInter lpPoint);
|
||||
|
||||
[LibraryImport("ole32.dll")]
|
||||
internal static partial int CoInitialize(IntPtr pvReserved);
|
||||
|
||||
[LibraryImport("ole32.dll")]
|
||||
internal static partial void CoUninitialize();
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ namespace Microsoft.CmdPal.Ext.Shell;
|
||||
internal sealed partial class FallbackExecuteItem : FallbackCommandItem
|
||||
{
|
||||
private readonly ExecuteItem _executeItem;
|
||||
private readonly SettingsManager _settings;
|
||||
|
||||
public FallbackExecuteItem(SettingsManager settings)
|
||||
: base(new ExecuteItem(string.Empty, settings), Resources.shell_command_display_title)
|
||||
{
|
||||
_settings = settings;
|
||||
_executeItem = (ExecuteItem)this.Command!;
|
||||
Title = string.Empty;
|
||||
_executeItem.Name = string.Empty;
|
||||
@@ -28,5 +30,9 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem
|
||||
_executeItem.Cmd = query;
|
||||
_executeItem.Name = string.IsNullOrEmpty(query) ? string.Empty : Properties.Resources.generic_run_command;
|
||||
Title = query;
|
||||
MoreCommands = [
|
||||
new CommandContextItem(new ExecuteItem(query, _settings, RunAsType.Administrator)),
|
||||
new CommandContextItem(new ExecuteItem(query, _settings, RunAsType.OtherUser)),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,57 +31,81 @@ internal sealed partial class WindowsSettingsListPage : DynamicListPage
|
||||
}
|
||||
|
||||
var filteredList = _windowsSettings.Settings
|
||||
.Where(Predicate)
|
||||
.OrderBy(found => found.Name);
|
||||
.Select(SearchScoringPredicate)
|
||||
.Where(scoredSetting => scoredSetting.Score > 0)
|
||||
.OrderByDescending(scoredSetting => scoredSetting.Score)
|
||||
.Select(scoredSetting => scoredSetting.Setting);
|
||||
|
||||
var newList = ResultHelper.GetResultList(filteredList, query);
|
||||
return newList;
|
||||
|
||||
bool Predicate(WindowsSetting found)
|
||||
// Rank settings by how they matched the search query. Order is:
|
||||
// 1. Exact Name (10 points)
|
||||
// 2. Name Starts With (8 points)
|
||||
// 3. Name (5 points)
|
||||
// 4. Area (4 points)
|
||||
// 5. AltName (2 points)
|
||||
// 6. Settings path (1 point)
|
||||
(WindowsSetting Setting, int Score) SearchScoringPredicate(WindowsSetting setting)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
// If no search string is entered skip query comparison.
|
||||
return true;
|
||||
return (setting, 0);
|
||||
}
|
||||
|
||||
if (found.Name.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
if (string.Equals(setting.Name, query, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
return (setting, 10);
|
||||
}
|
||||
|
||||
if (!(found.Areas is null))
|
||||
if (setting.Name.StartsWith(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
foreach (var area in found.Areas)
|
||||
return (setting, 8);
|
||||
}
|
||||
|
||||
if (setting.Name.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return (setting, 5);
|
||||
}
|
||||
|
||||
if (!(setting.Areas is null))
|
||||
{
|
||||
foreach (var area in setting.Areas)
|
||||
{
|
||||
// Search for areas on normal queries.
|
||||
if (area.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
return (setting, 4);
|
||||
}
|
||||
|
||||
// Search for Area only on queries with action char.
|
||||
if (area.Contains(query.Replace(":", string.Empty), StringComparison.CurrentCultureIgnoreCase)
|
||||
&& query.EndsWith(":", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
return (setting, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(found.AltNames is null))
|
||||
if (!(setting.AltNames is null))
|
||||
{
|
||||
foreach (var altName in found.AltNames)
|
||||
foreach (var altName in setting.AltNames)
|
||||
{
|
||||
if (altName.Contains(query, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
return (setting, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search by key char '>' for app name and settings path
|
||||
return query.Contains('>') ? ResultHelper.FilterBySettingsPath(found, query) : false;
|
||||
if (query.Contains('>') && ResultHelper.FilterBySettingsPath(setting, query))
|
||||
{
|
||||
return (setting, 1);
|
||||
}
|
||||
|
||||
return (setting, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
namespace SamplePagesExtension;
|
||||
|
||||
@@ -129,6 +130,25 @@ internal sealed partial class SampleListPageWithDetails : ListPage
|
||||
],
|
||||
},
|
||||
},
|
||||
new DetailsElement()
|
||||
{
|
||||
Key = "Commands",
|
||||
Data = new DetailsCommands()
|
||||
{
|
||||
Commands = [
|
||||
new ToastCommand("Hey! You clicked it!", MessageState.Success)
|
||||
{
|
||||
Name = "Do something amazing",
|
||||
Icon = new("\uE945"),
|
||||
},
|
||||
new ToastCommand("I warned you!", MessageState.Error)
|
||||
{
|
||||
Name = "Don't click me",
|
||||
Icon = new("\uEA39"),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
public partial class DetailsCommand : IDetailsCommand
|
||||
public partial class DetailsCommands : IDetailsCommands
|
||||
{
|
||||
public ICommand? Command { get; set; }
|
||||
public ICommand[]? Commands { get; set; }
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public class ThumbnailHelper
|
||||
private static nint GetLargestIcon(string path)
|
||||
{
|
||||
var shinfo = default(NativeMethods.SHFILEINFO);
|
||||
NativeMethods.SHGetFileInfo(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_SYSICONINDEX);
|
||||
NativeMethods.SHGetFileInfo(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_SYSICONINDEX);
|
||||
|
||||
var hIcon = IntPtr.Zero;
|
||||
var iID_IImageList = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950");
|
||||
|
||||
@@ -182,8 +182,8 @@ namespace Microsoft.CommandPalette.Extensions
|
||||
String Text { get; };
|
||||
}
|
||||
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
|
||||
interface IDetailsCommand requires IDetailsData {
|
||||
ICommand Command { get; };
|
||||
interface IDetailsCommands requires IDetailsData {
|
||||
ICommand[] Commands { get; };
|
||||
}
|
||||
[uuid("58070392-02bb-4e89-9beb-47ceb8c3d741")]
|
||||
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
|
||||
|
||||
@@ -107,21 +107,14 @@ namespace ColorPicker.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
public void OnColorPickerMouseDown()
|
||||
public void OpenColorEditor()
|
||||
{
|
||||
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenColorPickerAndThenEditor || _userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
|
||||
lock (_colorPickerVisibilityLock)
|
||||
{
|
||||
lock (_colorPickerVisibilityLock)
|
||||
{
|
||||
HideColorPicker();
|
||||
}
|
||||
HideColorPicker();
|
||||
}
|
||||
|
||||
ShowColorPickerEditor();
|
||||
}
|
||||
else
|
||||
{
|
||||
EndUserSession();
|
||||
}
|
||||
ShowColorPickerEditor();
|
||||
}
|
||||
|
||||
public static void SetTopMost()
|
||||
|
||||
@@ -16,10 +16,12 @@ namespace ColorPicker.Mouse
|
||||
// position and bool indicating zoom in or zoom out
|
||||
event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel;
|
||||
|
||||
event MouseUpEventHandler OnMouseDown;
|
||||
event PrimaryMouseDownEventHandler OnPrimaryMouseDown;
|
||||
|
||||
event SecondaryMouseUpEventHandler OnSecondaryMouseUp;
|
||||
|
||||
event MiddleMouseDownEventHandler OnMiddleMouseDown;
|
||||
|
||||
System.Windows.Point CurrentPosition { get; }
|
||||
|
||||
Color CurrentColor { get; }
|
||||
|
||||
@@ -7,17 +7,18 @@ using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Input;
|
||||
|
||||
using ColorPicker.Helpers;
|
||||
using ManagedCommon;
|
||||
|
||||
using static ColorPicker.NativeMethods;
|
||||
|
||||
namespace ColorPicker.Mouse
|
||||
{
|
||||
public delegate void MouseUpEventHandler(object sender, System.Drawing.Point p);
|
||||
public delegate void PrimaryMouseDownEventHandler(object sender, IntPtr wParam);
|
||||
|
||||
public delegate void SecondaryMouseUpEventHandler(object sender, IntPtr wParam);
|
||||
|
||||
public delegate void MiddleMouseDownEventHandler(object sender, IntPtr wParam);
|
||||
|
||||
internal class MouseHook
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
|
||||
@@ -30,23 +31,25 @@ namespace ColorPicker.Mouse
|
||||
private const int WM_RBUTTONUP = 0x0205;
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
|
||||
private const int WM_RBUTTONDOWN = 0x0204;
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
|
||||
private const int WM_MBUTTONDOWN = 0x0207;
|
||||
|
||||
private IntPtr _mouseHookHandle;
|
||||
private HookProc _mouseDelegate;
|
||||
|
||||
private event MouseUpEventHandler MouseDown;
|
||||
private event PrimaryMouseDownEventHandler PrimaryMouseDown;
|
||||
|
||||
public event MouseUpEventHandler OnMouseDown
|
||||
public event PrimaryMouseDownEventHandler OnPrimaryMouseDown
|
||||
{
|
||||
add
|
||||
{
|
||||
Subscribe();
|
||||
MouseDown += value;
|
||||
PrimaryMouseDown += value;
|
||||
}
|
||||
|
||||
remove
|
||||
{
|
||||
MouseDown -= value;
|
||||
PrimaryMouseDown -= value;
|
||||
Unsubscribe();
|
||||
}
|
||||
}
|
||||
@@ -68,6 +71,23 @@ namespace ColorPicker.Mouse
|
||||
}
|
||||
}
|
||||
|
||||
private event MiddleMouseDownEventHandler MiddleMouseDown;
|
||||
|
||||
public event MiddleMouseDownEventHandler OnMiddleMouseDown
|
||||
{
|
||||
add
|
||||
{
|
||||
Subscribe();
|
||||
MiddleMouseDown += value;
|
||||
}
|
||||
|
||||
remove
|
||||
{
|
||||
MiddleMouseDown -= value;
|
||||
Unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private event MouseWheelEventHandler MouseWheel;
|
||||
|
||||
public event MouseWheelEventHandler OnMouseWheel
|
||||
@@ -126,9 +146,9 @@ namespace ColorPicker.Mouse
|
||||
MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
|
||||
if (wParam.ToInt32() == WM_LBUTTONDOWN)
|
||||
{
|
||||
if (MouseDown != null)
|
||||
if (PrimaryMouseDown != null)
|
||||
{
|
||||
MouseDown.Invoke(null, new System.Drawing.Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y));
|
||||
PrimaryMouseDown.Invoke(null, wParam);
|
||||
}
|
||||
|
||||
return new IntPtr(-1);
|
||||
@@ -150,6 +170,16 @@ namespace ColorPicker.Mouse
|
||||
return new IntPtr(-1);
|
||||
}
|
||||
|
||||
if (wParam.ToInt32() == WM_MBUTTONDOWN)
|
||||
{
|
||||
if (MiddleMouseDown != null)
|
||||
{
|
||||
MiddleMouseDown.Invoke(null, wParam);
|
||||
}
|
||||
|
||||
return new IntPtr(-1);
|
||||
}
|
||||
|
||||
if (wParam.ToInt32() == WM_MOUSEWHEEL)
|
||||
{
|
||||
if (MouseWheel != null)
|
||||
|
||||
@@ -56,10 +56,12 @@ namespace ColorPicker.Mouse
|
||||
|
||||
public event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel;
|
||||
|
||||
public event MouseUpEventHandler OnMouseDown;
|
||||
public event PrimaryMouseDownEventHandler OnPrimaryMouseDown;
|
||||
|
||||
public event SecondaryMouseUpEventHandler OnSecondaryMouseUp;
|
||||
|
||||
public event MiddleMouseDownEventHandler OnMiddleMouseDown;
|
||||
|
||||
public System.Windows.Point CurrentPosition
|
||||
{
|
||||
get
|
||||
@@ -148,9 +150,10 @@ namespace ColorPicker.Mouse
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
_mouseHook.OnMouseDown += MouseHook_OnMouseDown;
|
||||
_mouseHook.OnPrimaryMouseDown += MouseHook_OnPrimaryMouseDown;
|
||||
_mouseHook.OnMouseWheel += MouseHook_OnMouseWheel;
|
||||
_mouseHook.OnSecondaryMouseUp += MouseHook_OnSecondaryMouseUp;
|
||||
_mouseHook.OnMiddleMouseDown += MouseHook_OnMiddleMouseDown;
|
||||
|
||||
if (_userSettings.ChangeCursor.Value)
|
||||
{
|
||||
@@ -169,10 +172,10 @@ namespace ColorPicker.Mouse
|
||||
OnMouseWheel?.Invoke(this, new Tuple<System.Windows.Point, bool>(_previousMousePosition, zoomIn));
|
||||
}
|
||||
|
||||
private void MouseHook_OnMouseDown(object sender, Point p)
|
||||
private void MouseHook_OnPrimaryMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
DisposeHook();
|
||||
OnMouseDown?.Invoke(this, p);
|
||||
OnPrimaryMouseDown?.Invoke(this, wParam);
|
||||
}
|
||||
|
||||
private void MouseHook_OnSecondaryMouseUp(object sender, IntPtr wParam)
|
||||
@@ -181,6 +184,12 @@ namespace ColorPicker.Mouse
|
||||
OnSecondaryMouseUp?.Invoke(this, wParam);
|
||||
}
|
||||
|
||||
private void MouseHook_OnMiddleMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
DisposeHook();
|
||||
OnMiddleMouseDown?.Invoke(this, wParam);
|
||||
}
|
||||
|
||||
private void CopiedColorRepresentation_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
_colorFormatChanged = true;
|
||||
@@ -194,9 +203,10 @@ namespace ColorPicker.Mouse
|
||||
}
|
||||
|
||||
_previousMousePosition = new System.Windows.Point(-1, 1);
|
||||
_mouseHook.OnMouseDown -= MouseHook_OnMouseDown;
|
||||
_mouseHook.OnPrimaryMouseDown -= MouseHook_OnPrimaryMouseDown;
|
||||
_mouseHook.OnMouseWheel -= MouseHook_OnMouseWheel;
|
||||
_mouseHook.OnSecondaryMouseUp -= MouseHook_OnSecondaryMouseUp;
|
||||
_mouseHook.OnMiddleMouseDown -= MouseHook_OnMiddleMouseDown;
|
||||
|
||||
if (_userSettings.ChangeCursor.Value)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,12 @@ namespace ColorPicker.Settings
|
||||
|
||||
SettingItem<ColorPickerActivationAction> ActivationAction { get; }
|
||||
|
||||
SettingItem<ColorPickerClickAction> PrimaryClickAction { get; }
|
||||
|
||||
SettingItem<ColorPickerClickAction> MiddleClickAction { get; }
|
||||
|
||||
SettingItem<ColorPickerClickAction> SecondaryClickAction { get; }
|
||||
|
||||
RangeObservableCollection<string> ColorHistory { get; }
|
||||
|
||||
SettingItem<int> ColorHistoryLimit { get; }
|
||||
|
||||
@@ -49,7 +49,10 @@ namespace ColorPicker.Settings
|
||||
ChangeCursor = new SettingItem<bool>(true);
|
||||
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
|
||||
CopiedColorRepresentation = new SettingItem<string>(ColorRepresentationType.HEX.ToString());
|
||||
ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenEditor);
|
||||
ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenColorPicker);
|
||||
PrimaryClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.PickColorThenEditor);
|
||||
MiddleClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.PickColorAndClose);
|
||||
SecondaryClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.Close);
|
||||
ColorHistoryLimit = new SettingItem<int>(20);
|
||||
ColorHistory.CollectionChanged += ColorHistory_CollectionChanged;
|
||||
ShowColorName = new SettingItem<bool>(false);
|
||||
@@ -78,6 +81,12 @@ namespace ColorPicker.Settings
|
||||
|
||||
public SettingItem<ColorPickerActivationAction> ActivationAction { get; private set; }
|
||||
|
||||
public SettingItem<ColorPickerClickAction> PrimaryClickAction { get; private set; }
|
||||
|
||||
public SettingItem<ColorPickerClickAction> MiddleClickAction { get; private set; }
|
||||
|
||||
public SettingItem<ColorPickerClickAction> SecondaryClickAction { get; private set; }
|
||||
|
||||
public RangeObservableCollection<string> ColorHistory { get; private set; } = new RangeObservableCollection<string>();
|
||||
|
||||
public SettingItem<int> ColorHistoryLimit { get; }
|
||||
@@ -121,6 +130,9 @@ namespace ColorPicker.Settings
|
||||
CopiedColorRepresentation.Value = settings.Properties.CopiedColorRepresentation;
|
||||
CopiedColorRepresentationFormat = new SettingItem<string>(string.Empty);
|
||||
ActivationAction.Value = settings.Properties.ActivationAction;
|
||||
PrimaryClickAction.Value = settings.Properties.PrimaryClickAction;
|
||||
MiddleClickAction.Value = settings.Properties.MiddleClickAction;
|
||||
SecondaryClickAction.Value = settings.Properties.SecondaryClickAction;
|
||||
ColorHistoryLimit.Value = settings.Properties.ColorHistoryLimit;
|
||||
ShowColorName.Value = settings.Properties.ShowColorName;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ using ColorPicker.Settings;
|
||||
using ColorPicker.ViewModelContracts;
|
||||
using Common.UI;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace ColorPicker.ViewModels
|
||||
@@ -79,9 +80,10 @@ namespace ColorPicker.ViewModels
|
||||
{
|
||||
SetColorDetails(mouseInfoProvider.CurrentColor);
|
||||
mouseInfoProvider.MouseColorChanged += Mouse_ColorChanged;
|
||||
mouseInfoProvider.OnMouseDown += MouseInfoProvider_OnMouseDown;
|
||||
mouseInfoProvider.OnPrimaryMouseDown += MouseInfoProvider_OnPrimaryMouseDown;
|
||||
mouseInfoProvider.OnMouseWheel += MouseInfoProvider_OnMouseWheel;
|
||||
mouseInfoProvider.OnSecondaryMouseUp += MouseInfoProvider_OnSecondaryMouseUp;
|
||||
mouseInfoProvider.OnMiddleMouseDown += MouseInfoProvider_OnMiddleMouseDown;
|
||||
}
|
||||
|
||||
_userSettings.ShowColorName.PropertyChanged += (s, e) => { OnPropertyChanged(nameof(ShowColorName)); };
|
||||
@@ -113,7 +115,7 @@ namespace ColorPicker.ViewModels
|
||||
|
||||
private void AppStateHandler_EnterPressed(object sender, EventArgs e)
|
||||
{
|
||||
MouseInfoProvider_OnMouseDown(null, default(System.Drawing.Point));
|
||||
MouseInfoProvider_OnPrimaryMouseDown(null, default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -167,18 +169,50 @@ namespace ColorPicker.ViewModels
|
||||
SetColorDetails(color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tell the color picker that the user have press a mouse button (after release the button)
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of this event</param>
|
||||
/// <param name="p">The current <see cref="System.Drawing.Point"/> of the mouse cursor</param>
|
||||
private void MouseInfoProvider_OnMouseDown(object sender, System.Drawing.Point p)
|
||||
private void MouseInfoProvider_OnPrimaryMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
ClipboardHelper.CopyToClipboard(ColorText);
|
||||
HandleMouseClickAction(_userSettings.PrimaryClickAction.Value);
|
||||
}
|
||||
|
||||
var color = GetColorString();
|
||||
private void MouseInfoProvider_OnMiddleMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
HandleMouseClickAction(_userSettings.MiddleClickAction.Value);
|
||||
}
|
||||
|
||||
var oldIndex = _userSettings.ColorHistory.IndexOf(color);
|
||||
private void MouseInfoProvider_OnSecondaryMouseUp(object sender, IntPtr wParam)
|
||||
{
|
||||
HandleMouseClickAction(_userSettings.SecondaryClickAction.Value);
|
||||
}
|
||||
|
||||
private void HandleMouseClickAction(ColorPickerClickAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ColorPickerClickAction.PickColorThenEditor:
|
||||
ClipboardHelper.CopyToClipboard(ColorText);
|
||||
UpdateColorHistory(GetColorString());
|
||||
|
||||
_appStateHandler.OpenColorEditor();
|
||||
|
||||
break;
|
||||
|
||||
case ColorPickerClickAction.PickColorAndClose:
|
||||
ClipboardHelper.CopyToClipboard(ColorText);
|
||||
UpdateColorHistory(GetColorString());
|
||||
|
||||
_appStateHandler.EndUserSession();
|
||||
|
||||
break;
|
||||
|
||||
case ColorPickerClickAction.Close:
|
||||
_appStateHandler.EndUserSession();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateColorHistory(string color)
|
||||
{
|
||||
int oldIndex = _userSettings.ColorHistory.IndexOf(color);
|
||||
if (oldIndex != -1)
|
||||
{
|
||||
_userSettings.ColorHistory.Move(oldIndex, 0);
|
||||
@@ -192,13 +226,6 @@ namespace ColorPicker.ViewModels
|
||||
{
|
||||
_userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1);
|
||||
}
|
||||
|
||||
_appStateHandler.OnColorPickerMouseDown();
|
||||
}
|
||||
|
||||
private void MouseInfoProvider_OnSecondaryMouseUp(object sender, IntPtr wParam)
|
||||
{
|
||||
_appStateHandler.EndUserSession();
|
||||
}
|
||||
|
||||
private string GetColorString()
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
"org": "microsoft",
|
||||
"project": "OS",
|
||||
"AssignedTo": "mengyuanchen@microsoft.com",
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
|
||||
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT",
|
||||
"IterationPath": "OS\\Future"
|
||||
},
|
||||
"jobNotificationEmail": "mengyuanchen@microsoft.com",
|
||||
"jobNotificationEmail": "PowerToys@microsoft.com",
|
||||
"skip": false,
|
||||
"rebootAfterSetup": false,
|
||||
"oneFuzzJobs": [
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">System</dpiAwareness>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
|
||||
|
||||
@@ -14,25 +14,7 @@ namespace PowerLauncher.Helper
|
||||
{
|
||||
public static class ErrorReporting
|
||||
{
|
||||
private static void Report(Exception e, bool waitForClose)
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
var logger = LogManager.GetLogger("UnHandledException");
|
||||
logger.Fatal(ExceptionFormatter.FormatException(e));
|
||||
|
||||
var reportWindow = new ReportWindow(e);
|
||||
|
||||
if (waitForClose)
|
||||
{
|
||||
reportWindow.ShowDialog();
|
||||
}
|
||||
else
|
||||
{
|
||||
reportWindow.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
private const string LoggerName = "UnHandledException";
|
||||
|
||||
public static void ShowMessageBox(string title, string message)
|
||||
{
|
||||
@@ -47,17 +29,20 @@ namespace PowerLauncher.Helper
|
||||
// handle non-ui thread exceptions
|
||||
System.Windows.Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
Report((Exception)e?.ExceptionObject, true);
|
||||
HandleException(e?.ExceptionObject as Exception, true);
|
||||
});
|
||||
}
|
||||
|
||||
public static void DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
// handle ui thread exceptions
|
||||
Report(e?.Exception, false);
|
||||
if (e != null)
|
||||
{
|
||||
// handle ui thread exceptions
|
||||
HandleException(e.Exception, false);
|
||||
|
||||
// prevent application exist, so the user can copy prompted error info
|
||||
e.Handled = true;
|
||||
// prevent application exist, so the user can copy prompted error info
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static string RuntimeInfo()
|
||||
@@ -68,5 +53,60 @@ namespace PowerLauncher.Helper
|
||||
$"\nx64: {Environment.Is64BitOperatingSystem}";
|
||||
return info;
|
||||
}
|
||||
|
||||
private static void HandleException(Exception e, bool isNotUIThread)
|
||||
{
|
||||
// The crash occurs in PresentationFramework.dll, not necessarily when the Runner UI is visible, originating from this line:
|
||||
// https://github.com/dotnet/wpf/blob/3439f20fb8c685af6d9247e8fd2978cac42e74ac/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Shell/WindowChromeWorker.cs#L1005
|
||||
// Many bug reports because users see the "Report problem UI" after "the" crash with System.Runtime.InteropServices.COMException 0xD0000701 or 0x80263001.
|
||||
// However, displaying this "Report problem UI" during WPF crashes, especially when DWM composition is changing, is not ideal; some users reported it hangs for up to a minute before the "Report problem UI" appears.
|
||||
// This change modifies the behavior to log the exception instead of showing the "Report problem UI".
|
||||
if (IsDwmCompositionException(e as System.Runtime.InteropServices.COMException))
|
||||
{
|
||||
var logger = LogManager.GetLogger(LoggerName);
|
||||
logger.Error($"From {(isNotUIThread ? "non" : string.Empty)} UI thread's exception: {ExceptionFormatter.FormatException(e)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Report(e, isNotUIThread);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Report(Exception e, bool waitForClose)
|
||||
{
|
||||
if (e != null)
|
||||
{
|
||||
var logger = LogManager.GetLogger(LoggerName);
|
||||
logger.Fatal($"From {(waitForClose ? "non" : string.Empty)} UI thread's exception: {ExceptionFormatter.FormatException(e)}");
|
||||
|
||||
var reportWindow = new ReportWindow(e);
|
||||
|
||||
if (waitForClose)
|
||||
{
|
||||
reportWindow.ShowDialog();
|
||||
}
|
||||
else
|
||||
{
|
||||
reportWindow.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsDwmCompositionException(System.Runtime.InteropServices.COMException comException)
|
||||
{
|
||||
if (comException == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var stackTrace = comException.StackTrace;
|
||||
if (string.IsNullOrEmpty(stackTrace))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for common DWM composition changed patterns in the stack trace
|
||||
return stackTrace.Contains("DwmCompositionChanged");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,21 @@
|
||||
</MediaPlayerElement.TransportControls>
|
||||
</MediaPlayerElement>
|
||||
|
||||
<RichTextBlock
|
||||
x:Name="VideoWarningMessage"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource TextFillColorSecondaryBrush}"
|
||||
Visibility="{x:Bind IsWarningMessageVisible(VideoPreviewer.MissingCodecName), Mode=OneWay}">
|
||||
<Paragraph>
|
||||
<Run Text="{x:Bind GetWarningMessage(VideoPreviewer.MissingCodecName), Mode=OneWay}" />
|
||||
<Hyperlink Click="CodecSearchHyperlink_Click">
|
||||
<Run x:Uid="VideoCodecStoreLink" />
|
||||
</Hyperlink>
|
||||
</Paragraph>
|
||||
</RichTextBlock>
|
||||
|
||||
|
||||
<controls:AudioControl
|
||||
x:Name="AudioPreview"
|
||||
Source="{x:Bind AudioPreviewer.Preview, Mode=OneWay}"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user