Compare commits

...

45 Commits

Author SHA1 Message Date
Dustin L. Howett
60a0c9134d Merge remote-tracking branch 'origin/main' into user/yeelam/RandomBuildBreak 2025-04-22 16:42:01 -05:00
Dustin L. Howett
232e1b79bd release: don't publish private symbols for 100 years (#39015) 2025-04-21 23:16:42 -05:00
Gordon Lam (SH)
4979d39489 Update target name 2025-04-22 09:20:19 +08:00
Gordon Lam (SH)
8bf342cc46 Test for Precreation of generated folder for any csproj 2025-04-22 09:20:19 +08:00
Gordon Lam
5ec2728dea Fix build break because of miss Signing for new files (#39014)
* Add CmdPalKeyboardService.dll as part of sign
* Move 3rd party signing to another section
2025-04-22 09:18:55 +08:00
Heiko
d314fa075e [RegPreview] Init with header and add NEW button (#37626)
* default value

* add new button

* fix tool tip

* update button symbol

* feedback changes

* spellcheck
2025-04-21 16:11:07 +08:00
Aung Khaing Khant
90723d5b12 [CmdPal] Fixed #38961 (#38988)
* [CmdPal] Fixed #38961

* [CmdPal] Fixed #38961

* [CmdPal] Fix #38961 Wrong Message for "Open Recycle Bin" Command

* [CmdPal] Fix #38961 Wrong Message for "Open Recycle Bin" Command

---------

Co-authored-by: Aung Khaing Khant <aungkhaingkhant@advent-soft.com>
2025-04-21 15:35:47 +08:00
Yu Leng
f2a5505601 [cmdpal] Add fallback item for system command. (#38865)
* init

* Remove unused cache

* merge main

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
2025-04-21 14:07:43 +08:00
Heiko
311ab88ec3 [CmdPalette > Time and Date] Custom formats (Port #37743) and other plugin improvements - 2 (#38952)
* port changes from broken PR

* fixes

* fix formatting
2025-04-21 13:47:45 +08:00
Niels Laute
c04400e7df [CmdPal] A11y improvements (#38840)
This PR introduces the following changes:

- Adding the right a11y labels - as a result, Accesibility Insights is no longer flagging any errors: https://github.com/microsoft/PowerToys/issues/38395
- Removing and tweaking a few animations, addressing: https://github.com/microsoft/PowerToys/issues/38438
- Localization improvements
2025-04-17 08:51:40 -05:00
Mike Griese
05218e8af6 Add the list item requested shortcuts back (#38573)
* [x] Re-adds the context menu shortcut text
* [x] Hooks up the keybindings to the search box so that you can just press the keys while you have an item selected, and do a context command
* [x] Hook these keybindings up to the context flyout itself
* [x] Adds a sample for testing

Solves #38271
2025-04-17 06:13:11 -05:00
Yu Leng
6cf73ce839 [cmdpal] Port v1 calculator extension (#38629)
* init

* update

* Remove duplicated cp command

* Change the long desc

* Update notice.md

* Use the same icon for fallback item

* Add Rappl to expect list

* update notice.md

* Move the original order back.

* Make Radians become default choice

* Fix empty result

* Remove unused settings.
Move history back.
Refactory the query logic

* fix typo

* merge main

* CmdPal: minor calc updates (#38914)

A bunch of calc updates

* maintain the visibility of the history
* add other formats to the context menu #38708
* some other icon tidying

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Mike Griese <migrie@microsoft.com>
2025-04-17 14:59:10 +08:00
Kai Tao
4f9e829155 [cmdpal] Run cmdpalette from runner locally (#38725)
* empowering users to maximize OOBE to their heart desire (#37823)

empowering users to maximize to their heart desire

* resume main

* Trust selfsign cert in localmachine\root to make msix available

* minor fix

* retry signing

---------

Co-authored-by: Clint Rutkas <clint@rutkas.com>
2025-04-17 11:53:22 +08:00
Ved Nig
397d5cf655 Powertoys for Linear plugin added (#38883)
* Update thirdPartyRunPlugins.md

* Update names.txt

---------

Co-authored-by: Clint Rutkas <clint@rutkas.com>
2025-04-16 15:26:36 -07:00
Mike Griese
01584f33e1 Update the settings form when ext settings are saved (#38851)
This one was subtle - the Settings class in the toolkit didn't ever change the items for a SettingsContentPage. For the main settings window, this was problematic. It would only ever hang onto one instance of that CommandSettings.SettingsContentPage, and never re-retrieve the value from it.

This fixes that issue, by making sure to raise an ItemsChanged in the settings changed handler, so that we automatically pull down the new settings forms.

For settings that were added to commands, as a context item, this wasn't an issue. They were always returning new forms to the host, with the current settings values in it.

Closes #38191
2025-04-16 14:50:56 -05:00
Mike Griese
67463abf98 Immediately select search text on opening page (#38842)
closes #38712
closes #38315
related to #38379 (and might sufficiently close that too)

This immediately selects the search text when a page is loaded.
![38712-select-search-text-000](https://github.com/user-attachments/assets/9db8b455-9afb-4b11-9a30-8ddaa23cdb64)
2025-04-16 14:47:55 -05:00
Mike Griese
e95a570d48 Don't auto-hide when an MSAL dialog is opened on us (#38850)
Apps that want to show MSAL dialogs on the Command Palette would explode if they passed CmdPal's HWND to WithParentActivityOrWindow. It's not entirely clear why, but MSAL would explode if the parent HWND is hidden.

When the MSAL dialog opened, we'd hide ourselves, and badda bing, badda boom, the extension would crash.

MSAL dialogs will set us to WS_DISABLED right before the dialog is opened. Easy solution. Don't hide ourselves, if we're disabled.

Helps some friends not depend on the existence of Teams :P
2025-04-16 14:47:33 -05:00
Heiko
cb27874805 [PowerToysRun] Add version info to plugin error messages (#38491)
* changes

* fix resx
2025-04-16 18:51:20 +00:00
Mike Griese
f65a3fc06f Adds support for JUMBO thumbnails in the helper (#38539)
Adds a parameter to `Toolkit.ThumbnailHelper.GetThumbnail` to retrieve the largest possible icon from the file. For most use cases, the normal icon size will be good for list items and page icons. 

But for details, you'll want to use the JUMBO icons, and to retrieve them, we need to get the icon from a different API. 

As a drive-by, I also have us fetching the highest-res app icon for UWP's rather than the lowest-res icon.

Solves #38238 

Screenshots:
| before | after | 
| ------ | ----- |
| ![image](https://github.com/user-attachments/assets/8aebf163-2f71-45c5-9bee-052ef5528c58) | ![image](https://github.com/user-attachments/assets/7d7b417a-d8d0-4234-ad2b-446a4ca804ba) |
| ![image](https://github.com/user-attachments/assets/3aa21305-2d5f-40a5-a091-fbe5ca5f332c) | ![image](https://github.com/user-attachments/assets/beb5e62f-c649-4cbc-8f6e-8d2c1655cac0) |
2025-04-16 12:04:46 -05:00
Stefan Markovic
c7789abf04 CmdPal: Add low-level keyboard hook for global hotkey (#38250)
Adds the ability to make the global CmdPal hotkey a low-level hook. This is needed for `win+space`, `win+r`, et al. 

I've only added this to the root hotkey. Other hotkeys will still use the normal `RegisterHotkey` ones. We can re-evaluate this for 0.2+.



Originally: https://github.com/zadjii-msft/PowerToys/issues/349

Solves: https://github.com/microsoft/PowerToys/issues/38297

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2025-04-16 05:36:01 -05:00
Davide Giacometti
e700f86ace [QuickAccent] Fix on-screen keyboard activation (#37581)
* fix on-screen keyboard activation

* cleanup
2025-04-16 11:08:43 +08:00
Yu Leng
a16f784011 [cmdpal] Fix empty file name issue when create new ext in "Create New Extension" command. (#38864)
Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
2025-04-16 10:17:43 +08:00
Abhyudit
4e0db267dc [PowerRename] Add 12-hour time format patterns with AM/PM support (#30703) (#38723)
* [PowerRename][Feature] Add new date/time formatting patterns to GetDatedFileName

* [PowerRename][UI] Add date/time shortcut patterns to cheat sheet

* [PowerRename][Tests] Add tests for new date/time formatting patterns

* [PowerRename] [Refactor] Simplify AM/PM string handling in time patterns
2025-04-16 10:15:03 +08:00
Carlos Zamora
0e98cbd57e [CNF] Only enable experimental features if they exist (#37690) 2025-04-16 10:14:23 +08:00
Clint Rutkas
f15bed5323 upgrading toolkit + suppressing warnings (#38746)
* upgrade toolkit to latest

* supressing warnings

* Update expect.txt

making generic

* Update suppression comments for AOT compatibility

* Fix case for 'MVVMTK' in spell-check file

* Update NOTICE.md
2025-04-15 11:58:33 -07:00
Clint Rutkas
d3c4e808d0 Upgrading Boost dependencies (#38782)
Upgrading Boost
2025-04-15 11:57:58 -07:00
Mike Griese
2b5181b4c9 Rename the [Ee]xts dir to ext (#38852)
**WARNING:** This PR will probably blow up all in-flight PRs

at some point in the early days of CmdPal, two of us created seperate
`Exts` and `exts` dirs. Depending on what the casing was on the branch
that you checked one of those out from, it'd get stuck like that on your
PC forever.

Windows didn't care, so we never noticed.

But GitHub does care, and now browsing the source on GitHub is basically
impossible.

Closes #38081
2025-04-15 06:07:22 -05:00
Typpi
60f50d853b Apply security best practices for GitHub Actions / Dependency (#38552)
This update aligns with Microsoft's security guidelines by pinning all GitHub Action tags and Docker tags to their full-length commits. This practice ensures immutability and reduces the risk of supply chain attacks. Note that 1st and 2nd party actions do not require hash pinning.
2025-04-15 16:33:05 +08:00
Stefan Markovic
f1bda8d71f [cmdpal] Setting a new alias should remove the old one (#38193)
* [cmdpal] Fix alias update

* Fix the command palette extension alias update issue

* clean code

---------

Co-authored-by: vanzue <vanzue@outlook.com>
2025-04-15 13:09:35 +08:00
PesBandi
21aa49cefb [ColorPicker]Only close on escape if focused (#37895) 2025-04-15 11:15:41 +08:00
ruslanlap
293fa262bb [PowerToysRun][Docs] Add Weather and Pomodoro to Third-Party plugins (#38760)
* [PowerToysRun][Docs] Add Weather and Pomodoro to Third-Party plugins

* [Spell-check] Add ruslanlap to allowed names and update expect.txt

* Update expect.txt

* Update names.txt

* Update names.txt

* Update names.txt

* Update names.txt
2025-04-14 17:02:29 +00:00
Clint Rutkas
578d99f3b3 upgrading to adjust fix vulnerability (#38784)
* upgrading to adjust fix vulnerablitlity

* Update NOTICE.md

* Update NuGet packages in NOTICE.md
2025-04-14 17:01:54 +00:00
Clint Rutkas
badb029bcf Upgrading some of the Testing framework items (#38779)
* starting to get some of the baseline

* Update NOTICE.md

* Upgrading streamjson gets the others on same version of newtonsoft.json

* Update PowerToys.Settings.csproj

* Update NOTICE.md
2025-04-14 17:01:37 +00:00
dcog989
bec6754aa3 Fix Color Picker resource leak (#38122) (#38147)
* Fix Color Picker resource leak (#38122)

Added a using statement to properly dispose of the Graphics object created from the Bitmap. This fixes resource leak.

* Fix CI complain

* Update MouseInfoProvider.cs

fix whitespace

---------

Co-authored-by: Kai Tao <69313318+vanzue@users.noreply.github.com>
2025-04-14 18:20:55 +08:00
OlegHarchevkin
d986592737 "ǔ" changed to "ŭ" in GetDefaultLetterKeyEPO (#37791) 2025-04-14 16:50:00 +08:00
Ionuț Manța
662f04ed34 [KeyboardManager] Fix modifier Key (Not right or left) stuck (#37930)
* Fix ctr,alt,shift getting stuck

* more changes

* Update src/modules/keyboardmanager/common/Helpers.h

Co-authored-by: Hao Liu <liuhaobupt@163.com>

---------

Co-authored-by: Hao Liu <liuhaobupt@163.com>
2025-04-14 16:48:10 +08:00
Bennett Blodinger
03bc72c436 Change log extension from .txt => .log (#33813)
* Change log extension

From .txt to .log

* Also add workspace logs

---------

Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
2025-04-14 07:20:43 +08:00
Muhammad Danish
5c8aa67781 Add securityContext to configuration files (#38017)
For the winget DSC, Setting developer mode, installing Visual Studio 2022 & fetching and installing VS components all require elevation. Added securityContext: elevated for these resources. These configurations can now be invoked from user context, and will prompt for a single UAC to run resources that require elevation in a separate process.
2025-04-14 07:19:22 +08:00
ruslanlap
b32c04fca1 [PowerToysRun][Docs] Add QuickNotes to Third-Party plugins (#38663)
* Add QuickNotes plugin to third-party Run plugins documentation

* chore: add ruslanlap to spelling allow-list

* chore: add ruslanlap to spelling allow-list

* chore: add ruslanlap to spelling allow-list

* Add ruslanlap to allowed names and remove from expected words list
2025-04-11 18:45:25 +00:00
Gordon Lam
4cb72ee126 Add Zhiwei as part of PowerToys! (#38744)
* Add Zhiwei as part of PowerToys!

* Fix the expect.txt for Zhiwei

* Fix the case problem on expect.txt zhiwei => Zhiwei
2025-04-11 12:58:10 +08:00
Davide Giacometti
55f8f3a53e [CmdPal] Tray icon settings (#38672)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

Added a settings to enable/disable the system tray icon (enabled by default).
Adopter the term "system tray icon" for consistency with Windows 11 settings.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] **Closes:** #38407
2025-04-10 16:44:54 -05:00
Yu Leng
a7994402fe [cmdpal] Add Open URL fallback command for WebSearch ext (#38685)
## Summary of the Pull Request
1. Add new fallback command for websearch

https://github.com/user-attachments/assets/39362d66-db59-42d4-b07c-7bfd60b2e420

## PR Checklist

- [x] **Closes:** #38497

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
2025-04-10 10:34:52 -05:00
RokyZevon
41472a483c [cmdpal] fix a broken link in README.md (#38714)
related issue: #38713
2025-04-10 09:00:33 -05:00
Laszlo Nemeth
94e8559796 [Bug report] - Auto fill bug report parameters. (#37991) 2025-04-10 16:29:06 +08:00
Clint Rutkas
fe53a9c89a empowering users to maximize OOBE to their heart desire (#37823)
empowering users to maximize to their heart desire
2025-04-09 22:27:17 -07:00
516 changed files with 5186 additions and 1291 deletions

View File

@@ -6,12 +6,16 @@ properties:
directives:
description: Enable Developer Mode
allowPrerelease: true
# Requires elevation for the set operation
securityContext: elevated
settings:
Ensure: Present
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: vsPackage
directives:
description: Install Visual Studio 2022 Enterprise (Any edition will work)
# Requires elevation for the set operation
securityContext: elevated
settings:
id: Microsoft.VisualStudio.2022.Enterprise
source: winget
@@ -21,6 +25,8 @@ properties:
directives:
description: Install required VS workloads
allowPrerelease: true
# Requires elevation for the get and set operations
securityContext: elevated
settings:
productId: Microsoft.VisualStudio.Product.Enterprise
channelId: VisualStudio.17.Release

View File

@@ -6,12 +6,16 @@ properties:
directives:
description: Enable Developer Mode
allowPrerelease: true
# Requires elevation for the set operation
securityContext: elevated
settings:
Ensure: Present
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: vsPackage
directives:
description: Install Visual Studio 2022 Professional (Any edition will work)
# Requires elevation for the set operation
securityContext: elevated
settings:
id: Microsoft.VisualStudio.2022.Professional
source: winget
@@ -21,6 +25,8 @@ properties:
directives:
description: Install required VS workloads
allowPrerelease: true
# Requires elevation for the get and set operations
securityContext: elevated
settings:
productId: Microsoft.VisualStudio.Product.Professional
channelId: VisualStudio.17.Release

View File

@@ -6,12 +6,16 @@ properties:
directives:
description: Enable Developer Mode
allowPrerelease: true
# Requires elevation for the set operation
securityContext: elevated
settings:
Ensure: Present
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: vsPackage
directives:
description: Install Visual Studio 2022 Community (Any edition will work)
# Requires elevation for the set operation
securityContext: elevated
settings:
id: Microsoft.VisualStudio.2022.Community
source: winget
@@ -21,6 +25,8 @@ properties:
directives:
description: Install required VS workloads
allowPrerelease: true
# Requires elevation for the get and set operations
securityContext: elevated
settings:
productId: Microsoft.VisualStudio.Product.Community
channelId: VisualStudio.17.Release

View File

@@ -1,6 +1,5 @@
name: "🕷️ Bug report"
description: Report errors or unexpected behavior
type: Bug
labels:
- Issue-Bug
- Needs-Triage
@@ -8,7 +7,8 @@ body:
- type: markdown
attributes:
value: Please make sure to [search for existing issues](https://github.com/microsoft/PowerToys/issues) before filing a new one!
- type: input
- id: version
type: input
attributes:
label: Microsoft PowerToys version
placeholder: X.XX.X
@@ -16,7 +16,8 @@ body:
validations:
required: true
- type: dropdown
- id: installed
type: dropdown
attributes:
label: Installation method
description: How / Where was PowerToys installed from?
@@ -33,14 +34,6 @@ body:
validations:
required: true
- type: dropdown
attributes:
label: Running as admin
description: Are you running PowerToys as Admin?
options:
- "Yes"
- "No"
- type: dropdown
attributes:
label: Area(s) with issue?
@@ -67,7 +60,7 @@ body:
- Keyboard Manager
- Mouse Utilities
- Mouse Without Borders
- New+
- New+
- Peek
- PowerRename
- PowerToys Run
@@ -106,6 +99,19 @@ body:
validations:
required: false
- id: additionalInfo
type: textarea
attributes:
label: Additional Information
placeholder: |
OS version
.Net version
System Language
User or System Installation
Running as admin
validations:
required: false
- type: textarea
attributes:
label: Other Software
@@ -116,3 +122,4 @@ body:
My Cool Application v0.3 (include a code snippet if it would help!)
validations:
required: false

View File

@@ -188,6 +188,8 @@ zhaoqpcn
Zoltan
Zykova
Sameerjs
ruslanlap
vednig
# OTHERS

View File

@@ -56,12 +56,10 @@ APIIs
Apm
APPBARDATA
APPEXECLINK
APPICONREFERENCE
APPLICATIONFRAMEHOST
appmanifest
APPMODEL
APPNAME
APPPUBLISHER
appref
appsettings
appwindow
@@ -173,9 +171,9 @@ CCHFORMNAME
CCom
CContext
CDeclaration
cdn
CElems
CENTERALIGN
cer
certlm
certmgr
cfp
@@ -254,8 +252,6 @@ createdump
CREATEPROCESS
CREATESCHEDULEDTASK
CREATESTRUCT
CREATETHREAD
CREATEWINDOW
CREATEWINDOWFAILED
CRECT
CRH
@@ -277,6 +273,7 @@ CURSORINFO
cursorpos
customaction
CUSTOMACTIONTEST
CUSTOMFORMATPLACEHOLDER
CVal
cvd
CVirtual
@@ -308,11 +305,7 @@ DCOM
DComposition
DCR
ddd
DDEAPPLICATION
DDECOMMAND
DDEIf
DDEIFEXEC
DDETOPIC
DDevice
DDxgi
Deact
@@ -326,16 +319,13 @@ DEFAULTFLAGS
DEFAULTICON
defaultlib
DEFAULTONLY
DEFAULTTOFOLDER
DEFAULTTONEAREST
DEFAULTTONULL
DEFAULTTOPRIMARY
DEFAULTTOSTAR
DEFERERASE
DEFPUSHBUTTON
deinitialization
DELA
DELEGATEEXECUTE
DELETEDKEYIMAGE
DELETESCANS
deletethis
@@ -355,6 +345,7 @@ DEVMODE
DEVMODEW
devpal
DIALOGEX
digicert
dimm
DISABLEASACTIONKEY
DISABLENOSCROLL
@@ -389,7 +380,6 @@ dreamsofameaningfullife
drivedetectionwarning
Droid
DROPFILES
DROPTARGET
DSTINVERT
DSurface
DTexture
@@ -510,12 +500,10 @@ Fira
FIXEDFILEINFO
FIXEDSYS
flac
flaticon
flyouts
FMask
fmtid
FOF
WANTNUKEWARNING
FOFX
FOLDERID
folderpath
@@ -525,7 +513,6 @@ FORCEMINIMIZE
FORMATDLGORD
formatetc
FORPARSING
fpvm
Fqc
FRAMECHANGED
frm
@@ -559,7 +546,6 @@ GETSECKEY
GETSTICKYKEYS
GETTEXTLENGTH
GHND
gifv
GMEM
GNumber
gpedit
@@ -653,7 +639,6 @@ HROW
hsb
HSCROLL
hsi
HSSH
HTCLIENT
hthumbnail
HTOUCHINPUT
@@ -691,12 +676,12 @@ iextn
IFACEMETHOD
IFACEMETHODIMP
IFile
IGNOREBASECLASS
IGNOREUNKNOWN
IGo
iid
Iindex
Ijwhost
ILD
IMAGEHLP
IMAGERESIZERCONTEXTMENU
IMAGERESIZEREXT
@@ -740,8 +725,6 @@ Inste
Interlop
INTRESOURCE
INVALIDARG
INVALIDCALL
INVALIDINDEX
invalidoperatioexception
ipcmanager
IPREVIEW
@@ -803,7 +786,6 @@ LEVELID
LExit
lhwnd
LIBID
libraryincludes
LIMITSIZE
LIMITTEXT
lindex
@@ -905,7 +887,6 @@ MBM
MBR
MDICHILD
MDL
mdpvm
mdtext
mdtxt
mdwn
@@ -961,6 +942,7 @@ mpmc
MRM
MRT
mru
MSAL
msc
mscorlib
msctls
@@ -1024,6 +1006,7 @@ netsh
newcolor
NEWDIALOGSTYLE
NEWFILE
NEWFILEHEADER
newitem
newpath
newplus
@@ -1053,7 +1036,6 @@ NOCRLF
nodeca
NODRAWCAPTION
NODRAWICON
NOFIXUPS
NOINHERITLAYOUT
NOINTERFACE
NOINVERT
@@ -1069,13 +1051,11 @@ NONELEVATED
NONINFRINGEMENT
nonspace
nonstd
NOOPEN
NOOWNERZORDER
NOPARENTNOTIFY
NOPREFIX
NOREDIRECTIONBITMAP
NOREDRAW
NOREMAPCLSID
NOREMOVE
norename
NOREPEAT
@@ -1094,11 +1074,9 @@ NOTIFYICONDATAW
NOTIMPL
NOTOPMOST
NOTRACK
NOTRUNCATE
NOTSRCCOPY
NOTSRCERASE
NOTXORPEN
NOUSERSETTINGS
NOZORDER
NPH
npmjs
@@ -1224,6 +1202,7 @@ Podcasts
POINTERID
POINTERUPDATE
Pokedex
Pomodoro
Popups
POPUPWINDOW
POSITIONITEM
@@ -1318,11 +1297,11 @@ Quarternary
QUERYENDSESSION
QUERYOPEN
QUEUESYNC
QUICKTIP
QUNS
QXZ
RAII
RAlt
Rappl
randi
Rasterization
Rasterize
@@ -1347,7 +1326,6 @@ REFCLSID
REFIID
REGCLS
regfile
REGISTERCLASSEX
REGISTERCLASSFAILED
REGISTRYHEADER
registrypath
@@ -1359,7 +1337,6 @@ REINSTALLMODE
reloadable
Relogger
remappings
REMAPRUNDLL
REMAPSUCCESSFUL
REMAPUNSUCCESSFUL
Remotable
@@ -1436,7 +1413,6 @@ SDDL
SDKDDK
sdns
searchterm
searchtext
SEARCHUI
SECONDARYDISPLAY
secpol
@@ -1485,6 +1461,7 @@ shellex
SHELLEXECUTEINFO
SHELLEXECUTEINFOW
SHELLEXTENSION
SHELLICONSIZE
SHELLNEWVALUE
SHFILEINFO
SHFILEOPSTRUCT
@@ -1493,9 +1470,9 @@ SHGDNF
SHGFI
SHGFIICON
SHGFILARGEICON
SHIL
shinfo
shlwapi
SHNAMEMAPPING
shobjidl
SHORTCUTATLEAST
SHORTCUTMAXONEACTIONKEY
@@ -1525,6 +1502,7 @@ SIDs
siex
sigdn
SIGNINGSCENARIO
signtool
Signtool
SINGLEKEY
sipolicy
@@ -1546,7 +1524,6 @@ SNAPPROCESS
snwprintf
softline
SOURCECLIENTAREAONLY
sourced
sourcedoc
SOURCEHEADER
sourcesdirectory
@@ -1673,6 +1650,7 @@ telephon
templatenamespace
testprocess
TEXCOORD
TEXTBOXNEWLINE
TEXTEXTRACTOR
TEXTINCLUDE
tfopen
@@ -1685,7 +1663,6 @@ THotkey
throughs
TIcon
TILEDWINDOW
TILEINFO
TILLSON
timedate
timediff
@@ -1699,9 +1676,6 @@ TLayout
tlb
tlbimp
tlc
TPMLEFTALIGN
TPMRETURNCMD
TMPVAR
TNP
Toolhelp
toolkitconverters
@@ -1709,6 +1683,8 @@ toolwindow
TOPDOWNDIB
TOUCHEVENTF
TOUCHINPUT
TPMLEFTALIGN
TPMRETURNCMD
TRACEHANDLE
tracelogging
tracerpt
@@ -1782,7 +1758,6 @@ USRDLL
UType
uuidv
uwp
ums
uxt
uxtheme
vabdq
@@ -1809,7 +1784,6 @@ VERTSIZE
VFT
vget
vgetq
videourl
viewmodel
VIRTKEY
VIRTUALDESK
@@ -1843,7 +1817,7 @@ vstprintf
VSTT
vswhere
Vtbl
WANTMAPPINGHANDLE
WANTNUKEWARNING
WANTPALM
wasdk
wbem
@@ -1958,7 +1932,6 @@ WUX
Wwanpp
XAxis
xclip
xdoc
XDocument
XElement
xfd
@@ -1981,13 +1954,13 @@ Yeet
YIncrement
yinle
yinyue
youtube
YPels
YResolution
YStr
YTM
YVIRTUALSCREEN
ZEROINIT
Zhiwei
zonable
zoneset
Zoneszonabletester

26
.github/workflows/dependency-review.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request,
# surfacing known-vulnerable versions of the packages declared or updated in the PR.
# Once installed, if the workflow run is marked as required,
# PRs introducing known-vulnerable packages will be blocked from merging.
#
# As recommended by Microsoft's security guidelines (https://docs.opensource.microsoft.com/security/tsg/actions/#requirements-for-security-hardening-your-own-github-actions),
# 3rd-party actions should be pinned to a specific commit hash to prevent supply chain attacks.
# This update aligns with best practices; 1st/2nd-party actions is not required hash pinning.
#
# Source repository: https://github.com/actions/dependency-review-action
name: 'Dependency Review'
on: [pull_request]
permissions:
contents: read
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4

View File

@@ -93,7 +93,7 @@ jobs:
steps:
- name: check-spelling
id: spelling
uses: check-spelling/check-spelling@v0.0.24
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
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@v0.0.24
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
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@v0.0.24
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
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@v0.0.24
uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24
with:
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
checkout: true

View File

@@ -220,6 +220,7 @@
"WinUI3Apps\\PowerToys.Settings.exe",
"PowerToys.CmdPalModuleInterface.dll",
"CmdPalKeyboardService.dll",
"*Microsoft.CmdPal.UI_*.msix"
],
"SigningInfo": {
@@ -330,6 +331,8 @@
"TestableIO.System.IO.Abstractions.Wrappers.dll",
"WinUI3Apps\\TestableIO.System.IO.Abstractions.Wrappers.dll",
"WinUI3Apps\\OpenAI.dll",
"Testably.Abstractions.FileSystem.Interface.dll",
"WinUI3Apps\\Testably.Abstractions.FileSystem.Interface.dll",
"ColorCode.Core.dll",
"ColorCode.UWP.dll",
"UnitsNet.dll",

View File

@@ -148,5 +148,7 @@ extends:
parameters:
versionNumber: ${{ parameters.versionNumber }}
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
${{ if ne(parameters.publishSymbolsToPublic, true) }}:
symbolExpiryTime: 10 # For private builds, expire symbols within 10 days. The default is 100 years.
subscription: $(SymbolPublishingServiceConnection)
symbolProject: $(SymbolPublishingProject)

View File

@@ -188,6 +188,7 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
- [@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
- [@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

View File

@@ -10,14 +10,14 @@
<PackageVersion Include="Azure.AI.OpenAI" Version="1.0.0-beta.17" />
<PackageVersion Include="CommunityToolkit.Common" Version="8.4.0" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250129-preview2" />
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
<PackageVersion Include="ControlzEx" Version="6.0.0" />
@@ -29,7 +29,7 @@
<PackageVersion Include="Mages" Version="3.0.0" />
<PackageVersion Include="Markdig.Signed" Version="0.34.0" />
<!-- 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="2.5.187" />
<PackageVersion Include="MessagePack" Version="3.1.3" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.4" />
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
@@ -61,7 +61,7 @@
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
<!-- Moq to stay below v4.20 due to behavior change. need to be sure fixed -->
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="MSTest" Version="3.6.3" />
<PackageVersion Include="MSTest" Version="3.8.3" />
<PackageVersion Include="NLog" Version="5.0.4" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
@@ -69,7 +69,7 @@
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
<PackageVersion Include="SharpCompress" Version="0.37.2" />
<PackageVersion Include="StreamJsonRpc" Version="2.19.27" />
<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.4" />
@@ -84,14 +84,17 @@
<!-- 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.4" />
<PackageVersion Include="System.Drawing.Common" Version="9.0.4" />
<PackageVersion Include="System.IO.Abstractions" Version="21.0.29" />
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="21.0.29" />
<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.4" />
<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.4" />
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.4" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.4" />
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
<PackageVersion Include="UnitsNet" Version="5.56.0" />
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />

View File

@@ -75,6 +75,40 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
```
## Utility: Command Palette Built-in Extensions
### Calculator
#### Mages
We use the Mages NuGet package for calculating the result of expression.
**Source**: [https://github.com/FlorianRappl/Mages](https://github.com/FlorianRappl/Mages)
```
The MIT License (MIT)
Copyright (c) 2016 - 2025 Florian Rappl
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: File Explorer Add-ins
### Monaco Editor
@@ -1393,7 +1427,6 @@ SOFTWARE.
## NuGet Packages used by PowerToys
- AdaptiveCards.ObjectModel.WinUI3 2.0.0-beta
- AdaptiveCards.Rendering.WinUI3 2.1.0-beta
- AdaptiveCards.Templating 2.0.2
@@ -1401,14 +1434,14 @@ SOFTWARE.
- Azure.AI.OpenAI 1.0.0-beta.17
- CommunityToolkit.Common 8.4.0
- CommunityToolkit.Mvvm 8.4.0
- CommunityToolkit.WinUI.Animations 8.2.250129-preview2
- CommunityToolkit.WinUI.Collections 8.2.250129-preview2
- CommunityToolkit.WinUI.Controls.Primitives 8.2.250129-preview2
- CommunityToolkit.WinUI.Controls.Segmented 8.2.250129-preview2
- CommunityToolkit.WinUI.Controls.SettingsControls 8.2.250129-preview2
- CommunityToolkit.WinUI.Controls.Sizers 8.2.250129-preview2
- CommunityToolkit.WinUI.Converters 8.2.250129-preview2
- CommunityToolkit.WinUI.Extensions 8.2.250129-preview2
- CommunityToolkit.WinUI.Animations 8.2.250402
- CommunityToolkit.WinUI.Collections 8.2.250402
- CommunityToolkit.WinUI.Controls.Primitives 8.2.250402
- CommunityToolkit.WinUI.Controls.Segmented 8.2.250402
- CommunityToolkit.WinUI.Controls.SettingsControls 8.2.250402
- CommunityToolkit.WinUI.Controls.Sizers 8.2.250402
- CommunityToolkit.WinUI.Converters 8.2.250402
- CommunityToolkit.WinUI.Extensions 8.2.250402
- CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2
- CommunityToolkit.WinUI.UI.Controls.Markdown 7.1.2
- ControlzEx 6.0.0
@@ -1419,7 +1452,7 @@ SOFTWARE.
- LazyCache 2.4.0
- Mages 3.0.0
- Markdig.Signed 0.34.0
- MessagePack 2.5.187
- MessagePack 3.1.3
- Microsoft.Bcl.AsyncInterfaces 9.0.4
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
- Microsoft.Data.Sqlite 9.0.4
@@ -1445,14 +1478,14 @@ SOFTWARE.
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
- ModernWpfUI 0.9.4
- Moq 4.18.4
- MSTest 3.6.3
- MSTest 3.8.3
- NLog.Extensions.Logging 5.3.8
- NLog.Schema 5.2.8
- OpenAI 2.0.0
- ReverseMarkdown 4.1.0
- ScipBe.Common.Office.OneNote 3.0.1
- SharpCompress 0.37.2
- StreamJsonRpc 2.19.27
- StreamJsonRpc 2.21.69
- StyleCop.Analyzers 1.2.0-beta.556
- System.CodeDom 9.0.4
- System.CommandLine 2.0.0-beta4.22272.1
@@ -1463,17 +1496,21 @@ SOFTWARE.
- System.Diagnostics.EventLog 9.0.4
- System.Diagnostics.PerformanceCounter 9.0.4
- System.Drawing.Common 9.0.4
- System.IO.Abstractions 21.0.29
- System.IO.Abstractions.TestingHelpers 21.0.29
- System.IO.Abstractions 22.0.13
- System.IO.Abstractions.TestingHelpers 22.0.13
- System.Management 9.0.4
- System.Net.Http 4.3.4
- System.Private.Uri 4.3.2
- System.Reactive 6.0.1
- System.Runtime.Caching 9.0.4
- System.ServiceProcess.ServiceController 9.0.4
- System.Text.Encoding.CodePages 9.0.4
- System.Text.Json 9.0.4
- System.Text.RegularExpressions 4.3.1
- UnicodeInformation 2.6.0
- UnitsNet 5.56.0
- UTF.Unknown 2.5.1
- WinUIEx 2.2.0
- WPF-UI 3.0.5
- WyHash 1.0.5

View File

@@ -624,19 +624,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CommandPalette", "CommandPa
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Built-in Extensions", "Built-in Extensions", "{ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Apps", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj", "{6CE438DF-C245-4997-A360-0A0939E4BA34}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Apps", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj", "{6CE438DF-C245-4997-A360-0A0939E4BA34}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Bookmarks", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj", "{E09AA983-C755-474F-83D6-A5CDF528C070}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Bookmarks", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj", "{E09AA983-C755-474F-83D6-A5CDF528C070}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Calc", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj", "{6D56B64D-FF1F-488F-AFED-9B9854A5D399}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Calc", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj", "{6D56B64D-FF1F-488F-AFED-9B9854A5D399}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Registry", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj", "{92EC89E4-9972-453A-8A1A-3A9E230C146A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Registry", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj", "{92EC89E4-9972-453A-8A1A-3A9E230C146A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsServices", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj", "{51939B4F-1F62-4BFF-A6A2-C08646E5BE95}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsServices", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj", "{51939B4F-1F62-4BFF-A6A2-C08646E5BE95}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsSettings", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj", "{D1160404-D3D1-497A-883A-4059C07C2273}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsSettings", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj", "{D1160404-D3D1-497A-883A-4059C07C2273}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsTerminal", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj", "{40F6D69D-E321-400F-A767-5628C7AE453D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsTerminal", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj", "{40F6D69D-E321-400F-A767-5628C7AE453D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extension SDK", "Extension SDK", "{F3D09629-59A2-4924-A4B9-D6BFAA2C1B49}"
EndProject
@@ -650,9 +650,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.UI", "sr
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample Extensions", "Sample Extensions", "{071E18A4-A530-46B8-AB7D-B862EE55E24E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessMonitorExtension", "src\modules\cmdpal\Exts\ProcessMonitorExtension\ProcessMonitorExtension.csproj", "{C846F7A7-792A-47D9-B0CB-417C900EE03D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessMonitorExtension", "src\modules\cmdpal\ext\ProcessMonitorExtension\ProcessMonitorExtension.csproj", "{C846F7A7-792A-47D9-B0CB-417C900EE03D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "src\modules\cmdpal\Exts\SamplePagesExtension\SamplePagesExtension.csproj", "{C831231F-891C-4572-9694-45062534B42A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "src\modules\cmdpal\ext\SamplePagesExtension\SamplePagesExtension.csproj", "{C831231F-891C-4572-9694-45062534B42A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{7520A2FE-00A2-49B8-83ED-DB216E874C04}"
EndProject
@@ -660,7 +660,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI.ViewModels", "src\modules\cmdpal\Microsoft.CmdPal.UI.ViewModels\Microsoft.CmdPal.UI.ViewModels.csproj", "{C66020D1-CB10-4CF7-8715-84C97FD5E5E2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.ClipboardHistory", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj", "{79775343-7A3D-445D-9104-3DD5B2893DF9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.ClipboardHistory", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj", "{79775343-7A3D-445D-9104-3DD5B2893DF9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalModuleInterface", "src\modules\cmdpal\CmdPalModuleInterface\CmdPalModuleInterface.vcxproj", "{0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}"
EndProject
@@ -668,15 +668,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesCsharpLibrary", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension.win10", "src\modules\NewPlus\NewShellExtensionContextMenu.win10\NewPlus.ShellExtension.win10.vcxproj", "{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Indexer", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj", "{453CBB73-A3CB-4D0B-8D24-6940B86FE21D}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Indexer", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj", "{453CBB73-A3CB-4D0B-8D24-6940B86FE21D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Shell", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj", "{C0CE3B5E-16D3-495D-B335-CA791B660162}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Shell", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj", "{C0CE3B5E-16D3-495D-B335-CA791B660162}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowWalker", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj", "{3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowWalker", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj", "{3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSearch", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj", "{605E914B-7232-4789-AF46-BF5D3DDFC14E}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSearch", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj", "{605E914B-7232-4789-AF46-BF5D3DDFC14E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WinGet", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WinGet", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", "src\modules\AdvancedPaste\AdvancedPaste.UnitTests\AdvancedPaste.UnitTests.csproj", "{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}"
EndProject
@@ -690,7 +690,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItModuleInterface", "sr
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItSettingsInterop", "src\modules\ZoomIt\ZoomItSettingsInterop\ZoomItSettingsInterop.vcxproj", "{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.TimeDate", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj", "{DCC6BD67-17BB-47AA-B507-FB0FE43A7449}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.TimeDate", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj", "{DCC6BD67-17BB-47AA-B507-FB0FE43A7449}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITestAutomation", "src\common\UITestAutomation\UITestAutomation.csproj", "{A558C25D-2007-498E-8B6F-43405AFAE9E2}"
EndProject
@@ -704,7 +704,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hosts.UITests", "src\module
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryPreview.FuzzTests", "src\modules\registrypreview\RegistryPreview.FuzzTests\RegistryPreview.FuzzTests.csproj", "{5702B3CC-8575-48D5-83D8-15BB42269CD3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -2574,14 +2576,18 @@ Global
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|ARM64.Build.0 = Debug|ARM64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.ActiveCfg = Debug|x64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.Build.0 = Debug|x64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x86.ActiveCfg = Debug|x64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x86.Build.0 = Debug|x64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.ActiveCfg = Release|ARM64
{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
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.ActiveCfg = Release|x64
{64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.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
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.Build.0 = Debug|x64
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.ActiveCfg = Release|ARM64
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.Build.0 = Release|ARM64
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.ActiveCfg = Release|x64
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2852,6 +2858,7 @@ Global
{4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
{64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}
{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}

View File

@@ -43,6 +43,9 @@ Contact the developers of a plugin directly for assistance with a specific plugi
| [TailwindCSS](https://github.com/skttl/ptrun-tailwindcss) | [skttl](https://github.com/skttl) | Search the documentation of TailwindCSS |
| [HttpStatusCodes](https://github.com/grzhan/HttpStatusCodePowerToys) | [grzhan](https://github.com/grzhan) | Search for http status codes |
| [SVGL](https://github.com/Sameerjs6/powertoys-svgl) | [SameerJS6](https://github.com/SameerJS6) | Search, Browse and copy SVG logos from SVGL. |
| [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. |
## Extending software plugins
@@ -65,3 +68,4 @@ 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 |

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Some items may be set in Directory.Build.props in root -->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project=".\Common.Dotnet.PrepareGeneratedFolder.targets" />
<PropertyGroup>
<WindowsSdkPackageVersion>10.0.22621.57</WindowsSdkPackageVersion>
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>

View File

@@ -0,0 +1,16 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="EnsureGeneratedBaseFolder" BeforeTargets="XamlPreCompile">
<PropertyGroup>
<!-- Only create the base 'generated' folder -->
<CompilerGeneratedFilesOutputPath>$(ProjectDir)obj\g</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<!-- Create 'generated' folder if missing -->
<MakeDir Directories="$(CompilerGeneratedFilesOutputPath)" />
<!-- Optional logging for debugging -->
<Message Text="Ensured: $(GeneratedBasePath)" Importance="Low" />
</Target>
</Project>

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// 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.
@@ -63,8 +63,16 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "<Dotnet port with style preservation>", Scope = "namespaceanddescendants", Target = "MouseWithoutBorders")]
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "<Dotnet port with style preservation>", Scope = "namespaceanddescendants", Target = "MouseWithoutBorders")]
// AOT
// AOT MVVMTK0045
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "AdvancedPaste.ViewModels")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "HostsUILib")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "EnvironmentVariablesUILib")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.UI")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.UI.Views")]
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")]
// AOT MVVMTK0049
[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")]

View File

@@ -25,7 +25,7 @@ namespace AllExperiments
}
// Using InvariantCulture since this is used for a log file name
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));

View File

@@ -54,7 +54,7 @@ namespace ManagedCommon
Directory.CreateDirectory(applicationLogPath);
}
var logFilePath = Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
var logFilePath = Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));

View File

@@ -14,6 +14,9 @@
<PackageReference Include="Appium.WebDriver" />
<PackageReference Include="MSTest" />
<PackageReference Include="System.IO.Abstractions" />
<PackageReference Include="System.Net.Http" />
<PackageReference Include="System.Private.Uri" />
<PackageReference Include="System.Text.RegularExpressions" />
</ItemGroup>
</Project>

View File

@@ -8,49 +8,49 @@ struct LogSettings
inline const static std::wstring logLevelOption = L"logLevel";
inline const static std::string runnerLoggerName = "runner";
inline const static std::wstring logPath = L"Logs\\";
inline const static std::wstring runnerLogPath = L"RunnerLogs\\runner-log.txt";
inline const static std::wstring runnerLogPath = L"RunnerLogs\\runner-log.log";
inline const static std::string actionRunnerLoggerName = "action-runner";
inline const static std::wstring actionRunnerLogPath = L"RunnerLogs\\action-runner-log.txt";
inline const static std::wstring actionRunnerLogPath = L"RunnerLogs\\action-runner-log.log";
inline const static std::string updateLoggerName = "update";
inline const static std::wstring updateLogPath = L"UpdateLogs\\update-log.txt";
inline const static std::wstring updateLogPath = L"UpdateLogs\\update-log.log";
inline const static std::string fileExplorerLoggerName = "FileExplorer";
inline const static std::wstring fileExplorerLogPath = L"Logs\\file-explorer-log.txt";
inline const static std::wstring fileExplorerLogPath = L"Logs\\file-explorer-log.log";
inline const static std::string gcodePrevLoggerName = "GcodePrevHandler";
inline const static std::wstring gcodePrevLogPath = L"logs\\FileExplorer_localLow\\GcodePreviewHandler\\gcode-prev-handler-log.txt";
inline const static std::wstring gcodePrevLogPath = L"logs\\FileExplorer_localLow\\GcodePreviewHandler\\gcode-prev-handler-log.log";
inline const static std::string gcodeThumbLoggerName = "GcodeThumbnailProvider";
inline const static std::wstring gcodeThumbLogPath = L"logs\\FileExplorer_localLow\\GcodeThumbnailProvider\\gcode-thumbnail-provider-log.txt";
inline const static std::wstring gcodeThumbLogPath = L"logs\\FileExplorer_localLow\\GcodeThumbnailProvider\\gcode-thumbnail-provider-log.log";
inline const static std::string mdPrevLoggerName = "MDPrevHandler";
inline const static std::wstring mdPrevLogPath = L"logs\\FileExplorer_localLow\\MDPrevHandler\\md-prev-handler-log.txt";
inline const static std::wstring mdPrevLogPath = L"logs\\FileExplorer_localLow\\MDPrevHandler\\md-prev-handler-log.log";
inline const static std::string monacoPrevLoggerName = "MonacoPrevHandler";
inline const static std::wstring monacoPrevLogPath = L"logs\\FileExplorer_localLow\\MonacoPrevHandler\\monaco-prev-handler-log.txt";
inline const static std::wstring monacoPrevLogPath = L"logs\\FileExplorer_localLow\\MonacoPrevHandler\\monaco-prev-handler-log.log";
inline const static std::string pdfPrevLoggerName = "PdfPrevHandler";
inline const static std::wstring pdfPrevLogPath = L"logs\\FileExplorer_localLow\\PdfPrevHandler\\pdf-prev-handler-log.txt";
inline const static std::wstring pdfPrevLogPath = L"logs\\FileExplorer_localLow\\PdfPrevHandler\\pdf-prev-handler-log.log";
inline const static std::string pdfThumbLoggerName = "PdfThumbnailProvider";
inline const static std::wstring pdfThumbLogPath = L"logs\\FileExplorer_localLow\\PdfThumbnailProvider\\pdf-thumbnail-provider-log.txt";
inline const static std::wstring pdfThumbLogPath = L"logs\\FileExplorer_localLow\\PdfThumbnailProvider\\pdf-thumbnail-provider-log.log";
inline const static std::string qoiPrevLoggerName = "QoiPrevHandler";
inline const static std::wstring qoiPrevLogPath = L"logs\\FileExplorer_localLow\\QoiPreviewHandler\\qoi-prev-handler-log.txt";
inline const static std::wstring qoiPrevLogPath = L"logs\\FileExplorer_localLow\\QoiPreviewHandler\\qoi-prev-handler-log.log";
inline const static std::string qoiThumbLoggerName = "QoiThumbnailProvider";
inline const static std::wstring qoiThumbLogPath = L"logs\\FileExplorer_localLow\\QoiThumbnailProvider\\qoi-thumbnail-provider-log.txt";
inline const static std::wstring qoiThumbLogPath = L"logs\\FileExplorer_localLow\\QoiThumbnailProvider\\qoi-thumbnail-provider-log.log";
inline const static std::string stlThumbLoggerName = "StlThumbnailProvider";
inline const static std::wstring stlThumbLogPath = L"logs\\FileExplorer_localLow\\StlThumbnailProvider\\stl-thumbnail-provider-log.txt";
inline const static std::wstring stlThumbLogPath = L"logs\\FileExplorer_localLow\\StlThumbnailProvider\\stl-thumbnail-provider-log.log";
inline const static std::string svgPrevLoggerName = "SvgPrevHandler";
inline const static std::wstring svgPrevLogPath = L"logs\\FileExplorer_localLow\\SvgPrevHandler\\svg-prev-handler-log.txt";
inline const static std::wstring svgPrevLogPath = L"logs\\FileExplorer_localLow\\SvgPrevHandler\\svg-prev-handler-log.log";
inline const static std::string svgThumbLoggerName = "SvgThumbnailProvider";
inline const static std::wstring svgThumbLogPath = L"logs\\FileExplorer_localLow\\SvgThumbnailProvider\\svg-thumbnail-provider-log.txt";
inline const static std::wstring svgThumbLogPath = L"logs\\FileExplorer_localLow\\SvgThumbnailProvider\\svg-thumbnail-provider-log.log";
inline const static std::string launcherLoggerName = "launcher";
inline const static std::wstring launcherLogPath = L"LogsModuleInterface\\launcher-log.txt";
inline const static std::wstring launcherLogPath = L"LogsModuleInterface\\launcher-log.log";
inline const static std::string mouseWithoutBordersLoggerName = "mouseWithoutBorders";
inline const static std::wstring mouseWithoutBordersLogPath = L"LogsModuleInterface\\mouseWithoutBorders-log.txt";
inline const static std::wstring awakeLogPath = L"Logs\\awake-log.txt";
inline const static std::wstring powerAccentLogPath = L"quick-accent-log.txt";
inline const static std::wstring mouseWithoutBordersLogPath = L"LogsModuleInterface\\mouseWithoutBorders-log.log";
inline const static std::wstring awakeLogPath = L"Logs\\awake-log.log";
inline const static std::wstring powerAccentLogPath = L"quick-accent-log.log";
inline const static std::string fancyZonesLoggerName = "fancyzones";
inline const static std::wstring fancyZonesLogPath = L"fancyzones-log.txt";
inline const static std::wstring fancyZonesLogPath = L"fancyzones-log.log";
inline const static std::wstring fancyZonesOldLogPath = L"FancyZonesLogs\\"; // needed to clean up old logs
inline const static std::string shortcutGuideLoggerName = "shortcut-guide";
inline const static std::wstring shortcutGuideLogPath = L"ShortcutGuideLogs\\shortcut-guide-log.txt";
inline const static std::wstring powerOcrLogPath = L"Logs\\text-extractor-log.txt";
inline const static std::wstring shortcutGuideLogPath = L"ShortcutGuideLogs\\shortcut-guide-log.log";
inline const static std::wstring powerOcrLogPath = L"Logs\\text-extractor-log.log";
inline const static std::string keyboardManagerLoggerName = "keyboard-manager";
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt";
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.log";
inline const static std::string findMyMouseLoggerName = "find-my-mouse";
inline const static std::string mouseHighlighterLoggerName = "mouse-highlighter";
inline const static std::string mouseJumpLoggerName = "mouse-jump";
@@ -60,22 +60,22 @@ struct LogSettings
inline const static std::string alwaysOnTopLoggerName = "always-on-top";
inline const static std::string powerOcrLoggerName = "TextExtractor";
inline const static std::string fileLocksmithLoggerName = "FileLocksmith";
inline const static std::wstring alwaysOnTopLogPath = L"always-on-top-log.txt";
inline const static std::wstring alwaysOnTopLogPath = L"always-on-top-log.log";
inline const static std::string hostsLoggerName = "hosts";
inline const static std::wstring hostsLogPath = L"Logs\\hosts-log.txt";
inline const static std::wstring hostsLogPath = L"Logs\\hosts-log.log";
inline const static std::string registryPreviewLoggerName = "registrypreview";
inline const static std::string cropAndLockLoggerName = "crop-and-lock";
inline const static std::wstring registryPreviewLogPath = L"Logs\\registryPreview-log.txt";
inline const static std::wstring registryPreviewLogPath = L"Logs\\registryPreview-log.log";
inline const static std::string environmentVariablesLoggerName = "environment-variables";
inline const static std::wstring cmdNotFoundLogPath = L"Logs\\cmd-not-found-log.txt";
inline const static std::wstring cmdNotFoundLogPath = L"Logs\\cmd-not-found-log.log";
inline const static std::string cmdNotFoundLoggerName = "cmd-not-found";
inline const static std::string newLoggerName = "NewPlus";
inline const static std::string workspacesLauncherLoggerName = "workspaces-launcher";
inline const static std::wstring workspacesLauncherLogPath = L"workspaces-launcher-log.txt";
inline const static std::wstring workspacesLauncherLogPath = L"workspaces-launcher-log.log";
inline const static std::string workspacesWindowArrangerLoggerName = "workspaces-window-arranger";
inline const static std::wstring workspacesWindowArrangerLogPath = L"workspaces-window-arranger-log.txt";
inline const static std::wstring workspacesWindowArrangerLogPath = L"workspaces-window-arranger-log.log";
inline const static std::string workspacesSnapshotToolLoggerName = "workspaces-snapshot-tool";
inline const static std::wstring workspacesSnapshotToolLogPath = L"workspaces-snapshot-tool-log.txt";
inline const static std::wstring workspacesSnapshotToolLogPath = L"workspaces-snapshot-tool-log.log";
inline const static std::string zoomItLoggerName = "zoom-it";
inline const static int retention = 30;
std::wstring logLevel;

View File

@@ -91,7 +91,7 @@ namespace LoggerHelpers
currentFolder.append(get_product_version());
auto logsPath = currentFolder;
logsPath.append(L"log.txt");
logsPath.append(L"log.log");
Logger::init(loggerName, logsPath.wstring(), PTSettingsHelper::get_log_settings_file_location());
delete_other_versions_log_folders(rootFolder.wstring(), currentFolder);

View File

@@ -15,8 +15,6 @@
<ProjectPriFileName>PowerToys.EnvironmentVariablesUILib.pri</ProjectPriFileName>
<GenerateLibraryLayout>true</GenerateLibraryLayout>
<IsPackable>true</IsPackable>
<!-- The default generated file path exceeds the length limit 260 on the build agent. Using a shorter path as a workaround. -->
<CompilerGeneratedFilesOutputPath>$(ProjectDir)obj\g</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<PropertyGroup>
@@ -56,7 +54,4 @@
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<Target Name="EnsureCompilerGeneratedFilesOutputPathExists" BeforeTargets="XamlPreCompile">
<MakeDir Directories="$(CompilerGeneratedFilesOutputPath)" />
</Target>
</Project>

View File

@@ -20,6 +20,9 @@
<ItemGroup>
<PackageReference Include="MSTest" />
<PackageReference Include="System.Net.Http" />
<PackageReference Include="System.Private.Uri" />
<PackageReference Include="System.Text.RegularExpressions" />
<ProjectReference Include="..\..\..\common\UITestAutomation\UITestAutomation.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,3 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View File

@@ -0,0 +1,40 @@
#include <windows.h>
#include "resource.h"
#include "../../../common/version/version.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
1 VERSIONINFO
FILEVERSION FILE_VERSION
PRODUCTVERSION PRODUCT_VERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
BEGIN
VALUE "CompanyName", COMPANY_NAME
VALUE "FileDescription", FILE_DESCRIPTION
VALUE "FileVersion", FILE_VERSION_STRING
VALUE "InternalName", INTERNAL_NAME
VALUE "LegalCopyright", COPYRIGHT_NOTE
VALUE "OriginalFilename", ORIGINAL_FILENAME
VALUE "ProductName", PRODUCT_NAME
VALUE "ProductVersion", PRODUCT_VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
END
END

View File

@@ -0,0 +1,187 @@
<?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>{5f63c743-f6ce-4dba-a200-2b3f8a14e8c2}</ProjectGuid>
<ProjectName>CmdPalKeyboardService</ProjectName>
<RootNamespace>CmdPalKeyboardService</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 Label="UserMacros" />
<PropertyGroup>
<TargetName>CmdPalKeyboardService</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>CmdPalKeyboardService.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="pch.h" />
<ClInclude Include="KeyboardListener.h">
<DependentUpon>KeyboardListener.idl</DependentUpon>
</ClInclude>
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="KeyboardListener.cpp">
<DependentUpon>KeyboardListener.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
</ItemGroup>
<ItemGroup>
<Midl Include="KeyboardListener.idl" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="CmdPalKeyboardService.def" />
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="CmdPalKeyboardService.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
<!-- 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>
</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>

View File

@@ -0,0 +1,36 @@
<?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" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<Midl Include="KeyboardListener.idl" />
</ItemGroup>
<ItemGroup>
<None Include="CmdPalKeyboardService.def" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="CmdPalKeyboardService.rc">
<Filter>Resources</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,165 @@
#include "pch.h"
#include "KeyboardListener.h"
#include "KeyboardListener.g.cpp"
// #include <common/logger/logger.h>
// #include <common/utils/logger_helper.h>
#include <common/utils/winapi_error.h>
namespace
{
}
namespace winrt::CmdPalKeyboardService::implementation
{
KeyboardListener::KeyboardListener()
{
s_instance = this;
}
void KeyboardListener::Start()
{
#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED)
const bool hook_disabled = IsDebuggerPresent();
#else
const bool hook_disabled = false;
#endif
if (!hook_disabled)
{
if (!s_llKeyboardHook)
{
s_llKeyboardHook = SetWindowsHookExW(WH_KEYBOARD_LL, LowLevelKeyboardProc, NULL, NULL);
if (!s_llKeyboardHook)
{
DWORD errorCode = GetLastError();
show_last_error_message(L"SetWindowsHookEx", errorCode, L"CmdPalKeyboardService");
}
}
}
}
void KeyboardListener::Stop()
{
if (s_llKeyboardHook && UnhookWindowsHookEx(s_llKeyboardHook))
{
s_llKeyboardHook = NULL;
}
}
void KeyboardListener::SetHotkeyAction(bool win, bool ctrl, bool shift, bool alt, uint8_t key, hstring const& id)
{
Hotkey hotkey = { .win = win, .ctrl = ctrl, .shift = shift, .alt = alt, .key = key };
std::unique_lock lock{ mutex };
HotkeyDescriptor desc = { .hotkey = hotkey, .id = std::wstring(id) };
hotkeyDescriptors.insert(desc);
}
void KeyboardListener::ClearHotkey(hstring const& id)
{
{
std::unique_lock lock{ mutex };
auto it = hotkeyDescriptors.begin();
while (it != hotkeyDescriptors.end())
{
if (it->id == id)
{
it = hotkeyDescriptors.erase(it);
}
else
{
++it;
}
}
}
}
void KeyboardListener::ClearHotkeys()
{
{
std::unique_lock lock{ mutex };
auto it = hotkeyDescriptors.begin();
while (it != hotkeyDescriptors.end())
{
it = hotkeyDescriptors.erase(it);
}
}
}
void KeyboardListener::SetProcessCommand(ProcessCommand processCommand)
{
m_processCommandCb = [trigger = std::move(processCommand)](hstring const& id) {
trigger(id);
};
}
LRESULT KeyboardListener::DoLowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
const auto& keyPressInfo = *reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
if ((wParam != WM_KEYDOWN) && (wParam != WM_SYSKEYDOWN))
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
Hotkey hotkey{
.win = (GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000),
.ctrl = static_cast<bool>(GetAsyncKeyState(VK_CONTROL) & 0x8000),
.shift = static_cast<bool>(GetAsyncKeyState(VK_SHIFT) & 0x8000),
.alt = static_cast<bool>(GetAsyncKeyState(VK_MENU) & 0x8000),
.key = static_cast<unsigned char>(keyPressInfo.vkCode)
};
if (hotkey == Hotkey{})
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
bool do_action = false;
std::wstring actionId{};
{
// Hold the lock for the shortest possible duration
std::unique_lock lock{ mutex };
HotkeyDescriptor dummy{ .hotkey = hotkey };
auto it = hotkeyDescriptors.find(dummy);
if (it != hotkeyDescriptors.end())
{
do_action = true;
actionId = it->id;
}
}
if (do_action)
{
m_processCommandCb(hstring{ actionId });
// After invoking the hotkey send a dummy key to prevent Start Menu from activating
INPUT dummyEvent[1] = {};
dummyEvent[0].type = INPUT_KEYBOARD;
dummyEvent[0].ki.wVk = 0xFF;
dummyEvent[0].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, dummyEvent, sizeof(INPUT));
// Swallow the key press
return 1;
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
LRESULT KeyboardListener::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (s_instance == nullptr)
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
if (nCode < 0)
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
return s_instance->DoLowLevelKeyboardProc(nCode, wParam, lParam);
}
}

View File

@@ -0,0 +1,67 @@
#pragma once
#include "KeyboardListener.g.h"
#include <mutex>
#include <spdlog/stopwatch.h>
#include <set>
namespace winrt::CmdPalKeyboardService::implementation
{
struct KeyboardListener : KeyboardListenerT<KeyboardListener>
{
struct Hotkey
{
bool win = false;
bool ctrl = false;
bool shift = false;
bool alt = false;
unsigned char key = 0;
std::strong_ordering operator<=>(const Hotkey&) const = default;
};
struct HotkeyDescriptor
{
Hotkey hotkey;
std::wstring id;
bool operator<(const HotkeyDescriptor& other) const
{
return hotkey < other.hotkey;
};
};
KeyboardListener();
void Start();
void Stop();
void SetHotkeyAction(bool win, bool ctrl, bool shift, bool alt, uint8_t key, hstring const& id);
void ClearHotkey(hstring const& id);
void ClearHotkeys();
void SetProcessCommand(ProcessCommand processCommand);
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
private:
LRESULT CALLBACK DoLowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
static inline KeyboardListener* s_instance;
HHOOK s_llKeyboardHook = nullptr;
// Max DWORD for key code to disable keys.
const DWORD VK_DISABLED = 0x100;
DWORD vkCodePressed = VK_DISABLED;
std::multiset<HotkeyDescriptor> hotkeyDescriptors;
std::mutex mutex;
std::function<void(hstring const&)> m_processCommandCb;
};
}
namespace winrt::CmdPalKeyboardService::factory_implementation
{
struct KeyboardListener : KeyboardListenerT<KeyboardListener, implementation::KeyboardListener>
{
};
}

View File

@@ -0,0 +1,16 @@
namespace CmdPalKeyboardService
{
[version(1.0), uuid(78ab07cd-e128-4e73-86aa-e48e6b6d01ff)] delegate void ProcessCommand(String id);
[default_interface] runtimeclass KeyboardListener {
KeyboardListener();
void Start();
void Stop();
void SetHotkeyAction(Boolean win, Boolean ctrl, Boolean shift, Boolean alt, UInt8 key, String id);
void ClearHotkey(String id);
void ClearHotkeys();
void SetProcessCommand(ProcessCommand processCommand);
}
}

View File

@@ -0,0 +1,17 @@
<?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>

View 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>

View File

@@ -0,0 +1 @@
#include "pch.h"

View File

@@ -0,0 +1,4 @@
#pragma once
#include <Unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>

View File

@@ -0,0 +1,13 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by PowerToys.MeasureToolCore.rc
//////////////////////////////
// Non-localizable
#define FILE_DESCRIPTION "CmdPalKeyboardService"
#define INTERNAL_NAME "CmdPalKeyboardService"
#define ORIGINAL_FILENAME "CmdPalKeyboardService.dll"
// Non-localizable
//////////////////////////////

View File

@@ -207,12 +207,16 @@ public:
try
{
if (!package::GetRegisteredPackage(L"Microsoft.CommandPalette", false).has_value())
std::wstring packageName = L"Microsoft.CommandPalette";
#ifdef _DEBUG
packageName = L"Microsoft.CommandPalette.Dev";
#endif
if (!package::GetRegisteredPackage(packageName, false).has_value())
{
Logger::info(L"CmdPal not installed. Installing...");
std::wstring installationFolder = get_module_folderpath();
#if _DEBUG
#ifdef _DEBUG
std::wstring archSubdir = L"x64";
#ifdef _M_ARM64
archSubdir = L"ARM64";

View File

@@ -1,177 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Text;
using Microsoft.CmdPal.Ext.Calc.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation;
namespace Microsoft.CmdPal.Ext.Calc;
public partial class CalculatorCommandProvider : CommandProvider
{
private readonly ListItem _listItem = new(new CalculatorListPage()) { Subtitle = Resources.calculator_top_level_subtitle };
private readonly FallbackCalculatorItem _fallback = new();
public CalculatorCommandProvider()
{
Id = "Calculator";
DisplayName = Resources.calculator_display_name;
Icon = IconHelpers.FromRelativePath("Assets\\Calculator.svg");
}
public override ICommandItem[] TopLevelCommands() => [_listItem];
public override IFallbackCommandItem[] FallbackCommands() => [_fallback];
}
// The calculator page is a dynamic list page
// * The first command is where we display the results. Title=result, Subtitle=query
// - The default command is `SaveCommand`.
// - When you save, insert into list at spot 1
// - change SearchText to the result
// - MoreCommands: a single `CopyCommand` to copy the result to the clipboard
// * The rest of the items are previously saved results
// - Command is a CopyCommand
// - Each item also sets the TextToSuggest to the result
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "This is sample code")]
public sealed partial class CalculatorListPage : DynamicListPage
{
private readonly List<ListItem> _items = [];
private readonly SaveCommand _saveCommand = new();
private readonly CopyTextCommand _copyContextCommand;
private readonly CommandContextItem _copyContextMenuItem;
private static readonly CompositeFormat ErrorMessage = System.Text.CompositeFormat.Parse(Properties.Resources.calculator_error);
public CalculatorListPage()
{
Icon = IconHelpers.FromRelativePath("Assets\\Calculator.svg");
Name = Resources.calculator_title;
PlaceholderText = Resources.calculator_placeholder_text;
Id = "com.microsoft.cmdpal.calculator";
_copyContextCommand = new CopyTextCommand(string.Empty);
_copyContextMenuItem = new CommandContextItem(_copyContextCommand);
_items.Add(new(_saveCommand) { Icon = new IconInfo("\uE94E") });
UpdateSearchText(string.Empty, string.Empty);
_saveCommand.SaveRequested += HandleSave;
}
private void HandleSave(object sender, object args)
{
var lastResult = _items[0].Title;
if (!string.IsNullOrEmpty(lastResult))
{
var li = new ListItem(new CopyTextCommand(lastResult))
{
Title = _items[0].Title,
Subtitle = _items[0].Subtitle,
TextToSuggest = lastResult,
};
_items.Insert(1, li);
_items[0].Subtitle = string.Empty;
SearchText = lastResult;
this.RaiseItemsChanged(this._items.Count);
}
}
public override void UpdateSearchText(string oldSearch, string newSearch)
{
var firstItem = _items[0];
if (string.IsNullOrEmpty(newSearch))
{
firstItem.Title = Resources.calculator_placeholder_text;
firstItem.Subtitle = string.Empty;
firstItem.MoreCommands = [];
}
else
{
_copyContextCommand.Text = ParseQuery(newSearch, out var result) ? result : string.Empty;
firstItem.Title = result;
firstItem.Subtitle = newSearch;
firstItem.MoreCommands = [_copyContextMenuItem];
}
}
internal static bool ParseQuery(string equation, out string result)
{
try
{
var resultNumber = new DataTable().Compute(equation, null);
result = resultNumber.ToString() ?? string.Empty;
return true;
}
catch (Exception e)
{
result = string.Format(CultureInfo.CurrentCulture, ErrorMessage, e.Message);
return false;
}
}
public override IListItem[] GetItems() => _items.ToArray();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "This is sample code")]
public sealed partial class SaveCommand : InvokableCommand
{
public event TypedEventHandler<object, object> SaveRequested;
public SaveCommand()
{
Name = Resources.calculator_save_command_name;
}
public override ICommandResult Invoke()
{
SaveRequested?.Invoke(this, this);
return CommandResult.KeepOpen();
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "This is sample code")]
internal sealed partial class FallbackCalculatorItem : FallbackCommandItem
{
private readonly CopyTextCommand _copyCommand = new(string.Empty);
private static readonly IconInfo _cachedIcon = IconHelpers.FromRelativePath("Assets\\Calculator.svg");
public FallbackCalculatorItem()
: base(new NoOpCommand(), Resources.calculator_title)
{
Command = _copyCommand;
_copyCommand.Name = string.Empty;
Title = string.Empty;
Subtitle = Resources.calculator_placeholder_text;
Icon = _cachedIcon;
}
public override void UpdateQuery(string query)
{
if (CalculatorListPage.ParseQuery(query, out var result))
{
_copyCommand.Text = result;
_copyCommand.Name = string.IsNullOrWhiteSpace(query) ? string.Empty : Resources.calculator_copy_command_name;
Title = result;
// we have to make the subtitle the equation,
// so that we will still string match the original query
// Otherwise, something like 1+2 will have a title of "3" and not match
Subtitle = query;
}
else
{
_copyCommand.Text = string.Empty;
_copyCommand.Name = string.Empty;
Title = string.Empty;
Subtitle = string.Empty;
}
}
}

View File

@@ -1,51 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CmdPal.Ext.System.Helpers;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Ext.System;
public sealed partial class SystemCommandsCache
{
public SystemCommandsCache(SettingsManager manager)
{
var list = new List<IListItem>();
var listLock = new object();
var a = Task.Run(() =>
{
var isBootedInUefiMode = Win32Helpers.GetSystemFirmwareType() == FirmwareType.Uefi;
var separateEmptyRB = manager.HideEmptyRecycleBin;
var confirmSystemCommands = manager.ShowDialogToConfirmCommand;
var showSuccessOnEmptyRB = manager.ShowSuccessMessageAfterEmptyingRecycleBin;
// normal system commands are fast and can be returned immediately
var systemCommands = Commands.GetSystemCommands(isBootedInUefiMode, separateEmptyRB, confirmSystemCommands, showSuccessOnEmptyRB);
lock (listLock)
{
list.AddRange(systemCommands);
}
});
var b = Task.Run(() =>
{
// Network (ip and mac) results are slow with many network cards and returned delayed.
// On global queries the first word/part has to be 'ip', 'mac' or 'address' for network results
var networkConnectionResults = Commands.GetNetworkConnectionResults(manager);
lock (listLock)
{
list.AddRange(networkConnectionResults);
}
});
Task.WaitAll(a, b);
CachedCommands = list.ToArray();
}
public IListItem[] CachedCommands { get; }
}

View File

@@ -1,189 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Globalization;
using System.Text.RegularExpressions;
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
internal static class TimeAndDateHelper
{
/// <summary>
/// Get the format for the time string
/// </summary>
/// <param name="targetFormat">Type of format</param>
/// <param name="timeLong">Show date with weekday and name of month (long format)</param>
/// <param name="dateLong">Show time with seconds (long format)</param>
/// <returns>String that identifies the time/date format (<see href="https://learn.microsoft.com/dotnet/api/system.datetime.tostring"/>)</returns>
internal static string GetStringFormat(FormatStringType targetFormat, bool timeLong, bool dateLong)
{
switch (targetFormat)
{
case FormatStringType.Time:
return timeLong ? "T" : "t";
case FormatStringType.Date:
return dateLong ? "D" : "d";
case FormatStringType.DateTime:
if (timeLong & dateLong)
{
return "F"; // Friday, October 31, 2008 5:04:32 PM
}
else if (timeLong & !dateLong)
{
return "G"; // 10/31/2008 5:04:32 PM
}
else if (!timeLong & dateLong)
{
return "f"; // Friday, October 31, 2008 5:04 PM
}
else
{
// (!timeLong & !dateLong)
return "g"; // 10/31/2008 5:04 PM
}
default:
return string.Empty; // Windows default based on current culture settings
}
}
/// <summary>
/// Returns the number week in the month (Used code from 'David Morton' from <see href="https://social.msdn.microsoft.com/Forums/vstudio/bf504bba-85cb-492d-a8f7-4ccabdf882cb/get-week-number-for-month"/>)
/// </summary>
/// <param name="date">date</param>
/// <returns>Number of week in the month</returns>
internal static int GetWeekOfMonth(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
{
var beginningOfMonth = new DateTime(date.Year, date.Month, 1);
var adjustment = 1; // We count from 1 to 7 and not from 0 to 6
while (date.Date.AddDays(1).DayOfWeek != formatSettingFirstDayOfWeek)
{
date = date.AddDays(1);
}
return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + adjustment;
}
/// <summary>
/// Returns the number of the day in the week
/// </summary>
/// <param name="date">Date</param>
/// <returns>Number of the day in the week</returns>
internal static int GetNumberOfDayInWeek(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
{
var daysInWeek = 7;
var adjustment = 1; // We count from 1 to 7 and not from 0 to 6
return ((date.DayOfWeek + daysInWeek - formatSettingFirstDayOfWeek) % daysInWeek) + adjustment;
}
/// <summary>
/// Convert input string to a <see cref="DateTime"/> object in local time
/// </summary>
/// <param name="input">String with date/time</param>
/// <param name="timestamp">The new <see cref="DateTime"/> object</param>
/// <returns>True on success, otherwise false</returns>
internal static bool ParseStringAsDateTime(in string input, out DateTime timestamp)
{
if (DateTime.TryParse(input, out timestamp))
{
// Known date/time format
return true;
}
else if (Regex.IsMatch(input, @"^u[\+-]?\d{1,10}$") && long.TryParse(input.TrimStart('u'), out var secondsU))
{
// Unix time stamp
// We use long instead of int, because int is too small after 03:14:07 UTC 2038-01-19
timestamp = DateTimeOffset.FromUnixTimeSeconds(secondsU).LocalDateTime;
return true;
}
else if (Regex.IsMatch(input, @"^ums[\+-]?\d{1,13}$") && long.TryParse(input.TrimStart("ums".ToCharArray()), out var millisecondsUms))
{
// Unix time stamp in milliseconds
// We use long instead of int because int is too small after 03:14:07 UTC 2038-01-19
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(millisecondsUms).LocalDateTime;
return true;
}
else if (Regex.IsMatch(input, @"^ft\d+$") && long.TryParse(input.TrimStart("ft".ToCharArray()), out var secondsFt))
{
// Windows file time
// DateTime.FromFileTime returns as local time.
timestamp = DateTime.FromFileTime(secondsFt);
return true;
}
else
{
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
return false;
}
}
/// <summary>
/// Test if input is special parsing for Unix time, Unix time in milliseconds or File time.
/// </summary>
/// <param name="input">String with date/time</param>
/// <returns>True if yes, otherwise false</returns>
internal static bool IsSpecialInputParsing(string input)
{
return Regex.IsMatch(input, @"^.*(u|ums|ft)\d");
}
/// <summary>
/// Returns a CalendarWeekRule enum value based on the plugin setting.
/// </summary>
internal static CalendarWeekRule GetCalendarWeekRule(int pluginSetting)
{
switch (pluginSetting)
{
case 0:
return CalendarWeekRule.FirstDay;
case 1:
return CalendarWeekRule.FirstFullWeek;
case 2:
return CalendarWeekRule.FirstFourDayWeek;
default:
// Wrong json value and system setting (-1).
return DateTimeFormatInfo.CurrentInfo.CalendarWeekRule;
}
}
/// <summary>
/// Returns a DayOfWeek enum value based on the FirstDayOfWeek plugin setting.
/// </summary>
internal static DayOfWeek GetFirstDayOfWeek(int pluginSetting)
{
switch (pluginSetting)
{
case 0:
return DayOfWeek.Sunday;
case 1:
return DayOfWeek.Monday;
case 2:
return DayOfWeek.Tuesday;
case 3:
return DayOfWeek.Wednesday;
case 4:
return DayOfWeek.Thursday;
case 5:
return DayOfWeek.Friday;
case 6:
return DayOfWeek.Saturday;
default:
// Wrong json value and system setting (-1).
return DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;
}
}
}
/// <summary>
/// Type of time/date format
/// </summary>
internal enum FormatStringType
{
Time,
Date,
DateTime,
}

View File

@@ -1,97 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace SamplePagesExtension;
internal sealed partial class SampleListPage : ListPage
{
public SampleListPage()
{
Icon = new IconInfo("\uEA37");
Name = "Sample List Page";
}
public override IListItem[] GetItems()
{
var confirmOnceArgs = new ConfirmationArgs
{
PrimaryCommand = new AnonymousCommand(
() =>
{
var t = new ToastStatusMessage("The dialog was confirmed");
t.Show();
})
{
Name = "Confirm",
Result = CommandResult.KeepOpen(),
},
Title = "You can set a title for the dialog",
Description = "Are you really sure you want to do the thing?",
};
var confirmTwiceArgs = new ConfirmationArgs
{
PrimaryCommand = new AnonymousCommand(() => { })
{
Name = "How sure are you?",
Result = CommandResult.Confirm(confirmOnceArgs),
},
Title = "You can ask twice too",
Description = "You probably don't want to though, that'd be annoying.",
};
return [
new ListItem(new NoOpCommand())
{
Title = "This is a basic item in the list",
Subtitle = "I don't do anything though",
},
new ListItem(new SampleListPageWithDetails())
{
Title = "This item will take you to another page",
Subtitle = "This allows for nested lists of items",
},
new ListItem(new OpenUrlCommand("https://github.com/microsoft/powertoys"))
{
Title = "Or you can go to links",
Subtitle = "This takes you to the PowerToys repo on GitHub",
},
new ListItem(new SampleMarkdownPage())
{
Title = "Items can have tags",
Subtitle = "and I'll take you to a page with markdown content",
Tags = [new Tag("Sample Tag")],
},
new ListItem(new SendMessageCommand())
{
Title = "I send lots of messages",
Subtitle = "Status messages can be used to provide feedback to the user in-app",
},
new SendSingleMessageItem(),
new ListItem(new IndeterminateProgressMessageCommand())
{
Title = "Do a thing with a spinner",
Subtitle = "Messages can have progress spinners, to indicate something is happening in the background",
},
new ListItem(
new AnonymousCommand(() => { })
{
Result = CommandResult.Confirm(confirmOnceArgs),
})
{
Title = "Confirm before doing something",
},
new ListItem(
new AnonymousCommand(() => { })
{
Result = CommandResult.Confirm(confirmTwiceArgs),
})
{
Title = "Confirm twice before doing something",
}
];
}
}

View File

@@ -7,11 +7,15 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.System;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandBarViewModel : ObservableObject,
IRecipient<UpdateCommandBarMessage>
IRecipient<UpdateCommandBarMessage>,
IRecipient<UpdateItemKeybindingsMessage>
{
public ICommandBarContext? SelectedItem
{
@@ -49,13 +53,18 @@ public partial class CommandBarViewModel : ObservableObject,
[ObservableProperty]
public partial ObservableCollection<CommandContextItemViewModel> ContextCommands { get; set; } = [];
private Dictionary<KeyChord, CommandContextItemViewModel>? _contextKeybindings;
public CommandBarViewModel()
{
WeakReferenceMessenger.Default.Register<UpdateCommandBarMessage>(this);
WeakReferenceMessenger.Default.Register<UpdateItemKeybindingsMessage>(this);
}
public void Receive(UpdateCommandBarMessage message) => SelectedItem = message.ViewModel;
public void Receive(UpdateItemKeybindingsMessage message) => _contextKeybindings = message.Keys;
private void SetSelectedItem(ICommandBarContext? value)
{
if (value != null)
@@ -131,4 +140,22 @@ public partial class CommandBarViewModel : ObservableObject,
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(SecondaryCommand.Command.Model, SecondaryCommand.Model));
}
}
public bool CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key)
{
if (_contextKeybindings != null)
{
// Does the pressed key match any of the keybindings?
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
if (_contextKeybindings.TryGetValue(pressedKeyChord, out var item))
{
// TODO GH #245: This is a bit of a hack, but we need to make sure that the keybindings are updated before we send the message
// so that the correct item is activated.
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(item));
return true;
}
}
return false;
}
}

View File

@@ -9,12 +9,16 @@ namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandContextItemViewModel(ICommandContextItem contextItem, WeakReference<IPageContext> context) : CommandItemViewModel(new(contextItem), context)
{
private readonly KeyChord nullKeyChord = new(0, 0, 0);
public new ExtensionObject<ICommandContextItem> Model { get; } = new(contextItem);
public bool IsCritical { get; private set; }
public KeyChord? RequestedShortcut { get; private set; }
public bool HasRequestedShortcut => RequestedShortcut != null && (RequestedShortcut.Value != nullKeyChord);
public override void InitializeProperties()
{
if (IsInitialized)
@@ -31,6 +35,9 @@ public partial class CommandContextItemViewModel(ICommandContextItem contextItem
}
IsCritical = contextItem.IsCritical;
// I actually don't think this will ever actually be null, because
// KeyChord is a struct, which isn't nullable in WinRT
if (contextItem.RequestedShortcut != null)
{
RequestedShortcut = new(

View File

@@ -398,6 +398,23 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
base.SafeCleanup();
Initialized |= InitializedState.CleanedUp;
}
/// <summary>
/// Generates a mapping of key -> command item for this particular item's
/// MoreCommands. (This won't include the primary Command, but it will
/// include the secondary one). This map can be used to quickly check if a
/// shortcut key was pressed
/// </summary>
/// <returns>a dictionary of KeyChord -> Context commands, for all commands
/// that have a shortcut key set.</returns>
internal Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
{
return MoreCommands
.Where(c => c.HasRequestedShortcut)
.ToDictionary(
c => c.RequestedShortcut ?? new KeyChord(0, 0, 0),
c => c);
}
}
[Flags]

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.IO.Compression;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -28,69 +29,69 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
"body": [
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_page_title}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_page_title)}},
"size": "large"
},
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_page_text}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_page_text)}},
"wrap": true
},
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_name_header}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_header)}},
"weight": "bolder",
"size": "default"
},
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_name_description}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_description)}},
"wrap": true
},
{
"type": "Input.Text",
"label": "{{Properties.Resources.builtin_create_extension_name_label}}",
"label": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_label)}},
"isRequired": true,
"errorMessage": "{{Properties.Resources.builtin_create_extension_name_required}}",
"errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_required)}},
"id": "ExtensionName",
"placeholder": "ExtensionName",
"regex": "^[^\\s]+$"
},
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_display_name_header}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_header)}},
"weight": "bolder",
"size": "default"
},
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_display_name_description}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_description)}},
"wrap": true
},
{
"type": "Input.Text",
"label": "{{Properties.Resources.builtin_create_extension_display_name_label}}",
"label": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_label)}},
"isRequired": true,
"errorMessage": "{{Properties.Resources.builtin_create_extension_display_name_required}}",
"errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_required)}},
"id": "DisplayName",
"placeholder": "My new extension"
},
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_directory_header}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_header)}},
"weight": "bolder",
"size": "default"
},
{
"type": "TextBlock",
"text": "{{Properties.Resources.builtin_create_extension_directory_description}}",
"text": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_description)}},
"wrap": true
},
{
"type": "Input.Text",
"label": "{{Properties.Resources.builtin_create_extension_directory_label}}",
"label": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_label)}},
"isRequired": true,
"errorMessage": "{{Properties.Resources.builtin_create_extension_directory_required}}",
"errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_required)}},
"id": "OutputPath",
"placeholder": "C:\\users\\me\\dev"
}
@@ -98,7 +99,7 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
"actions": [
{
"type": "Action.Submit",
"title": "{{Properties.Resources.builtin_create_extension_submit}}",
"title": {{FormatJsonString(Properties.Resources.builtin_create_extension_submit)}},
"associatedInputs": "auto"
}
]
@@ -192,4 +193,10 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase
// Delete the temp dir
Directory.Delete(tempDir, true);
}
private string FormatJsonString(string str)
{
// Escape the string for JSON
return JsonSerializer.Serialize(str);
}
}

View File

@@ -52,6 +52,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
public string SearchText { get; private set; } = string.Empty;
public string InitialSearchText { get; private set; } = string.Empty;
public CommandItemViewModel EmptyContent { get; private set; }
private bool _isDynamic;
@@ -128,7 +130,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
try
{
IListItem[] newItems = _model.Unsafe!.GetItems();
var newItems = _model.Unsafe!.GetItems();
// Collect all the items into new viewmodels
Collection<ListItemViewModel> newViewModels = [];
@@ -136,7 +138,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
// TODO we can probably further optimize this by also keeping a
// HashSet of every ExtensionObject we currently have, and only
// building new viewmodels for the ones we haven't already built.
foreach (IListItem? item in newItems)
foreach (var item in newItems)
{
ListItemViewModel viewModel = new(item, new(this));
@@ -147,8 +149,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
}
}
IEnumerable<ListItemViewModel> firstTwenty = newViewModels.Take(20);
foreach (ListItemViewModel? item in firstTwenty)
var firstTwenty = newViewModels.Take(20);
foreach (var item in firstTwenty)
{
item?.SafeInitializeProperties();
}
@@ -233,7 +235,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
iterable = Items.ToArray();
}
foreach (ListItemViewModel item in iterable)
foreach (var item in iterable)
{
ct.ThrowIfCancellationRequested();
@@ -266,8 +268,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
return 1;
}
MatchResult nameMatch = StringMatcher.FuzzySearch(query, listItem.Title);
MatchResult descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle);
var nameMatch = StringMatcher.FuzzySearch(query, listItem.Title);
var descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle);
return new[] { nameMatch.Score, (descriptionMatch.Score - 4) / 2, 0 }.Max();
}
@@ -280,7 +282,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
// Similarly stolen from ListHelpers.FilterList
public static IEnumerable<ListItemViewModel> FilterList(IEnumerable<ListItemViewModel> items, string query)
{
IOrderedEnumerable<ScoredListItemViewModel> scores = items
var scores = items
.Where(i => !i.IsInErrorState)
.Select(li => new ScoredListItemViewModel() { ViewModel = li, Score = ScoreListItem(query, li) })
.Where(score => score.Score > 0)
@@ -342,6 +344,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
{
WeakReferenceMessenger.Default.Send<UpdateCommandBarMessage>(new(item));
WeakReferenceMessenger.Default.Send<UpdateItemKeybindingsMessage>(new(item.Keybindings()));
if (ShowDetails && item.HasDetails)
{
WeakReferenceMessenger.Default.Send<ShowDetailsMessage>(new(item.Details));
@@ -359,7 +363,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
{
base.InitializeProperties();
IListPage? model = _model.Unsafe;
var model = _model.Unsafe;
if (model == null)
{
return; // throw?
@@ -373,8 +377,9 @@ public partial class ListViewModel : PageViewModel, IDisposable
_modelPlaceholderText = model.PlaceholderText;
UpdateProperty(nameof(PlaceholderText));
SearchText = model.SearchText;
InitialSearchText = SearchText = model.SearchText;
UpdateProperty(nameof(SearchText));
UpdateProperty(nameof(InitialSearchText));
EmptyContent = new(new(model.EmptyContent), PageContext);
EmptyContent.SlowInitializeProperties();
@@ -385,7 +390,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
public void LoadMoreIfNeeded()
{
IListPage? model = this._model.Unsafe;
var model = this._model.Unsafe;
if (model == null)
{
return;
@@ -412,7 +417,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
{
base.FetchProperty(propertyName);
IListPage? model = this._model.Unsafe;
var model = this._model.Unsafe;
if (model == null)
{
return; // throw?
@@ -475,13 +480,13 @@ public partial class ListViewModel : PageViewModel, IDisposable
lock (_listLock)
{
foreach (ListItemViewModel item in Items)
foreach (var item in Items)
{
item.SafeCleanup();
}
Items.Clear();
foreach (ListItemViewModel item in FilteredItems)
foreach (var item in FilteredItems)
{
item.SafeCleanup();
}
@@ -489,7 +494,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
FilteredItems.Clear();
}
IListPage? model = _model.Unsafe;
var model = _model.Unsafe;
if (model != null)
{
model.ItemsChanged -= Model_ItemsChanged;

View File

@@ -51,6 +51,12 @@ public record PerformCommandMessage
Context = context.Unsafe;
}
public PerformCommandMessage(CommandContextItemViewModel contextCommand)
{
Command = contextCommand.Command.Model;
Context = contextCommand.Model.Unsafe;
}
public PerformCommandMessage(ConfirmResultViewModel vm)
{
Command = vm.PrimaryCommand.Model;

View File

@@ -0,0 +1,9 @@
// 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.CommandPalette.Extensions;
namespace Microsoft.CmdPal.UI.ViewModels.Messages;
public record UpdateItemKeybindingsMessage(Dictionary<KeyChord, CommandContextItemViewModel>? Keys);

View File

@@ -31,7 +31,7 @@
<ProjectReference Include="..\Microsoft.CmdPal.Common\Microsoft.CmdPal.Common.csproj" />
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj" />
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />

View File

@@ -26,6 +26,8 @@ public partial class SettingsModel : ObservableObject
public HotkeySettings? Hotkey { get; set; } = DefaultActivationShortcut;
public bool UseLowLevelGlobalHotkey { get; set; }
public bool ShowAppDetails { get; set; }
public bool HotkeyGoesHome { get; set; }
@@ -36,6 +38,8 @@ public partial class SettingsModel : ObservableObject
public bool HighlightSearchOnActivate { get; set; } = true;
public bool ShowSystemTrayIcon { get; set; } = true;
public Dictionary<string, ProviderSettings> ProviderSettings { get; set; } = [];
public Dictionary<string, CommandAlias> Aliases { get; set; } = [];

View File

@@ -27,6 +27,17 @@ public partial class SettingsViewModel : INotifyPropertyChanged
}
}
public bool UseLowLevelGlobalHotkey
{
get => _settings.UseLowLevelGlobalHotkey;
set
{
_settings.UseLowLevelGlobalHotkey = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Hotkey)));
Save();
}
}
public bool ShowAppDetails
{
get => _settings.ShowAppDetails;
@@ -87,6 +98,16 @@ public partial class SettingsViewModel : INotifyPropertyChanged
}
}
public bool ShowSystemTrayIcon
{
get => _settings.ShowSystemTrayIcon;
set
{
_settings.ShowSystemTrayIcon = value;
Save();
}
}
public ObservableCollection<ProviderSettingsViewModel> CommandProviders { get; } = [];
public SettingsViewModel(SettingsModel settings, IServiceProvider serviceProvider, TaskScheduler scheduler)

View File

@@ -152,7 +152,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
{
GenerateId();
UpdateAlias();
FetchAliasFromAliasManager();
UpdateHotkey();
UpdateTags();
}
@@ -163,24 +163,31 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
private void HandleChangeAlias()
{
SetAlias(Alias);
SetAlias();
Save();
}
public void SetAlias(CommandAlias? newAlias)
public void SetAlias()
{
_serviceProvider.GetService<AliasManager>()!.UpdateAlias(Id, newAlias);
UpdateAlias();
var commandAlias = Alias is null
? null
: new CommandAlias(Alias.Alias, Alias.CommandId, Alias.IsDirect);
_serviceProvider.GetService<AliasManager>()!.UpdateAlias(Id, commandAlias);
UpdateTags();
}
private void UpdateAlias()
private void FetchAliasFromAliasManager()
{
// Add tags for the alias, if we have one.
var aliases = _serviceProvider.GetService<AliasManager>();
if (aliases != null)
var am = _serviceProvider.GetService<AliasManager>();
if (am != null)
{
Alias = aliases.AliasFromId(Id);
var commandAlias = am.AliasFromId(Id);
if (commandAlias is not null)
{
// Decouple from the alias manager alias object
Alias = new CommandAlias(commandAlias.Alias, commandAlias.CommandId, commandAlias.IsDirect);
}
}
}

View File

@@ -36,7 +36,7 @@
<!-- Template for actions in the mode actions dropdown button -->
<DataTemplate x:Key="ContextMenuViewModelTemplate" x:DataType="viewmodels:CommandContextItemViewModel">
<Grid>
<Grid AutomationProperties.Name="{x:Bind Title, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32" />
<ColumnDefinition Width="*" />
@@ -53,37 +53,16 @@
Grid.Column="1"
VerticalAlignment="Center"
Text="{x:Bind Title, Mode=OneWay}" />
<!--<TextBlock
<TextBlock
Grid.Column="2"
Margin="16,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Foreground="{ThemeResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind RequestedShortcut, Mode=OneWay, Converter={StaticResource KeyChordToStringConverter}}" />-->
Text="{x:Bind RequestedShortcut, Mode=OneWay, Converter={StaticResource KeyChordToStringConverter}}" />
</Grid>
</DataTemplate>
<animations:ImplicitAnimationSet x:Name="ShowAnimations">
<animations:OpacityAnimation
From="0"
To="1.0"
Duration="0:0:0.340" />
<animations:ScaleAnimation
From="0.85"
To="1"
Duration="0:0:0.350" />
</animations:ImplicitAnimationSet>
<animations:ImplicitAnimationSet x:Name="HideAnimations">
<animations:OpacityAnimation
From="1.0"
To="0"
Duration="0:0:0.240" />
<animations:ScaleAnimation
From="1"
To="0.85"
Duration="0:0:0.350" />
</animations:ImplicitAnimationSet>
</ResourceDictionary>
</UserControl.Resources>
@@ -135,9 +114,6 @@
<Button
x:Name="SettingsIconButton"
x:Uid="SettingsButton"
animations:Implicit.HideAnimations="{StaticResource HideAnimations}"
animations:Implicit.ShowAnimations="{StaticResource ShowAnimations}"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
Style="{StaticResource SubtleButtonStyle}"
Tapped="SettingsIcon_Tapped"
Visibility="{x:Bind CurrentPageViewModel.IsNested, Mode=OneWay, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
@@ -167,10 +143,8 @@
<Button
x:Name="PrimaryButton"
Padding="6,4,4,4"
animations:Implicit.HideAnimations="{StaticResource HideAnimations}"
animations:Implicit.ShowAnimations="{StaticResource ShowAnimations}"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
x:Load="{x:Bind IsLoaded, Mode=OneWay}"
AutomationProperties.Name="{x:Bind ViewModel.PrimaryCommand.Name, Mode=OneWay}"
Background="Transparent"
Style="{StaticResource SubtleButtonStyle}"
Tapped="PrimaryButton_Tapped"
@@ -198,10 +172,8 @@
<Button
x:Name="SecondaryButton"
Padding="6,4,4,4"
animations:Implicit.HideAnimations="{StaticResource HideAnimations}"
animations:Implicit.ShowAnimations="{StaticResource ShowAnimations}"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
x:Load="{x:Bind IsLoaded, Mode=OneWay}"
AutomationProperties.Name="{x:Bind ViewModel.SecondaryCommand.Name, Mode=OneWay}"
Style="{StaticResource SubtleButtonStyle}"
Tapped="SecondaryButton_Tapped"
Visibility="{x:Bind ViewModel.HasSecondaryCommand, Mode=OneWay}">
@@ -245,13 +217,10 @@
x:Name="MoreCommandsButton"
x:Uid="MoreCommandsButton"
Padding="4"
animations:Implicit.HideAnimations="{StaticResource HideAnimations}"
animations:Implicit.ShowAnimations="{StaticResource ShowAnimations}"
ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5"
Content="{ui:FontIcon Glyph=&#xE712;,
FontSize=16}"
Style="{StaticResource SubtleButtonStyle}"
ToolTipService.ToolTip="Ctrl+k"
ToolTipService.ToolTip="Ctrl+K"
Visibility="{x:Bind ViewModel.ShouldShowContextMenu, Mode=OneWay}">
<Button.Flyout>
<Flyout Placement="TopEdgeAlignedRight">
@@ -263,6 +232,7 @@
ItemClick="CommandsDropdown_ItemClick"
ItemTemplate="{StaticResource ContextMenuViewModelTemplate}"
ItemsSource="{x:Bind ViewModel.ContextCommands, Mode=OneWay}"
KeyDown="CommandsDropdown_KeyDown"
SelectionMode="None">
<ListView.ItemContainerStyle>
<Style BasedOn="{StaticResource DefaultListViewItemStyle}" TargetType="ListViewItem">

View File

@@ -6,10 +6,13 @@ using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.Views;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Input;
using Windows.System;
using Windows.UI.Core;
namespace Microsoft.CmdPal.UI.Controls;
@@ -89,4 +92,23 @@ public sealed partial class CommandBar : UserControl,
MoreCommandsButton.Flyout.Hide();
}
}
private void CommandsDropdown_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Handled)
{
return;
}
var ctrlPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down);
var altPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down);
var shiftPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down);
var winPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.LeftWindows).HasFlag(CoreVirtualKeyStates.Down) ||
InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.RightWindows).HasFlag(CoreVirtualKeyStates.Down);
if (ViewModel?.CheckKeybinding(ctrlPressed, altPressed, shiftPressed, winPressed, e.Key) ?? false)
{
e.Handled = true;
}
}
}

View File

@@ -8,6 +8,8 @@ using CommunityToolkit.WinUI;
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.Views;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
@@ -21,6 +23,7 @@ namespace Microsoft.CmdPal.UI.Controls;
public sealed partial class SearchBar : UserControl,
IRecipient<GoHomeMessage>,
IRecipient<FocusSearchBoxMessage>,
IRecipient<UpdateItemKeybindingsMessage>,
ICurrentPageAware
{
private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread();
@@ -31,6 +34,8 @@ public sealed partial class SearchBar : UserControl,
private readonly DispatcherQueueTimer _debounceTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
private bool _isBackspaceHeld;
private Dictionary<KeyChord, CommandContextItemViewModel>? _keyBindings;
public PageViewModel? CurrentPageViewModel
{
get => (PageViewModel?)GetValue(CurrentPageViewModelProperty);
@@ -69,6 +74,7 @@ public sealed partial class SearchBar : UserControl,
this.InitializeComponent();
WeakReferenceMessenger.Default.Register<GoHomeMessage>(this);
WeakReferenceMessenger.Default.Register<FocusSearchBoxMessage>(this);
WeakReferenceMessenger.Default.Register<UpdateItemKeybindingsMessage>(this);
}
public void ClearSearch()
@@ -105,7 +111,9 @@ public sealed partial class SearchBar : UserControl,
var ctrlPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down);
var altPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down);
var shiftPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down);
var winPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.LeftWindows).HasFlag(CoreVirtualKeyStates.Down) ||
InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.RightWindows).HasFlag(CoreVirtualKeyStates.Down);
if (ctrlPressed && e.Key == VirtualKey.Enter)
{
// ctrl+enter
@@ -164,6 +172,19 @@ public sealed partial class SearchBar : UserControl,
{
WeakReferenceMessenger.Default.Send<NavigateBackMessage>(new());
}
if (_keyBindings != null)
{
// Does the pressed key match any of the keybindings?
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrlPressed, altPressed, shiftPressed, winPressed, (int)e.Key, 0);
if (_keyBindings.TryGetValue(pressedKeyChord, out var item))
{
// TODO GH #245: This is a bit of a hack, but we need to make sure that the keybindings are updated before we send the message
// so that the correct item is activated.
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(item));
e.Handled = true;
}
}
}
private void FilterBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
@@ -250,18 +271,31 @@ public sealed partial class SearchBar : UserControl,
private void Page_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var property = e.PropertyName;
if (CurrentPageViewModel is ListViewModel list &&
property == nameof(ListViewModel.SearchText))
{
// Only if the text actually changed...
// (sometimes this triggers on a round-trip of the SearchText)
if (FilterBox.Text != list.SearchText)
{
// ... Update our displayed text, and...
FilterBox.Text = list.SearchText;
// ... Move the cursor to the end of the input
FilterBox.Select(FilterBox.Text.Length, 0);
if (CurrentPageViewModel is ListViewModel list)
{
if (property == nameof(ListViewModel.SearchText))
{
// Only if the text actually changed...
// (sometimes this triggers on a round-trip of the SearchText)
if (FilterBox.Text != list.SearchText)
{
// ... Update our displayed text, and...
FilterBox.Text = list.SearchText;
// ... Move the cursor to the end of the input
FilterBox.Select(FilterBox.Text.Length, 0);
}
}
else if (property == nameof(ListViewModel.InitialSearchText))
{
// GH #38712:
// The ListPage will notify us of the `InitialSearchText` when
// we first load the viewmodel. We can use that as an
// opportunity to immediately select the search text. That lets
// the user start typing a new search without manually
// selecting the old one.
SelectSearch();
}
}
}
@@ -269,4 +303,9 @@ public sealed partial class SearchBar : UserControl,
public void Receive(GoHomeMessage message) => ClearSearch();
public void Receive(FocusSearchBoxMessage message) => this.Focus(Microsoft.UI.Xaml.FocusState.Programmatic);
public void Receive(UpdateItemKeybindingsMessage message)
{
_keyBindings = message.Keys;
}
}

View File

@@ -38,6 +38,7 @@
<Setter Property="IsTabStop" Value="False" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="AutomationProperties.AutomationControlType" Value="Custom" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Padding" Value="{ThemeResource TagPadding}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
@@ -56,6 +57,7 @@
Padding="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
AutomationProperties.Name="{TemplateBinding Text}"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"

View File

@@ -28,21 +28,22 @@
NotEmptyValue="Visible" />
<DataTemplate x:Key="TagTemplate" x:DataType="viewmodels:TagViewModel">
<ItemContainer>
<cpcontrols:Tag
BackgroundColor="{x:Bind Background, Mode=OneWay}"
FontSize="12"
ForegroundColor="{x:Bind Foreground, Mode=OneWay}"
Icon="{x:Bind Icon, Mode=OneWay}"
Text="{x:Bind Text, Mode=OneWay}"
ToolTipService.ToolTip="{x:Bind ToolTip, Mode=OneWay}" />
</ItemContainer>
<cpcontrols:Tag
AutomationProperties.Name="{x:Bind Text, Mode=OneWay}"
BackgroundColor="{x:Bind Background, Mode=OneWay}"
FontSize="12"
ForegroundColor="{x:Bind Foreground, Mode=OneWay}"
Icon="{x:Bind Icon, Mode=OneWay}"
Text="{x:Bind Text, Mode=OneWay}"
ToolTipService.ToolTip="{x:Bind ToolTip, Mode=OneWay}" />
</DataTemplate>
<!-- https://learn.microsoft.com/windows/apps/design/controls/itemsview#specify-the-look-of-the-items -->
<DataTemplate x:Key="ListItemViewModelTemplate" x:DataType="viewmodels:ListItemViewModel">
<Grid Padding="0,12,0,12" ColumnSpacing="12">
<Grid
Padding="0,12,0,12"
AutomationProperties.Name="{x:Bind Title, Mode=OneWay}"
ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="28" />
<ColumnDefinition Width="*" />
@@ -55,6 +56,7 @@
Width="20"
Height="20"
Margin="4,0,4,0"
AutomationProperties.AccessibilityView="Raw"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
SourceKey="{x:Bind Icon, Mode=OneWay}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}" />

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Runtime.InteropServices;
using CmdPalKeyboardService;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Common.Helpers;
using Microsoft.CmdPal.Common.Messages;
@@ -52,9 +53,10 @@ public sealed partial class MainWindow : Window,
#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 bool _createdIcon;
private DestroyIconSafeHandle? _largeIcon;
private DesktopAcrylicController? _acrylicController;
@@ -67,6 +69,11 @@ public sealed partial class MainWindow : Window,
_hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32());
CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
_keyboardListener = new KeyboardListener();
_keyboardListener.Start();
_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
@@ -99,7 +106,6 @@ public sealed partial class MainWindow : Window,
_hotkeyWndProc = HotKeyPrc;
var hotKeyPrcPointer = Marshal.GetFunctionPointerForDelegate(_hotkeyWndProc);
_originalWndProc = Marshal.GetDelegateForFunctionPointer<WNDPROC>(PInvoke.SetWindowLongPtr(_hwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, hotKeyPrcPointer));
AddNotificationIcon();
// Load our settings, and then also wire up a settings changed handler
HotReloadSettings();
@@ -149,6 +155,7 @@ public sealed partial class MainWindow : Window,
var settings = App.Current.Services.GetService<SettingsModel>()!;
SetupHotkey(settings);
SetupTrayIcon(settings.ShowSystemTrayIcon);
// This will prevent our window from appearing in alt+tab or the taskbar.
// You'll _need_ to use the hotkey to summon it.
@@ -279,16 +286,12 @@ public sealed partial class MainWindow : Window,
ShowHwnd(message.Hwnd, settings.SummonOn);
}
public void Receive(HideWindowMessage message)
{
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
}
public void Receive(HideWindowMessage message) => PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
public void Receive(QuitMessage message) =>
public void Receive(QuitMessage message)
{
// This might come in on a background thread
DispatcherQueue.TryEnqueue(() => Close());
}
public void Receive(DismissMessage message) =>
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
@@ -299,12 +302,14 @@ public sealed partial class MainWindow : Window,
var extensionService = serviceProvider.GetService<IExtensionService>()!;
extensionService.SignalStopExtensionsAsync();
RemoveNotificationIcon();
RemoveTrayIcon();
// WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592).
// Workaround by turning it off before shutdown.
App.Current.DebugSettings.FailFastOnErrors = false;
DisposeAcrylic();
_keyboardListener.Stop();
}
private void DisposeAcrylic()
@@ -369,12 +374,17 @@ public sealed partial class MainWindow : Window,
// ... then don't hide the window when it loses focus.
return;
}
else
{
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnLostFocus());
// Are we disabled? If we are, then we don't want to dismiss on focus lost.
// This can happen if an extension wanted to show a modal dialog on top of our
// window i.e. in the case of an MSAL auth window.
if (PInvoke.IsWindowEnabled(_hwnd) == 0)
{
return;
}
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnLostFocus());
}
if (_configurationSource != null)
@@ -383,14 +393,13 @@ public sealed partial class MainWindow : Window,
}
}
public void Summon(string commandId)
{
public void Summon(string commandId) =>
// The actual showing and hiding of the window will be done by the
// ShellPage. This is because we don't want to show the window if the
// user bound a hotkey to just an invokable command, which we can't
// know till the message is being handled.
WeakReferenceMessenger.Default.Send<HotkeySummonMessage>(new(commandId, _hwnd));
}
#pragma warning disable SA1310 // Field names should not contain underscore
private const uint DOT_KEY = 0xBE;
@@ -399,6 +408,8 @@ public sealed partial class MainWindow : Window,
private void UnregisterHotkeys()
{
_keyboardListener.ClearHotkeys();
while (_hotkeys.Count > 0)
{
PInvoke.UnregisterHotKey(_hwnd, _hotkeys.Count - 1);
@@ -413,19 +424,28 @@ public sealed partial class MainWindow : Window,
var globalHotkey = settings.Hotkey;
if (globalHotkey != null)
{
var vk = globalHotkey.Code;
var modifiers =
(globalHotkey.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
(globalHotkey.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
(globalHotkey.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
(globalHotkey.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
;
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
if (success)
if (settings.UseLowLevelGlobalHotkey)
{
_keyboardListener.SetHotkeyAction(globalHotkey.Win, globalHotkey.Ctrl, globalHotkey.Shift, globalHotkey.Alt, (byte)globalHotkey.Code, string.Empty);
_hotkeys.Add(new(globalHotkey, string.Empty));
}
else
{
var vk = globalHotkey.Code;
var modifiers =
(globalHotkey.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) |
(globalHotkey.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) |
(globalHotkey.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) |
(globalHotkey.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0)
;
var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk);
if (success)
{
_hotkeys.Add(new(globalHotkey, string.Empty));
}
}
}
foreach (var commandHotkey in settings.CommandHotkeys)
@@ -451,6 +471,26 @@ public sealed partial class MainWindow : Window,
}
}
private void HandleSummon(string commandId)
{
var isRootHotkey = string.IsNullOrEmpty(commandId);
PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey));
// Note to future us: the wParam will have the index of the hotkey we registered.
// We can use that in the future to differentiate the hotkeys we've pressed
// so that we can bind hotkeys to individual commands
if (!this.Visible || !isRootHotkey)
{
Activate();
Summon(commandId);
}
else if (isRootHotkey)
{
PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE);
}
}
private LRESULT HotKeyPrc(
HWND hwnd,
uint uMsg,
@@ -465,22 +505,23 @@ public sealed partial class MainWindow : Window,
if (hotkeyIndex < _hotkeys.Count)
{
var hotkey = _hotkeys[hotkeyIndex];
var isRootHotkey = string.IsNullOrEmpty(hotkey.CommandId);
PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey));
HandleSummon(hotkey.CommandId);
// Note to future us: the wParam will have the index of the hotkey we registered.
// We can use that in the future to differentiate the hotkeys we've pressed
// so that we can bind hotkeys to individual commands
if (!this.Visible || !isRootHotkey)
{
Activate();
// var isRootHotkey = string.IsNullOrEmpty(hotkey.CommandId);
Summon(hotkey.CommandId);
}
else if (isRootHotkey)
{
PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_HIDE);
}
// // Note to future us: the wParam will have the index of the hotkey we registered.
// // We can use that in the future to differentiate the hotkeys we've pressed
// // so that we can bind hotkeys to individual commands
// if (!this.Visible || !isRootHotkey)
// {
// Activate();
// Summon(hotkey.CommandId);
// }
// else if (isRootHotkey)
// {
// PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_HIDE);
// }
}
return (LRESULT)IntPtr.Zero;
@@ -491,9 +532,9 @@ public sealed partial class MainWindow : Window,
// WM_WINDOWPOSCHANGING which is always received on explorer startup sequence.
case PInvoke.WM_WINDOWPOSCHANGING:
{
if (!_createdIcon)
if (_trayIconData == null)
{
AddNotificationIcon();
SetupTrayIcon();
}
}
@@ -505,7 +546,7 @@ public sealed partial class MainWindow : Window,
{
// Handle the case where explorer.exe restarts.
// Even if we created it before, do it again
AddNotificationIcon();
SetupTrayIcon();
}
else if (uMsg == WM_TRAY_ICON)
{
@@ -525,55 +566,60 @@ public sealed partial class MainWindow : Window,
return PInvoke.CallWindowProc(_originalWndProc, hwnd, uMsg, wParam, lParam);
}
private void AddNotificationIcon()
private void SetupTrayIcon(bool? showSystemTrayIcon = null)
{
// We only need to build the tray data once.
if (_trayIconData == null)
if (showSystemTrayIcon ?? App.Current.Services.GetService<SettingsModel>()!.ShowSystemTrayIcon)
{
// 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()
// We only need to build the tray data once.
if (_trayIconData == null)
{
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"),
};
// 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);
}
var d = (NOTIFYICONDATAW)_trayIconData;
// Add the notification icon
if (PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_ADD, in d))
else
{
_createdIcon = true;
RemoveTrayIcon();
}
}
private void RemoveNotificationIcon()
private void RemoveTrayIcon()
{
if (_trayIconData != null && _createdIcon)
if (_trayIconData != null)
{
var d = (NOTIFYICONDATAW)_trayIconData;
if (PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_DELETE, in d))
{
_createdIcon = false;
_trayIconData = null;
}
}
_largeIcon?.Close();
}
private DestroyIconSafeHandle GetAppIconHandle()
{
var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
DestroyIconSafeHandle largeIcon;
DestroyIconSafeHandle smallIcon;
PInvoke.ExtractIconEx(exePath, 0, out largeIcon, out smallIcon, 1);
PInvoke.ExtractIconEx(exePath, 0, out largeIcon, out _, 1);
return largeIcon;
}
}

View File

@@ -23,13 +23,13 @@
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(CIBuild)'=='true'">
<PropertyGroup>
<GenerateAppxPackageOnBuild>true</GenerateAppxPackageOnBuild>
</PropertyGroup>
<PropertyGroup>
<!-- This lets us actually reference types from Microsoft.Terminal.UI -->
<CsWinRTIncludes>Microsoft.Terminal.UI</CsWinRTIncludes>
<CsWinRTIncludes>Microsoft.Terminal.UI;CmdPalKeyboardService</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
</PropertyGroup>
@@ -73,12 +73,17 @@
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="System.Net.Http" />
<PackageReference Include="System.Private.Uri" />
<PackageReference Include="System.Text.Json" />
<!-- LOAD BEARING: GeneratePathProperty=true on BOTH the AC dependencies. Don't forget the AdaptiveCardsWorkaround below -->
<PackageReference Include="AdaptiveCards.ObjectModel.WinUI3" GeneratePathProperty="true" />
<PackageReference Include="AdaptiveCards.Rendering.WinUI3" GeneratePathProperty="True" />
<PackageReference Include="AdaptiveCards.Templating" />
<PackageReference Include="System.Text.RegularExpressions" />
</ItemGroup>
<!--
@@ -92,32 +97,38 @@
<ItemGroup>
<ProjectReference Include="..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj" />
<ProjectReference Include="..\Microsoft.CmdPal.Common\Microsoft.CmdPal.Common.csproj" />
<ProjectReference Include="..\Microsoft.CmdPal.UI.ViewModels\Microsoft.CmdPal.UI.ViewModels.csproj" />
<ProjectReference Include="..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj" />
<ProjectReference Include="..\Exts\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj" />
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj" />
<ProjectReference Include="..\Microsoft.Terminal.UI\Microsoft.Terminal.UI.vcxproj">
<ReferenceOutputAssembly>True</ReferenceOutputAssembly>
<Private>True</Private>
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
</ProjectReference>
<ProjectReference Include="..\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj">
<ReferenceOutputAssembly>True</ReferenceOutputAssembly>
<Private>True</Private>
<CopyLocalSatelliteAssemblies>True</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<ItemGroup>

View File

@@ -15,6 +15,7 @@ CallWindowProc
ShowWindow
SetForegroundWindow
EnableWindow
IsWindowEnabled
SetFocus
SetActiveWindow
MonitorFromWindow

View File

@@ -41,6 +41,7 @@
<DataTemplate x:Key="TagTemplate" x:DataType="viewModels:TagViewModel">
<cpcontrols:Tag
HorizontalAlignment="Left"
AutomationProperties.Name="{x:Bind Text, Mode=OneWay}"
BackgroundColor="{x:Bind Background, Mode=OneWay}"
FontSize="12"
ForegroundColor="{x:Bind Foreground, Mode=OneWay}"
@@ -147,27 +148,36 @@
Visibility="{x:Bind ViewModel.CurrentPage.IsNested, Mode=OneWay, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
<animations:Implicit.ShowAnimations>
<animations:OpacityAnimation
EasingMode="EaseIn"
EasingType="Cubic"
From="0"
To="1.0"
Duration="0:0:0.340" />
Duration="0:0:0.187" />
<animations:ScaleAnimation
EasingMode="EaseIn"
EasingType="Cubic"
From="0.5"
To="1"
Duration="0:0:0.350" />
Duration="0:0:0.187" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1.0"
To="0"
Duration="0:0:0.240" />
Duration="0:0:0.187" />
<animations:ScaleAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1"
To="0.5"
Duration="0:0:0.350" />
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
</Image>
<Button
x:Name="BackButton"
x:Uid="BackButton"
Margin="4,0,4,0"
Padding="4"
HorizontalAlignment="Center"
@@ -178,35 +188,42 @@
FontSize="16"
Style="{StaticResource SubtleButtonStyle}"
Tapped="BackButton_Tapped"
ToolTipService.ToolTip="Back"
Visibility="{x:Bind ViewModel.CurrentPage.IsNested, Mode=OneWay}">
<animations:Implicit.ShowAnimations>
<animations:OpacityAnimation
EasingMode="EaseIn"
EasingType="Cubic"
From="0"
To="1.0"
Duration="0:0:0.340" />
Duration="0:0:0.333" />
<animations:ScaleAnimation
From="0.5"
To="1"
Duration="0:0:0.350" />
Duration="0:0:0.333" />
<animations:TranslationAnimation
From="16,0,0"
To="0,0,0"
Duration="0:0:0.350" />
Duration="0:0:0.333" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1.0"
To="0"
Duration="0:0:0.340" />
Duration="0:0:0.333" />
<animations:ScaleAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="1"
To="0.5"
Duration="0:0:0.350" />
Duration="0:0:0.333" />
<animations:TranslationAnimation
EasingMode="EaseOut"
EasingType="Cubic"
From="0,0,0"
To="16,0,0"
Duration="0:0:0.350" />
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
</Button>
<cpcontrols:IconBox
@@ -223,29 +240,29 @@
<animations:OpacityAnimation
From="0"
To="1.0"
Duration="0:0:0.450" />
Duration="0:0:0.333" />
<animations:ScaleAnimation
From="0.8"
To="1"
Duration="0:0:0.500" />
Duration="0:0:0.333" />
<animations:TranslationAnimation
From="8,0,0"
To="0,0,0"
Duration="0:0:0.400" />
Duration="0:0:0.187" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
From="1.0"
To="0"
Duration="0:0:0.340" />
Duration="0:0:0.333" />
<animations:ScaleAnimation
From="1"
To="0.8"
Duration="0:0:0.350" />
Duration="0:0:0.333" />
<animations:TranslationAnimation
From="0,0,0"
To="8,0,0"
Duration="0:0:0.350" />
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
</cpcontrols:IconBox>
</StackPanel>
@@ -272,13 +289,13 @@
<animations:OpacityAnimation
From="0"
To="1.0"
Duration="0:0:0.340" />
Duration="0:0:0.333" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
From="1.0"
To="0"
Duration="0:0:0.340" />
Duration="0:0:0.333" />
</animations:Implicit.HideAnimations>
</ProgressBar>
@@ -313,21 +330,21 @@
<animations:OpacityAnimation
From="0"
To="1.0"
Duration="0:0:0.270" />
Duration="0:0:0.187" />
<animations:TranslationAnimation
From="24,0,0"
To="0,0,0"
Duration="0:0:0.280" />
Duration="0:0:0.187" />
</animations:Implicit.ShowAnimations>
<animations:Implicit.HideAnimations>
<animations:OpacityAnimation
From="1.0"
To="0"
Duration="0:0:0.180" />
Duration="0:0:0.187" />
<animations:TranslationAnimation
From="0,0,0"
To="24,0,0"
Duration="0:0:0.220" />
Duration="0:0:0.187" />
</animations:Implicit.HideAnimations>
<Grid Margin="12">
<Grid.RowDefinitions>
@@ -343,6 +360,7 @@
MinHeight="64"
MaxHeight="96"
HorizontalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
SourceKey="{x:Bind ViewModel.Details.HeroImage, Mode=OneWay}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}"
Visibility="{x:Bind HasHeroImage, Mode=OneWay}" />

View File

@@ -187,6 +187,8 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
WeakReferenceMessenger.Default.Send<UpdateCommandBarMessage>(new(null));
WeakReferenceMessenger.Default.Send<UpdateItemKeybindingsMessage>(new(null));
var isMainPage = command is MainListPage;
// Construct our ViewModel of the appropriate type and pass it the UI Thread context.
@@ -427,8 +429,6 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
}
_settingsWindow.Activate();
WeakReferenceMessenger.Default.Send<UpdateCommandBarMessage>(new(null));
});
}

View File

@@ -36,9 +36,18 @@
<TextBlock x:Uid="ActivationSettingsHeader" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
<controls:SettingsCard x:Uid="Settings_GeneralPage_ActivationKey_SettingsExpander" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">
<controls:SettingsExpander
x:Uid="Settings_GeneralPage_ActivationKey_SettingsExpander"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}"
IsExpanded="True">
<ptControls:ShortcutControl HotkeySettings="{x:Bind viewModel.Hotkey, Mode=TwoWay}" />
</controls:SettingsCard>
<controls:SettingsExpander.Items>
<controls:SettingsCard x:Uid="Settings_GeneralPage_LowLevelHook_SettingsCard">
<ToggleSwitch IsOn="{x:Bind viewModel.UseLowLevelGlobalHotkey, Mode=TwoWay}" />
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<controls:SettingsCard x:Uid="Settings_GeneralPage_GoHome_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=&#xE80F;}">
<ToggleSwitch IsOn="{x:Bind viewModel.HotkeyGoesHome, Mode=TwoWay}" />
</controls:SettingsCard>
@@ -68,6 +77,10 @@
<ToggleSwitch IsOn="{x:Bind viewModel.SingleClickActivates, Mode=TwoWay}" />
</controls:SettingsCard>
<controls:SettingsCard x:Uid="Settings_GeneralPage_ShowSystemTrayIcon_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=&#xE75B;}">
<ToggleSwitch IsOn="{x:Bind viewModel.ShowSystemTrayIcon, Mode=TwoWay}" />
</controls:SettingsCard>
<!-- Example 'About' section -->
<TextBlock x:Uid="AboutSettingsHeader" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />

View File

@@ -322,6 +322,12 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
<data name="Settings_GeneralPage_ActivationKey_SettingsExpander.Description" xml:space="preserve">
<value>This key will open the Command Palette.</value>
</data>
<data name="Settings_GeneralPage_LowLevelHook_SettingsCard.Header" xml:space="preserve">
<value>Use low-level keyboard hook</value>
</data>
<data name="Settings_GeneralPage_LowLevelHook_SettingsCard.Description" xml:space="preserve">
<value>Try this if there are issues with the shortcut (Command Palette might not get focus when triggered from an elevated window)</value>
</data>
<data name="Settings_GeneralPage_GoHome_SettingsCard.Header" xml:space="preserve">
<value>Go home when activated</value>
</data>
@@ -373,9 +379,6 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
<data name="Settings_GeneralPage_NavigationViewItem_Extensions.Content" xml:space="preserve">
<value>Extensions</value>
</data>
<data name="MoreCommandsButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>More commands</value>
</data>
<data name="SettingsButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Open Command Palette settings</value>
</data>
@@ -385,4 +388,19 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
<data name="BehaviorSettingsHeader.Text" xml:space="preserve">
<value>Behavior</value>
</data>
<data name="Settings_GeneralPage_ShowSystemTrayIcon_SettingsCard.Header" xml:space="preserve">
<value>Show system tray icon</value>
</data>
<data name="Settings_GeneralPage_ShowSystemTrayIcon_SettingsCard.Description" xml:space="preserve">
<value>Choose if Command Palette is visible in the system tray</value>
</data>
<data name="BackButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Back</value>
</data>
<data name="BackButton.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Back</value>
</data>
<data name="MoreCommandsButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>More</value>
</data>
</root>

View File

@@ -40,7 +40,7 @@ Projects of interest are:
[Initial SDK Spec]: ./doc/initial-sdk-spec/initial-sdk-spec.md
[generic samples]: ./Exts/SamplePagesExtension
[real samples]: .Exts/ProcessMonitorExtension
[real samples]: ./Exts/ProcessMonitorExtension
[real extensions that we've "shipped" already]: https://github.com/zadjii/CmdPalExtensions/blob/main/src/extensions

View File

@@ -152,7 +152,7 @@ We've made it easy to build a new extension. Just follow these steps:
2. Run the following PowerShell script, replacing "MastodonExtension" with the `Name` of your extension and "Mastodon extension for cmdpal" with the `DisplayName` of the [command that will show up in the root view](#root-view) of the Command Palette:
```powershell
.\Exts\NewExtension.ps1 -name MastodonExtension -DisplayName "Mastodon extension for cmdpal"
.\ext\NewExtension.ps1 -name MastodonExtension -DisplayName "Mastodon extension for cmdpal"
```
3. Open the solution in Visual Studio.

View File

@@ -57,7 +57,7 @@ public sealed partial class AllAppsPage : ListPage
Stopwatch stopwatch = new();
stopwatch.Start();
List<AppItem> apps = GetPrograms();
var apps = GetPrograms();
this.allAppsSection = apps
.Select((app) => new AppListItem(app, true))
@@ -73,26 +73,15 @@ public sealed partial class AllAppsPage : ListPage
internal List<AppItem> GetPrograms()
{
IEnumerable<AppItem> uwpResults = AppCache.Instance.Value.UWPs
var uwpResults = AppCache.Instance.Value.UWPs
.Where((application) => application.Enabled)
.Select(app =>
new AppItem()
{
Name = app.Name,
Subtitle = app.Description,
Type = UWPApplication.Type(),
IcoPath = app.LogoType != LogoType.Error ? app.LogoPath : string.Empty,
DirPath = app.Location,
UserModelId = app.UserModelId,
IsPackaged = true,
Commands = app.GetCommands(),
});
.Select(UwpToAppItem);
IEnumerable<AppItem> win32Results = AppCache.Instance.Value.Win32s
var win32Results = AppCache.Instance.Value.Win32s
.Where((application) => application.Enabled && application.Valid)
.Select(app =>
{
string icoPath = string.IsNullOrEmpty(app.IcoPath) ?
var icoPath = string.IsNullOrEmpty(app.IcoPath) ?
(app.AppType == Win32Program.ApplicationType.InternetShortcutApplication ?
app.IcoPath :
app.FullPath) :
@@ -116,4 +105,21 @@ public sealed partial class AllAppsPage : ListPage
return uwpResults.Concat(win32Results).OrderBy(app => app.Name).ToList();
}
private AppItem UwpToAppItem(UWPApplication app)
{
var iconPath = app.LogoType != LogoType.Error ? app.LogoPath : string.Empty;
var item = new AppItem()
{
Name = app.Name,
Subtitle = app.Description,
Type = UWPApplication.Type(),
IcoPath = iconPath,
DirPath = app.Location,
UserModelId = app.UserModelId,
IsPackaged = true,
Commands = app.GetCommands(),
};
return item;
}
}

View File

@@ -32,7 +32,13 @@ internal sealed partial class AppListItem : ListItem
Tags = [_appTag];
MoreCommands = _app.Commands!.ToArray();
_details = new Lazy<Details>(() => BuildDetails());
_details = new Lazy<Details>(() =>
{
var t = BuildDetails();
t.Wait();
return t.Result;
});
_icon = new Lazy<IconInfo>(() =>
{
var t = FetchIcon(useThumbnails);
@@ -41,8 +47,9 @@ internal sealed partial class AppListItem : ListItem
});
}
private Details BuildDetails()
private async Task<Details> BuildDetails()
{
// Build metadata, with app type, path, etc.
var metadata = new List<DetailsElement>();
metadata.Add(new DetailsElement() { Key = "Type", Data = new DetailsTags() { Tags = [new Tag(_app.Type)] } });
if (!_app.IsPackaged)
@@ -50,10 +57,33 @@ internal sealed partial class AppListItem : ListItem
metadata.Add(new DetailsElement() { Key = "Path", Data = new DetailsLink() { Text = _app.ExePath } });
}
// Icon
IconInfo? heroImage = null;
if (_app.IsPackaged)
{
heroImage = new IconInfo(_app.IcoPath);
}
else
{
try
{
var stream = await ThumbnailHelper.GetThumbnail(_app.ExePath, true);
if (stream != null)
{
heroImage = IconInfo.FromStream(stream);
}
}
catch (Exception)
{
// do nothing if we fail to load an icon.
// Logging it would be too NOISY, there's really no need.
}
}
return new Details()
{
Title = this.Title,
HeroImage = this.Icon ?? new IconInfo(string.Empty),
HeroImage = heroImage ?? this.Icon ?? new IconInfo(string.Empty),
Metadata = metadata.ToArray(),
};
}
@@ -64,11 +94,6 @@ internal sealed partial class AppListItem : ListItem
if (_app.IsPackaged)
{
icon = new IconInfo(_app.IcoPath);
if (_details.IsValueCreated)
{
_details.Value.HeroImage = icon;
}
return icon;
}
@@ -94,11 +119,6 @@ internal sealed partial class AppListItem : ListItem
icon = new IconInfo(_app.IcoPath);
}
if (_details.IsValueCreated)
{
_details.Value.HeroImage = icon;
}
return icon;
}
}

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

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