mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-01 09:56:32 +01:00
Compare commits
36 Commits
pr35429
...
dev/addNew
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78ed5c7966 | ||
|
|
3dc491339a | ||
|
|
271d64b8dc | ||
|
|
a90b646e72 | ||
|
|
084402a2bd | ||
|
|
08fe8089b8 | ||
|
|
53212188b7 | ||
|
|
7c9876582c | ||
|
|
6cece12b85 | ||
|
|
863f7aa233 | ||
|
|
b81478eb97 | ||
|
|
40acdea356 | ||
|
|
f1322d22c3 | ||
|
|
6b3bbf7e8f | ||
|
|
f66450f6a8 | ||
|
|
d31934b7de | ||
|
|
4f3d7009a8 | ||
|
|
25aac6b63d | ||
|
|
00ee6c1510 | ||
|
|
0a1fd8b134 | ||
|
|
057c13a34d | ||
|
|
2ea9d56129 | ||
|
|
3d306f6177 | ||
|
|
eed39e5d13 | ||
|
|
da58b83a88 | ||
|
|
ce5e5647b3 | ||
|
|
7382f1836f | ||
|
|
9e3a19804c | ||
|
|
a3018b0f7d | ||
|
|
c04b4a761f | ||
|
|
369a147a80 | ||
|
|
00c86fef4f | ||
|
|
72a481b17c | ||
|
|
b204353308 | ||
|
|
da52d485a6 | ||
|
|
515f2386d9 |
7
.github/actions/spell-check/allow/names.txt
vendored
7
.github/actions/spell-check/allow/names.txt
vendored
@@ -56,7 +56,6 @@ damienleroy
|
||||
davidegiacometti
|
||||
debian
|
||||
Deibisu
|
||||
Deibisu
|
||||
Delimarsky
|
||||
Deondre
|
||||
DHowett
|
||||
@@ -72,6 +71,7 @@ Garside
|
||||
Gershaft
|
||||
Giordani
|
||||
Gokce
|
||||
grzhan
|
||||
Guo
|
||||
hanselman
|
||||
Harmath
|
||||
@@ -87,7 +87,6 @@ jefflord
|
||||
Jordi
|
||||
jyuwono
|
||||
Kairu
|
||||
Kairu
|
||||
Kamra
|
||||
Kantarci
|
||||
Karthick
|
||||
@@ -123,7 +122,6 @@ Quriz
|
||||
randyrants
|
||||
ricardosantos
|
||||
riri
|
||||
riri
|
||||
ritchielawrence
|
||||
robmikh
|
||||
Rutkas
|
||||
@@ -147,6 +145,7 @@ TBM
|
||||
tilovell
|
||||
Triet
|
||||
waaverecords
|
||||
Whuihuan
|
||||
Xpg
|
||||
ycv
|
||||
Yuniardi
|
||||
@@ -157,6 +156,8 @@ Zykova
|
||||
|
||||
# OTHERS
|
||||
|
||||
Bilibili
|
||||
BVID
|
||||
cmdow
|
||||
Controlz
|
||||
cortana
|
||||
|
||||
40
.github/actions/spell-check/expect.txt
vendored
40
.github/actions/spell-check/expect.txt
vendored
@@ -1,7 +1,6 @@
|
||||
# FALSE POSITIVES
|
||||
## "PackagemanagerWrapper.cs" should be "PackageManagerWrapper.cs"
|
||||
## NOTICE.MD > MOZILLA PUBLIC LICENSE v1.1
|
||||
|
||||
aaaa
|
||||
abcdefghjkmnpqrstuvxyz
|
||||
abgr
|
||||
@@ -43,7 +42,6 @@ AMPROPSETID
|
||||
amr
|
||||
ANDSCANS
|
||||
animatedvisuals
|
||||
anr
|
||||
ansicolor
|
||||
ANull
|
||||
AOC
|
||||
@@ -71,11 +69,9 @@ AQS
|
||||
ARandom
|
||||
ARCHITEW
|
||||
ARemapped
|
||||
ari
|
||||
ARPINSTALLLOCATION
|
||||
ARPPRODUCTICON
|
||||
ARRAYSIZE
|
||||
arw
|
||||
asf
|
||||
AShortcut
|
||||
ASingle
|
||||
@@ -106,6 +102,7 @@ backtracer
|
||||
bbwe
|
||||
bck
|
||||
BESTEFFORT
|
||||
bezelled
|
||||
bhid
|
||||
BIF
|
||||
bigbar
|
||||
@@ -153,6 +150,7 @@ CALG
|
||||
callbackptr
|
||||
calpwstr
|
||||
Cangjie
|
||||
caniuse
|
||||
CANRENAME
|
||||
CAPTUREBLT
|
||||
CAPTURECHANGED
|
||||
@@ -261,7 +259,7 @@ CRH
|
||||
critsec
|
||||
Crossdevice
|
||||
CRSEL
|
||||
crw
|
||||
crx
|
||||
CSearch
|
||||
CSettings
|
||||
cso
|
||||
@@ -303,8 +301,8 @@ DCOM
|
||||
dcommon
|
||||
dcomp
|
||||
DComposition
|
||||
dcr
|
||||
dcs
|
||||
DCR
|
||||
DCs
|
||||
ddd
|
||||
DDEIf
|
||||
DDevice
|
||||
@@ -374,7 +372,6 @@ DRAWCLIPBOARD
|
||||
DRAWFRAME
|
||||
drawingcolor
|
||||
dreamsofameaningfullife
|
||||
drf
|
||||
drivedetectionwarning
|
||||
dshow
|
||||
DSTINVERT
|
||||
@@ -418,7 +415,6 @@ editkeyboardwindow
|
||||
EDITSHORTCUTS
|
||||
editshortcutswindow
|
||||
EFile
|
||||
eip
|
||||
ekus
|
||||
emmintrin
|
||||
Emoji
|
||||
@@ -592,7 +588,7 @@ Hiberboot
|
||||
HIBYTE
|
||||
hicon
|
||||
HIDEWINDOW
|
||||
hif
|
||||
Hif
|
||||
HIMAGELIST
|
||||
himl
|
||||
hinst
|
||||
@@ -641,6 +637,7 @@ HWNDLAST
|
||||
HWNDNEXT
|
||||
HWNDPREV
|
||||
hyjiacan
|
||||
IApp
|
||||
IBeam
|
||||
ICapture
|
||||
IClass
|
||||
@@ -667,7 +664,6 @@ IGNOREUNKNOWN
|
||||
IGraphics
|
||||
iid
|
||||
Iindex
|
||||
iiq
|
||||
IJson
|
||||
Ijwhost
|
||||
IKs
|
||||
@@ -730,17 +726,17 @@ ISSEPARATOR
|
||||
ITask
|
||||
ith
|
||||
ITHUMBNAIL
|
||||
ITwoWayPipeMessageIPCManaged
|
||||
IUI
|
||||
IUnknown
|
||||
IUse
|
||||
IWbem
|
||||
IWeb
|
||||
IWIC
|
||||
iwr
|
||||
IYUV
|
||||
jfi
|
||||
jfif
|
||||
jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi
|
||||
jif
|
||||
jjw
|
||||
jobject
|
||||
jpe
|
||||
@@ -749,7 +745,6 @@ Jsons
|
||||
jsonval
|
||||
junja
|
||||
jxr
|
||||
kdc
|
||||
keybd
|
||||
KEYBDDATA
|
||||
KEYBDINPUT
|
||||
@@ -874,7 +869,6 @@ MAXIMIZEBOX
|
||||
MAXSHORTCUTSIZE
|
||||
maxversiontested
|
||||
MBR
|
||||
mdc
|
||||
MDICHILD
|
||||
MDL
|
||||
mdtext
|
||||
@@ -882,7 +876,6 @@ mdtxt
|
||||
mdwn
|
||||
MEDIASUBTYPE
|
||||
mediatype
|
||||
mef
|
||||
MENUITEMINFO
|
||||
MENUITEMINFOW
|
||||
MERGECOPY
|
||||
@@ -940,7 +933,6 @@ mpmc
|
||||
MRM
|
||||
MRT
|
||||
mru
|
||||
mrw
|
||||
msc
|
||||
mscorlib
|
||||
msdata
|
||||
@@ -1005,6 +997,7 @@ newitem
|
||||
newpath
|
||||
newplus
|
||||
NEWPLUSCONTEXTMENU
|
||||
NEWPLUSSHELLEXTENSIONWIN
|
||||
newrow
|
||||
newsgroups
|
||||
NIF
|
||||
@@ -1063,7 +1056,6 @@ NOZORDER
|
||||
NPH
|
||||
npmjs
|
||||
NResize
|
||||
nrw
|
||||
nsunt
|
||||
NTAPI
|
||||
ntdll
|
||||
@@ -1093,7 +1085,6 @@ opensource
|
||||
openxmlformats
|
||||
OPTIMIZEFORINVOKE
|
||||
ORAW
|
||||
ori
|
||||
ORPHANEDDIALOGTITLE
|
||||
ORSCANS
|
||||
oss
|
||||
@@ -1142,7 +1133,7 @@ pdo
|
||||
pdto
|
||||
pdtobj
|
||||
pdw
|
||||
Peb
|
||||
peb
|
||||
pef
|
||||
PElems
|
||||
Pels
|
||||
@@ -1178,6 +1169,7 @@ pnid
|
||||
Pnp
|
||||
Popups
|
||||
POPUPWINDOW
|
||||
POSITIONITEM
|
||||
POWERRENAMECONTEXTMENU
|
||||
powerrenameinput
|
||||
POWERRENAMETEST
|
||||
@@ -1214,6 +1206,7 @@ prgms
|
||||
pri
|
||||
PRINTCLIENT
|
||||
printmanagement
|
||||
privacystatement
|
||||
prm
|
||||
proactively
|
||||
PROCESSENTRY
|
||||
@@ -1271,7 +1264,6 @@ QUERYENDSESSION
|
||||
QUERYOPEN
|
||||
QUEUESYNC
|
||||
QUNS
|
||||
raf
|
||||
RAII
|
||||
RAlt
|
||||
Rasterize
|
||||
@@ -1375,8 +1367,6 @@ runtimes
|
||||
ruuid
|
||||
rvm
|
||||
rwin
|
||||
rwl
|
||||
rwz
|
||||
sacl
|
||||
safeprojectname
|
||||
SAMEKEYPREVIOUSLYMAPPED
|
||||
@@ -1510,7 +1500,6 @@ Srch
|
||||
SRCINVERT
|
||||
SRCPAINT
|
||||
SResize
|
||||
srf
|
||||
srme
|
||||
srre
|
||||
srw
|
||||
@@ -1585,6 +1574,8 @@ SYSLIB
|
||||
SYSMENU
|
||||
SYSTEMAPPS
|
||||
SYSTEMTIME
|
||||
SYSTEMWOW
|
||||
tailwindcss
|
||||
tapp
|
||||
TApplication
|
||||
TApplied
|
||||
@@ -1628,6 +1619,7 @@ tkconverters
|
||||
TLayout
|
||||
tlb
|
||||
tlbimp
|
||||
tlhelp
|
||||
TMPVAR
|
||||
TNP
|
||||
Toolhelp
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
|
||||
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.dll",
|
||||
"WinUI3Apps\\NewPlusPackage.msix",
|
||||
"WinUI3Apps\\PowerToys.NewPlus.ShellExtension.win10.dll",
|
||||
|
||||
"PowerAccent.Core.dll",
|
||||
"PowerToys.PowerAccent.dll",
|
||||
@@ -201,6 +202,7 @@
|
||||
"PowerToys.WorkspacesLauncherUI.exe",
|
||||
"PowerToys.WorkspacesLauncherUI.dll",
|
||||
"PowerToys.WorkspacesModuleInterface.dll",
|
||||
"PowerToys.WorkspacesCsharpLibrary.dll",
|
||||
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewExt.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreviewUILib.dll",
|
||||
@@ -321,6 +323,10 @@
|
||||
"WinUI3Apps\\ReverseMarkdown.dll",
|
||||
"WinUI3Apps\\SharpCompress.dll",
|
||||
"WinUI3Apps\\ZstdSharp.dll",
|
||||
"TestableIO.System.IO.Abstractions.dll",
|
||||
"WinUI3Apps\\TestableIO.System.IO.Abstractions.dll",
|
||||
"TestableIO.System.IO.Abstractions.Wrappers.dll",
|
||||
"WinUI3Apps\\TestableIO.System.IO.Abstractions.Wrappers.dll",
|
||||
"ColorCode.Core.dll",
|
||||
"ColorCode.UWP.dll",
|
||||
"UnitsNet.dll",
|
||||
|
||||
0
.pipelines/SDKUpgrade/sdkValidation.yml
Normal file
0
.pipelines/SDKUpgrade/sdkValidation.yml
Normal file
@@ -37,6 +37,10 @@ parameters:
|
||||
type: boolean
|
||||
displayName: "Run Tests"
|
||||
default: true
|
||||
- name: useVSPreview
|
||||
type: boolean
|
||||
displayName: "Build Using Visual Studio Preview"
|
||||
default: false
|
||||
|
||||
extends:
|
||||
template: templates/pipeline-ci-build.yml
|
||||
@@ -44,3 +48,4 @@ extends:
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
|
||||
@@ -33,6 +33,11 @@ parameters:
|
||||
- x64
|
||||
- arm64
|
||||
|
||||
- name: useVSPreview
|
||||
type: boolean
|
||||
displayName: "Build Using Visual Studio Preview"
|
||||
default: false
|
||||
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
|
||||
extends:
|
||||
@@ -42,7 +47,10 @@ extends:
|
||||
- 1ES.PT.ViaStartRight
|
||||
pool:
|
||||
name: SHINE-INT-S
|
||||
image: SHINE-VS17-Latest
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
demands: ImageOverride -equals SHINE-VS17-Preview
|
||||
${{ else }}:
|
||||
image: SHINE-VS17-Latest
|
||||
os: windows
|
||||
sdl:
|
||||
tsa:
|
||||
@@ -58,7 +66,10 @@ extends:
|
||||
parameters:
|
||||
pool:
|
||||
name: SHINE-INT-L
|
||||
image: SHINE-VS17-Latest
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
demands: ImageOverride -equals SHINE-VS17-Preview
|
||||
${{ else }}:
|
||||
image: SHINE-VS17-Latest
|
||||
os: windows
|
||||
variables:
|
||||
IsPipeline: 1 # The installer uses this to detect whether it should pick up localizations
|
||||
|
||||
@@ -50,7 +50,9 @@ parameters:
|
||||
- name: runTests
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
- name: useVSPreview
|
||||
type: boolean
|
||||
default: false
|
||||
- name: versionNumber
|
||||
type: string
|
||||
default: '0.0.1'
|
||||
@@ -135,7 +137,7 @@ jobs:
|
||||
- template: steps-ensure-dotnet-version.yml
|
||||
parameters:
|
||||
sdk: true
|
||||
version: '8.0'
|
||||
version: '9.0'
|
||||
|
||||
- ${{ if eq(parameters.runTests, true) }}:
|
||||
- task: VisualStudioTestPlatformInstaller@1
|
||||
@@ -181,6 +183,9 @@ jobs:
|
||||
- pwsh: |-
|
||||
& "$(build.sourcesdirectory)\.pipelines\verifyAndSetLatestVCToolsVersion.ps1"
|
||||
displayName: Work around DD-1541167 (VCToolsVersion)
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
env:
|
||||
VCWhereExtraVersionTarget: '-prerelease'
|
||||
|
||||
- pwsh: |-
|
||||
& "$(build.sourcesdirectory)\.pipelines\installWiX.ps1"
|
||||
@@ -228,7 +233,10 @@ jobs:
|
||||
inputs:
|
||||
solution: '**\HostsUILib.csproj'
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-hosts.binlog
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-hosts.binlog /p:NoWarn=NU5104
|
||||
${{ else }}:
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-hosts.binlog
|
||||
configuration: $(BuildConfiguration)
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
@@ -241,7 +249,10 @@ jobs:
|
||||
inputs:
|
||||
solution: '**\EnvironmentVariablesUILib.csproj'
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-env-var-editor.binlog
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-env-var-editor.binlog /p:NoWarn=NU5104
|
||||
${{ else }}:
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-env-var-editor.binlog
|
||||
configuration: $(BuildConfiguration)
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
@@ -254,7 +265,10 @@ jobs:
|
||||
inputs:
|
||||
solution: '**\RegistryPreviewUILib.csproj'
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-registry-preview.binlog
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-registry-preview.binlog /p:NoWarn=NU5104
|
||||
${{ else }}:
|
||||
msbuildArgs: /p:CIBuild=true;NoBuild=true -t:pack /bl:$(LogOutputDirectory)\build-registry-preview.binlog
|
||||
configuration: $(BuildConfiguration)
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
@@ -376,6 +390,16 @@ jobs:
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
|
||||
### HACK: On ARM64 builds, building an app with Windows App SDK copies the x64 WebView2 dll instead of the ARM64 one. This task makes sure the right dll is used.
|
||||
- task: CopyFiles@2
|
||||
displayName: HACK Copy core WebView2 ARM64 dll to output directory
|
||||
condition: eq(variables['BuildPlatform'],'arm64')
|
||||
inputs:
|
||||
contents: packages/Microsoft.Web.WebView2.1.0.2739.15/runtimes/win-ARM64/native_uap/Microsoft.Web.WebView2.Core.dll
|
||||
targetFolder: $(Build.SourcesDirectory)/ARM64/Release/WinUI3Apps/
|
||||
flattenFolders: True
|
||||
OverWrite: True
|
||||
|
||||
# Check if deps.json files don't reference different dll versions.
|
||||
- pwsh: |-
|
||||
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\$(BuildPlatform)\$(BuildConfiguration)'
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
- template: steps-ensure-dotnet-version.yml
|
||||
parameters:
|
||||
sdk: true
|
||||
version: '8.0'
|
||||
version: '9.0'
|
||||
|
||||
- task: VisualStudioTestPlatformInstaller@1
|
||||
displayName: Ensure VSTest Platform
|
||||
|
||||
@@ -19,6 +19,9 @@ parameters:
|
||||
- name: runTests
|
||||
type: boolean
|
||||
default: true
|
||||
- name: useVSPreview
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
stages:
|
||||
# Allow manual builds to skip pre-check
|
||||
@@ -43,12 +46,15 @@ stages:
|
||||
name: SHINE-INT-L
|
||||
${{ else }}:
|
||||
name: SHINE-OSS-L
|
||||
${{ if eq(parameters.useVSPreview, true) }}:
|
||||
demands: ImageOverride -equals SHINE-VS17-Preview
|
||||
buildPlatforms:
|
||||
- ${{ platform }}
|
||||
buildConfigurations: [Release]
|
||||
enablePackageCaching: true
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
|
||||
- ${{ if eq(parameters.runTests, true) }}:
|
||||
- stage: Test_${{ platform }}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
parameters:
|
||||
- name: version
|
||||
type: string
|
||||
default: "8.0"
|
||||
default: "9.0"
|
||||
- name: sdk
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$LatestVCToolsVersion = (([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml)).instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.CRT.Source" }).version;
|
||||
$LatestVCToolsVersion = (([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest $env:VCWhereExtraVersionTarget -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml)).instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.CRT.Source" }).version;
|
||||
|
||||
Write-Output "Latest VCToolsVersion: $LatestVCToolsVersion"
|
||||
Write-Output "Updating VCToolsVersion environment variable for job"
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
# PowerToys Contributor's Guide
|
||||
|
||||
Below is our guidance for how to report issues, propose new features, and submit contributions via Pull Requests (PRs). Our philosophy is heavily based around understanding the problem and scenarios first, this is why we follow this pattern before work has started.
|
||||
Below is our guidance for reporting issues, proposing new features, and submitting contributions via Pull Requests (PRs). Our philosophy is to understand the problem and scenarios first, which is why we follow this pattern before work starts.
|
||||
|
||||
1. There is an issue
|
||||
2. There has been a conversation
|
||||
3. There is agreement on the problem, the fit for PowerToys, and the solution to the problem (implementation)
|
||||
1. There is an issue.
|
||||
2. There has been a conversation.
|
||||
3. There is agreement on the problem, the fit for PowerToys, and the solution to the problem (implementation).
|
||||
|
||||
## Filing an issue
|
||||
## Filing an Issue
|
||||
|
||||
Please follow this simple rule to help us eliminate any unnecessary wasted effort & frustration, and ensure an efficient and effective use of everyone's time - yours, ours, and other community members':
|
||||
**Importance of Filing an Issue First**
|
||||
|
||||
> 👉 If you have a question, think you've discovered an issue, would like to propose a new feature, etc., then find/file an issue **BEFORE** starting work to fix/implement it.
|
||||
Please follow this rule to help eliminate wasted effort and frustration, and to ensure an efficient and effective use of everyone’s time:
|
||||
|
||||
When requesting new features / enhancements, understanding problem and scenario around it is extremely important. Having additional evidence, data, tweets, blog posts, research, ... anything is extremely helpful. This information provides context to the scenario that may otherwise be lost.
|
||||
> 👉 If you have a question, think you've discovered an issue, or would like to propose a new feature, please find/file an issue **BEFORE** starting work to fix/implement it.
|
||||
|
||||
* Don't know whether you're reporting an issue or requesting a feature? File an issue
|
||||
* Have a question that you don't see answered in docs, videos, etc.? File an issue
|
||||
* Want to know if we're planning on building a particular feature? File an issue
|
||||
* Got a great idea for a new utility or feature? File an issue/request/idea
|
||||
* Don't understand how to do something? File an issue/Community Guidance Request
|
||||
* Found an existing issue that describes yours? Great - upvote and add additional commentary / info / repro-steps / etc.
|
||||
When requesting new features or enhancements, providing additional evidence, data, tweets, blog posts, or research is extremely helpful. This information gives context to the scenario that may otherwise be lost.
|
||||
|
||||
A quick search before filing an issue also could be helpful. It is likely someone else has found the problem you're seeing, and someone may be working on or have already contributed a fix!
|
||||
* Unsure whether it’s an issue or feature request? File an issue.
|
||||
* Have a question that isn't answered in the docs, videos, etc.? File an issue.
|
||||
* Want to know if we’re planning a particular feature? File an issue.
|
||||
* Got a great idea for a new utility or feature? File an issue/request/idea.
|
||||
* Don’t understand how to do something? File an issue/Community Guidance Request.
|
||||
* Found an existing issue that describes yours? Great! Upvote and add additional commentary, info, or repro steps.
|
||||
|
||||
### How to tell the PowerToys team this is an interesting thing to focus on
|
||||
A quick search before filing an issue could be helpful. It’s likely someone else has found the same problem, and they may even be working on or have already contributed a fix!
|
||||
|
||||
Upvote the original issue by clicking its [+😊] button and hitting 👍 (+1) icon or a different one. This way allows us to measure how impactful different issues are compared to others. The issue with comments like "+1", "me too", or similar is they actually make it harder to have a conversation and harder to quickly determine trending important requests.
|
||||
### Indicating Interest in Issues
|
||||
|
||||
To let the team know which issues are important, upvote by clicking the [+😊] button and the 👍 icon on the original issue post. Avoid comments like "+1" or "me too" as they clutter the discussion and make it harder to prioritize requests.
|
||||
|
||||
---
|
||||
|
||||
## Contributing fixes / features
|
||||
## Contributing Fixes/Features
|
||||
|
||||
Please comment on [our "Would you like to contribute to PowerToys?" thread](https://github.com/microsoft/PowerToys/issues/28769) to let us know you're interested in working on something before you start the work. Not only does this avoid multiple people unexpectedly working on the same thing at the same time but it enables us to make sure everyone is clear on what should be done to implement any new functionality. It's less work for everyone, in the long run, to establish this up front.
|
||||
Please comment on our ["Would you like to contribute to PowerToys?"](https://github.com/microsoft/PowerToys/issues/28769) thread to let us know you're interested in working on something before you start. This helps avoid multiple people unexpectedly working on the same thing and ensures everyone is clear on what should be done. It's less work for everyone to establish this up front.
|
||||
|
||||
### Localization issues
|
||||
### Localization Issues
|
||||
|
||||
Please file localization issues, so our internal localization team can identify and fix them. However we currently don't accept community Pull Requests fixing localization issues. Localization is handled by the internal Microsoft team only.
|
||||
For localization issues, please file an issue to notify our internal localization team, as community PRs for localization aren't accepted. Localization is handled exclusively by the internal Microsoft team.
|
||||
|
||||
### To Spec or not to Spec
|
||||
### To Spec or Not to Spec
|
||||
|
||||
A key point is for everyone to understand the approach that will be taken. We want to be sure if anyone does work, we will accept it in. Items that are larger in scope we'll want some type of spec to understand what is being planned and have a discussion. Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.
|
||||
A key point is for everyone to understand the approach that will be taken. We want to be sure that any work done will be accepted. Larger-scope items will require a spec to outline the approach and allow for discussion. Specs help collaborators consider different solutions, describe feature behavior, and plan for errors. Achieving agreement in a spec before writing code often results in simpler code and less wasted effort.
|
||||
|
||||
For such scenarios, once a team member has agreed with your approach, skip ahead to the section headed "Development" section below.
|
||||
|
||||
Team members will be happy to help review specs and guide them to completion.
|
||||
Once a team member has agreed with your approach, proceed to the "Development" section below. Team members are happy to help review specs and guide them to completion.
|
||||
|
||||
### Help Wanted
|
||||
|
||||
Once the team has approved an issue/spec approach to solving, development can proceed. If no developers are immediately available, the spec can be parked ready for a developer to get started. Parked specs' issues will be labeled "Help Wanted". To find a list of development opportunities waiting for developer involvement, visit the Issues and filter on [the Help-Wanted label](https://github.com/microsoft/PowerToys/labels/Help%20Wanted).
|
||||
Once the team has approved an issue/spec approach, development can proceed. If no developers are immediately available, the spec may be parked and labeled "Help Wanted," ready for a developer to get started. For development opportunities, visit [Issues labeled Help Wanted](https://github.com/microsoft/PowerToys/labels/Help%20Wanted).
|
||||
|
||||
---
|
||||
|
||||
@@ -55,18 +55,18 @@ Once the team has approved an issue/spec approach to solving, development can pr
|
||||
|
||||
Follow the [development guidelines](https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/readme.md).
|
||||
|
||||
### Naming of features and functionality
|
||||
### Naming Features and Functionality
|
||||
|
||||
Naming should be descriptive and straight forward. We want names to be clear about functionality and usefulness moving forward.
|
||||
Names should be descriptive and straightforward, clearly reflecting functionality and usefulness.
|
||||
|
||||
### How can I become a collaborator on the PowerToys team
|
||||
### Becoming a Collaborator on the PowerToys Team
|
||||
|
||||
Be a great community member. Just help out a lot and make useful additions, filing bugs/suggestions, help develop fixes and features, code reviews, and always, docs. Lets continue to make the PowerToys repository a great spot to learn and make a great set of utilities.
|
||||
Be an active community member! Make helpful contributions by filing bugs, offering suggestions, developing fixes and features, conducting code reviews, and updating documentation.
|
||||
|
||||
When the time comes, Microsoft will reach out and help make you a formal team member. Just make sure they can reach out to you :)
|
||||
When the time comes, Microsoft will reach out to you about becoming a formal team member. Just make sure they have a way to contact you. 😊
|
||||
|
||||
---
|
||||
|
||||
## Thank you
|
||||
## Thank You
|
||||
|
||||
Thank you in advance for your contribution!
|
||||
Thank you in advance for your contribution! We appreciate your help in making PowerToys a better tool for everyone.
|
||||
|
||||
1020
DATA_AND_PRIVACY.md
Normal file
1020
DATA_AND_PRIVACY.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -26,19 +26,19 @@
|
||||
<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="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.7" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0-preview.24508.2" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2739.15" />
|
||||
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="8.0.10" />
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
||||
<!--
|
||||
@@ -47,7 +47,7 @@
|
||||
-->
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.1.5" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.6.240923002" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.6.241114003" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
|
||||
@@ -63,24 +63,26 @@
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.19.27" />
|
||||
<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="8.0.0" />
|
||||
<PackageVersion Include="System.CodeDom" Version="9.0.0" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="8.0.1" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="8.0.1" />
|
||||
<PackageVersion Include="System.ComponentModel.Composition" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Data.OleDb" Version="9.0.0" />
|
||||
<!-- Package System.Data.SqlClient added to force it as a dependency of Microsoft.Windows.Compatibility to the latest version available at this time. -->
|
||||
<PackageVersion Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="8.0.1" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="8.0.7" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="17.2.3" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="17.2.3" />
|
||||
<PackageVersion Include="System.Management" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Diagnostics.EventLog" Version="9.0.0" />
|
||||
<!-- 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.0" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="9.0.0" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="21.0.29" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="21.0.29" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="8.0.1" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="8.0.1" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="9.0.0" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.0" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
@@ -92,4 +94,4 @@
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Client" Version="2.4.17140001" />
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Contract" Version="3.0.16990001" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
47
NOTICE.md
47
NOTICE.md
@@ -1318,22 +1318,22 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Mages 2.0.2
|
||||
- Markdig.Signed 0.34.0
|
||||
- MessagePack 2.5.187
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 8.0.0
|
||||
- Microsoft.Data.Sqlite 8.0.7
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0-preview.24508.2
|
||||
- Microsoft.Data.Sqlite 9.0.0
|
||||
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
|
||||
- Microsoft.Extensions.DependencyInjection 8.0.0
|
||||
- Microsoft.Extensions.Hosting 8.0.0
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 8.0.0
|
||||
- Microsoft.Extensions.Logging 8.0.0
|
||||
- Microsoft.Extensions.Logging.Abstractions 8.0.0
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.0
|
||||
- Microsoft.Extensions.Hosting 9.0.0
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.0
|
||||
- Microsoft.Extensions.Logging 9.0.0
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.0
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2739.15
|
||||
- Microsoft.Win32.SystemEvents 8.0.0
|
||||
- Microsoft.Windows.Compatibility 8.0.10
|
||||
- Microsoft.Win32.SystemEvents 9.0.0
|
||||
- Microsoft.Windows.Compatibility 9.0.0
|
||||
- Microsoft.Windows.CsWin32 0.2.46-beta
|
||||
- Microsoft.Windows.CsWinRT 2.1.5
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
|
||||
- Microsoft.WindowsAppSDK 1.6.240923002
|
||||
- Microsoft.WindowsAppSDK 1.6.241114003
|
||||
- Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9
|
||||
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
|
||||
- ModernWpfUI 0.9.4
|
||||
@@ -1346,22 +1346,23 @@ EXHIBIT A -Mozilla Public License.
|
||||
- SharpCompress 0.37.2
|
||||
- StreamJsonRpc 2.19.27
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 8.0.0
|
||||
- System.CodeDom 9.0.0
|
||||
- System.CommandLine 2.0.0-beta4.22272.1
|
||||
- System.ComponentModel.Composition 8.0.0
|
||||
- System.Configuration.ConfigurationManager 8.0.1
|
||||
- System.Data.OleDb 8.0.1
|
||||
- System.ComponentModel.Composition 9.0.0
|
||||
- System.Configuration.ConfigurationManager 9.0.0
|
||||
- System.Data.OleDb 9.0.0
|
||||
- System.Data.SqlClient 4.8.6
|
||||
- System.Diagnostics.EventLog 8.0.1
|
||||
- System.Drawing.Common 8.0.7
|
||||
- System.IO.Abstractions 17.2.3
|
||||
- System.IO.Abstractions.TestingHelpers 17.2.3
|
||||
- System.Management 8.0.0
|
||||
- System.Diagnostics.EventLog 9.0.0
|
||||
- System.Diagnostics.PerformanceCounter 9.0.0
|
||||
- System.Drawing.Common 9.0.0
|
||||
- System.IO.Abstractions 21.0.29
|
||||
- System.IO.Abstractions.TestingHelpers 21.0.29
|
||||
- System.Management 9.0.0
|
||||
- System.Reactive 6.0.1
|
||||
- System.Runtime.Caching 8.0.1
|
||||
- System.ServiceProcess.ServiceController 8.0.1
|
||||
- System.Text.Encoding.CodePages 8.0.0
|
||||
- System.Text.Json 8.0.5
|
||||
- System.Runtime.Caching 9.0.0
|
||||
- System.ServiceProcess.ServiceController 9.0.0
|
||||
- System.Text.Encoding.CodePages 9.0.0
|
||||
- System.Text.Json 9.0.0
|
||||
- UnicodeInformation 2.6.0
|
||||
- UnitsNet 5.56.0
|
||||
- UTF.Unknown 2.5.1
|
||||
|
||||
@@ -630,6 +630,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "src\common\Tele
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseWithoutBorders.UnitTests", "src\modules\MouseWithoutBorders\MouseWithoutBorders.UnitTests\MouseWithoutBorders.UnitTests.csproj", "{66614C26-314C-4B91-9071-76133422CFEF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesCsharpLibrary", "src\modules\Workspaces\WorkspacesCsharpLibrary\WorkspacesCsharpLibrary.csproj", "{89D0E199-B17A-418C-B2F8-7375B6708357}"
|
||||
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
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@@ -2246,6 +2250,30 @@ Global
|
||||
{8A08D663-4995-40E3-B42C-3F910625F284}.Release|x64.Build.0 = Release|x64
|
||||
{8A08D663-4995-40E3-B42C-3F910625F284}.Release|x86.ActiveCfg = Release|x64
|
||||
{8A08D663-4995-40E3-B42C-3F910625F284}.Release|x86.Build.0 = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.Build.0 = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x86.Build.0 = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.ActiveCfg = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.Build.0 = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x86.ActiveCfg = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x86.Build.0 = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.Build.0 = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x86.Build.0 = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.ActiveCfg = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.Build.0 = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x86.ActiveCfg = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x86.Build.0 = Release|x64
|
||||
{D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2646,30 +2674,6 @@ Global
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x64.Build.0 = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x86.ActiveCfg = Release|x64
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033}.Release|x86.Build.0 = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x64.Build.0 = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Debug|x86.Build.0 = Debug|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.ActiveCfg = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x64.Build.0 = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x86.ActiveCfg = Release|x64
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA}.Release|x86.Build.0 = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x64.Build.0 = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Debug|x86.Build.0 = Debug|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.ActiveCfg = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x64.Build.0 = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x86.ActiveCfg = Release|x64
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77}.Release|x86.Build.0 = Release|x64
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{B31FCC55-B5A4-4EA7-B414-2DCEAE6AF332}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2778,6 +2782,30 @@ Global
|
||||
{66614C26-314C-4B91-9071-76133422CFEF}.Release|x64.Build.0 = Release|x64
|
||||
{66614C26-314C-4B91-9071-76133422CFEF}.Release|x86.ActiveCfg = Release|x64
|
||||
{66614C26-314C-4B91-9071-76133422CFEF}.Release|x86.Build.0 = Release|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|x64.Build.0 = Debug|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Debug|x86.Build.0 = Debug|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x64.ActiveCfg = Release|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x64.Build.0 = Release|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x86.ActiveCfg = Release|x64
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357}.Release|x86.Build.0 = Release|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|x64.Build.0 = Debug|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Debug|x86.Build.0 = Debug|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|x64.ActiveCfg = Release|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|x64.Build.0 = Release|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|x86.ActiveCfg = Release|x64
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}.Release|x86.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -2956,6 +2984,8 @@ Global
|
||||
{B5EB9FE9-37EF-47C3-B8B8-81AD3C2972C2} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
|
||||
{A663E672-B26D-4EC0-BEAB-FE2E424AC46F} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
|
||||
{8A08D663-4995-40E3-B42C-3F910625F284} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{D962A009-834F-4EEC-AABB-430DF8F98E39} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{9873BA05-4C41-4819-9283-CF45D795431B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A} = {9873BA05-4C41-4819-9283-CF45D795431B}
|
||||
@@ -2995,8 +3025,6 @@ Global
|
||||
{8ACB33D9-C95B-47D4-8363-9731EE0930A0} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC}
|
||||
{CA716AE6-FE5C-40AC-BB8F-2C87912687AC} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{F055103B-F80B-4D0C-BF48-057C55620033} = {5A7818A8-109C-4E1C-850D-1A654E234B0E}
|
||||
{923DF87C-CA99-4D1C-B1D2-959174E95BFA} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{D5E42C63-57C5-4EF6-AECE-1E2FCA725B77} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||
{A2221D7E-55E7-4BEA-90D1-4F162D670BBF} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{BE126CBB-AE12-406A-9837-A05ACFCA57A7} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{14CB58B7-D280-4A7A-95DE-4B2DF14EA000} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
@@ -3009,6 +3037,8 @@ Global
|
||||
{37D07516-4185-43A4-924F-3C7A5D95ECF6} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD} = {8F62026A-294B-41C6-8839-87463613F216}
|
||||
{66614C26-314C-4B91-9071-76133422CFEF} = {B6C42F16-73EB-477E-8B0D-4E6CF6C20AAC}
|
||||
{89D0E199-B17A-418C-B2F8-7375B6708357} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
|
||||
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
||||
146
README.md
146
README.md
@@ -34,19 +34,19 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
Go to the [Microsoft PowerToys GitHub releases page][github-release-link] and click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user.
|
||||
|
||||
<!-- items that need to be updated release to release -->
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.86%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.85%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.85.1/PowerToysUserSetup-0.85.1-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.85.1/PowerToysUserSetup-0.85.1-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.85.1/PowerToysSetup-0.85.1-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.85.1/PowerToysSetup-0.85.1-arm64.exe
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.87%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.86%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.86.0/PowerToysUserSetup-0.86.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.86.0/PowerToysUserSetup-0.86.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.86.0/PowerToysSetup-0.86.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.86.0/PowerToysSetup-0.86.0-arm64.exe
|
||||
|
||||
| Description | Filename | sha256 hash |
|
||||
|----------------|----------|-------------|
|
||||
| Per user - x64 | [PowerToysUserSetup-0.85.1-x64.exe][ptUserX64] | 5F287C34BF68972C55D7C26585EA5C449B0DBA7D458BF7039CFF448E1D7B732B |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.85.1-arm64.exe][ptUserArm64] | 6D5C3B24156E6E66FD38AD15076B8442F0A1C5CFCBBDC33AD478FB27E5E086AE |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.85.1-x64.exe][ptMachineX64] | 1CDD3C9602F6E5DDC19C66A4FDFE4231389C08E6A037DD22C0A6471F10C7BE02 |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.85.1-arm64.exe][ptMachineArm64] | 6F4DC0217495973B974B7AC1099FD01A2A0FCEE96E8719074EC97FBBC0ECAC4A |
|
||||
| Per user - x64 | [PowerToysUserSetup-0.86.0-x64.exe][ptUserX64] | CFB9608B28B8FF12C9A7C9814A6EF981636EB5AB261DC278C28EC93FD959CCE2 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.86.0-arm64.exe][ptUserArm64] | 861CEDBFDCDA993D1D1056E3280319D5EA45D142CA3C737AB1FB4FABD651A5F5 |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.86.0-x64.exe][ptMachineX64] | 857DE9DC5938D9602F82DFD6183DB5E6823B875A412AEC59B4BE93617E27E9CD |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.86.0-arm64.exe][ptMachineArm64] | 6F37192534C195A02A80AAE1E449DF61C894C50763096A06195581801943FA31 |
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
@@ -92,113 +92,103 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
|
||||
|
||||
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
|
||||
|
||||
### 0.85 - September 2024 Update
|
||||
### 0.86 - October 2024 Update
|
||||
|
||||
In this release, we focused on new features, stability, and improvements.
|
||||
|
||||
**Highlights**
|
||||
|
||||
- New utility: New+ - allows setting a personalized set of templates to quickly create files and folders from a File Explorer context menu. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Language selection - it's now possible to select which UI language should be used by PowerToys utilities.
|
||||
- Lots of quality fixes for Workspaces, improving the number of supported applications.
|
||||
- Reduced Peek memory usage by fixing image leaks. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
|
||||
- Advanced Paste has new abilities: Image to text, and paste to file (text / png / html).
|
||||
- In settings, we've adjusted the left navigation to group the utilities. As the number of utilities shipped with PowerToys keeps growing, we felt this was a needed adjustment. Thanks everyone for your feedback!
|
||||
- Workspaces received many bug fixes, including the proper launching of many instances of the same application in the same workspace. Note, we are still actively looking at how to properly handle PWA detection.
|
||||
- We've added a diagnostic data (telemetry) opt-in option in the Settings General tab. As it is off-by-default, we encourage users to turn it on as that helps direct our development efforts and their journeys. More information about the data we collect can be found in the [PowerToys Data and Privacy documentation](https://aka.ms/powertoys-data-and-privacy-documentation) and what each event does.
|
||||
|
||||
### General
|
||||
|
||||
- Added a general setting to select which UI language should be used in PowerToys utilities.
|
||||
- Fixed internal code of some policies for Group Policy Objects, that were reading registry entries using the wrong internal functions, and structured code better to avoid future mistakes of the same kind. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added a setting for diagnostic data (telemetry) opt-in (off by default, however, see above for why we encourage you to opt-in!) and user controls to view data.
|
||||
- Improved exception logging by adding the type of Exception and InnerException. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Advanced Paste
|
||||
|
||||
- Fixed some telemetry calls to signal Advanced Paste activation on the cases where a direct shortcut is being used without showing the UI.
|
||||
- User-defined custom actions can only be used with AI turned on, so custom actions were disabled on Settings when AI is disabled and were hidden from the Advanced Paste UI.
|
||||
- Added new built-in actions: Image to text, and paste txt, png or html as a file.
|
||||
|
||||
### Awake
|
||||
### Mouse Jump
|
||||
|
||||
- Fixed tray icon behaviors, not appearing and showing incorrect time. Thanks [@dend](https://github.com/dend)!
|
||||
- Refactored the common classes into a separate project. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Brought back the telemetry events that were deleted across previous refactoring efforts.
|
||||
|
||||
### Environment Variables Editor
|
||||
### Mouse Without Borders
|
||||
|
||||
- Added the `_NT_SYMBOL_PATH`, `_NT_ALT_SYMBOL_PATH` and `_NT_SYMCACHE_PATH` as variables that are shown as lists. Thanks [@chwarr](https://github.com/chwarr)!
|
||||
|
||||
### FancyZones
|
||||
|
||||
- Allow snapping applications that were launched by Workspaces.
|
||||
|
||||
### File Locksmith
|
||||
|
||||
- Fixed an issue causing File Locksmith to be triggered by unrelated verbs in the context menu.
|
||||
|
||||
### Mouse Pointer Crosshairs
|
||||
|
||||
- Allow crosshairs radius to be 0 pixels. Thanks [@octastylos-pseudodipteros](https://github.com/octastylos-pseudodipteros)!
|
||||
- Refactored the Logger common classes. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
|
||||
### New+
|
||||
|
||||
- New utility - Allows setting a personalized set of templates to quickly create files and folders from a File Explorer context menu. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Added missing entry for New+ policy state reporting in the Bug Report tool. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Added a policy for enabling/disabling whether filename extensions should be shown. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed the telemetry event for when the modules is enabled or disabled. (This was a hotfix for 0.85)
|
||||
- Fixed bug when creating folders or files that contain Unicode characters. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Fixed bug when the name of a new folder collided with an already existing folder. Thanks [@cgaarden](https://github.com/cgaarden)!
|
||||
- Updated the New+ icons to the fluent style.
|
||||
|
||||
### Peek
|
||||
|
||||
- Properly show file's modified date instead of creation date in the file previewer. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed memory leak caused by unmanaged bitmap images not being freed. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed an issue causing Peek to not be displayed the first time when using a preview handler to display files. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Prevent tooltip in file previewer from overlapping with title bar controls. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Fixed memory leaks in thumbnails and refactored image previewer. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
- Folder preview enumeration of size and number of files is now more responsive and faster. Thanks [@daverayment](https://github.com/daverayment)!
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
- Improved the message boxes to be more specific when PowerToys Run failed to initialize itself or any plugin. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Use capital letters when showing degree results in the Unit Converter plugin. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Handled a culture not found error when checking for right-to-left languages.
|
||||
- Fixed the WebSearch plugin results title being trimmed in the UI. Thanks [@octastylos-pseudodipteros](https://github.com/octastylos-pseudodipteros)!
|
||||
- The Unit Converter plugin will now show more significant digits. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Improved error handling when copying to the clipboard results in an error. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
|
||||
### Quick Accent
|
||||
|
||||
- Add the Middle Eastern Romanization character set. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Add the degree sign, integral and vertical ellipsis when "All Languages" is selected. Thanks [@rddunphy](https://github.com/rddunphy)!
|
||||
- Added support for the Serbian Cyrillic character set. Thanks [@Sirozha1337](https://github.com/Sirozha1337)!
|
||||
|
||||
### Registry Preview
|
||||
|
||||
- Adopted the Monaco Editor as the UI text editor. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Settings
|
||||
|
||||
- Fixed the link to the Workspaces documentation. (This was a hotfix for 0.84)
|
||||
- Fixed flyout issues after the Windows App SDK upgrade. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed initialization for the New+ settings page. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed enabled state of a control on the New+ settings page if the module is enabled by policy. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed a crash when cancelling the template folder selection in the New+ settings page.
|
||||
- Fixed a crash when trying to access a non-existing templates folder from the New+ page. (This was a hotfix for 0.85)
|
||||
- Added a navigation tree to group utilities in the left navigation menu.
|
||||
- Sorted the list of languages in the language selection combo box in the General tab. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fixed the state of the info bar about templates not being backed up to not close and react to the module's enabled state in the New+ page. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed a crash caused by a dangling thread.
|
||||
- Clicking a notification about there being an update available should now correctly open the Settings application in the General tab.
|
||||
- Fixed a UI freeze when trying to access the Diagnostic Data Viewer files. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
|
||||
### Workspaces
|
||||
|
||||
- Fixed detecting and snapping applications like Discord. (This was a hotfix for 0.84)
|
||||
- Fixed detecting and snapping applications like Steam. (This was a hotfix for 0.84)
|
||||
- Fixed button visibility in the UI. (This was a hotfix for 0.84)
|
||||
- Fixed an issue launching the wrong project when the editor was closed without saving or cancelling a new project.
|
||||
- Properly handle repositioning windows running as administrator.
|
||||
- Properly handle cases where the monitor where a workspace was saved is no longer present.
|
||||
- Fixed the workspace launcher restarting itself in a loop without success.
|
||||
- Properly handle standalone applications.
|
||||
- Fixed issues causing icons to not show.
|
||||
- Fixed launching the incorrect workspace when launching many workspaces quickly through shortcuts. (This was a hotfix for 0.85)
|
||||
- Fixed launching many instances of the same application in a workspace.
|
||||
- Fixed a crash when a previously captured monitor ID no longer existed.
|
||||
- Fixed an issue causing the wrong coordinates to be saved for minimized applications.
|
||||
- Fixed an issue causing a crash when stress testing workspace launching.
|
||||
- Fixed application launching when UAC is off and every application always runs elevated.
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fixed the thirdPartyRunPlugins.md entry for the RDP plugin. Thanks [@YisroelTech](https://github.com/YisroelTech)!
|
||||
- Added HackMD plugin mention to thirdPartyRunPlugins.md. Thanks [@8LWXpg](https://github.com/8LWXpg)!
|
||||
- Added SSH plugin mention to thirdPartyRunPlugins.md. Thanks [@8LWXpg](https://github.com/8LWXpg)!
|
||||
- Added the [Data and Privacy documentation](https://github.com/microsoft/PowerToys/blob/main/DATA_AND_PRIVACY.md) to the repo.
|
||||
|
||||
### Development
|
||||
|
||||
- Upgraded Windows App SDK to 1.6.
|
||||
- Upgraded the Target Platform Version to 10.0.22621.0.
|
||||
- Added a bot trigger to automatically add a label to Workspaces issues. Thanks [@plante-msft](https://github.com/plante-msft)!
|
||||
- Fixed a regular expression in the bot triggers for wanting to submit community contributions. Thanks [@PesBandi](https://github.com/PesBandi)!
|
||||
- Fixed analyzer errors after the Visual Studio 17.12 update. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Fixed the TSA configuration for release CI builds.
|
||||
- Refactored automated file component generation during installer builds.
|
||||
- Rewrote the Azure Devops build system to be more modular and share more definitions between PR CI and Release CI.
|
||||
- Fixed debugging of the New+ page of the Settings application when a settings file was not present.
|
||||
- Fixed setting the version of the App Manifest in the File Locksmith and New+ context menu app packages.
|
||||
- Fixed abstracted UI library nuget package signing on release CI.
|
||||
- Removed build status from GitHub README.
|
||||
- Fixed the CI precheck action to take into account the recent changes in CI actions.
|
||||
- Added the new Microsoft org issue types to the issue templates. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Updated System.Text.Json to 8.0.5 and System.Runtime.Caching to 8.0.1 and related dependencies to the latest to address security reports. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Updated WinAppSDK to 1.6.1 and CsWinRT to 2.1.5. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Upgraded the WpfUI dependency to 3.0.5.
|
||||
- Updated MessagePack to 2.5.187 and StreamJsonRpc to 2.19.27 to address security reports.
|
||||
- Removed some of the hacks that are no longer needed that tried to force same dependency versions in .csproj files.
|
||||
- Removed the Markdown file exclusions from the conditions that trigger a full CI test.
|
||||
- CI fails again when there are XAML style errors in a PR.
|
||||
- Fixed CI actions that were not failing when one of the powershell scripts they tried to run was failing.
|
||||
- Fixed analyzer violations to allow fully building PowerToys on Visual Studio 17.12. Thanks [@snickler](https://github.com/snickler)!
|
||||
|
||||
#### What is being planned for version 0.86
|
||||
#### What is being planned for version 0.87
|
||||
|
||||
For [v0.86][github-next-release-work], we'll work on the items below:
|
||||
For [v0.87][github-next-release-work], we'll work on the items below:
|
||||
|
||||
- Stability / bug fixes
|
||||
- New module: File Actions Menu
|
||||
@@ -214,7 +204,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct][oss-conduct
|
||||
|
||||
## Privacy Statement
|
||||
|
||||
The application logs basic telemetry. Our Telemetry Data page (Coming Soon) has the trends from the telemetry. Please read the [Microsoft privacy statement][privacy-link] for more information.
|
||||
The application logs basic diagnostic data (telemetry). For more information on privacy and what we collect, see our [PowerToys Data and Privacy documentation](https://aka.ms/powertoys-data-and-privacy-documentation).
|
||||
|
||||
[oss-CLA]: https://cla.opensource.microsoft.com
|
||||
[oss-conduct-code]: CODE_OF_CONDUCT.md
|
||||
|
||||
@@ -39,6 +39,9 @@ Contact the developers of a plugin directly for assistance with a specific plugi
|
||||
| [GitHubRepo](https://github.com/8LWXpg/PowerToysRun-GitHubRepo) | [8LWXpg](https://github.com/8LWXpg) | Search and open GitHub repositories |
|
||||
| [ProcessKiller](https://github.com/8LWXpg/PowerToysRun-ProcessKiller) | [8LWXpg](https://github.com/8LWXpg) | Search and kill processes |
|
||||
| [ChatGPT](https://github.com/ferraridavide/ChatGPTPowerToys) | [ferraridavide](https://github.com/ferraridavide) | Ask a question to ChatGPT |
|
||||
| [CanIUse](https://github.com/skttl/ptrun-caniuse) | [skttl](https://github.com/skttl) | Look up browser feature support with caniuse.com |
|
||||
| [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 |
|
||||
|
||||
## Extending software plugins
|
||||
|
||||
@@ -58,3 +61,4 @@ Below are community created plugins that target a website or software. They are
|
||||
| [PowerSearch for 1Password](https://github.com/KairuDeibisu/PowerToysRunPlugin1Password) | [KairuDeibisu](https://github.com/KairuDeibisu) | An unofficial plugin for searching 1Password for usernames and passwords |
|
||||
| [HackMD](https://github.com/8LWXpg/PowerToysRun-HackMD) | [8LWXpg](https://github.com/8LWXpg) | Open HackMD notes |
|
||||
| [SSH](https://github.com/8LWXpg/PowerToysRun-SSH) | [8LWXpg](https://github.com/8LWXpg) | Connect to ssh clients |
|
||||
| [Bilibili](https://github.com/Whuihuan/PowerToysRun-Bilibili) | [Whuihuan](https://github.com/Whuihuan) | Use AVID or BVID to parse and jump to Bilibili |
|
||||
|
||||
@@ -18,6 +18,19 @@
|
||||
<DirectoryRef Id="NewPlusAssetsInstallFolder" FileSource="$(var.NewPlusAssetsFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--NewPlusAssetsFiles_Component_Def-->
|
||||
|
||||
<!-- NewPlus Shell Extension for Win10 registration -->
|
||||
<Component Id="NewPlus_ShellExtension_win10" Guid="D5456D4A-6EEC-4B85-944D-6A6A4A74FFA6" Win64="yes">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\CLSID\{FF90D477-E32A-4BE8-8CC5-A502A97F5401}">
|
||||
<RegistryValue Type="string" Value="NewPlus Shell Extension Win10" />
|
||||
<RegistryValue Type="string" Name="ContextMenuOptIn" Value="" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Value="[WinUI3AppsInstallFolder]PowerToys.NewPlus.ShellExtension.win10.dll" />
|
||||
<RegistryValue Type="string" Key="InprocServer32" Name="ThreadingModel" Value="Apartment" />
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="SOFTWARE\Classes\Directory\background\ShellEx\ContextMenuHandlers\NewPlusShellExtensionWin10">
|
||||
<RegistryValue Type="string" Value="{FF90D477-E32A-4BE8-8CC5-A502A97F5401}"/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="NewPlusComponentGroup">
|
||||
@@ -27,6 +40,7 @@
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveFolderNewPlusAssetsFolder" Directory="NewPlusAssetsInstallFolder" On="uninstall"/>
|
||||
</Component>
|
||||
<ComponentRef Id="NewPlus_ShellExtension_win10" />
|
||||
</ComponentGroup>
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<WindowsSdkPackageVersion>10.0.22621.48</WindowsSdkPackageVersion>
|
||||
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
@@ -14,7 +14,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoWarn></NoWarn>
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
<WarningsNotAsErrors>CA1720</WarningsNotAsErrors>
|
||||
<WarningsNotAsErrors>CA1720;CA1859;CA2263;CA2022</WarningsNotAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
|
||||
@@ -7,7 +7,7 @@ export async function registerAdditionalLanguages(monaco){
|
||||
await languageDefinitions();
|
||||
registerAdditionalLanguage("cppExt", [".ino", ".pde"], "cpp", monaco)
|
||||
registerAdditionalLanguage("xmlExt", [".wsdl", ".csproj", ".vcxproj", ".vbproj", ".fsproj"], "xml", monaco)
|
||||
registerAdditionalLanguage("txtExt", [".sln", ".log", ".vsconfig", ".env", ".srt"], "txt", monaco)
|
||||
registerAdditionalLanguage("txtExt", [".sln", ".log", ".vsconfig", ".env", ".srt", ".ahk"], "txt", monaco)
|
||||
registerAdditionalLanguage("razorExt", [".razor"], "razor", monaco)
|
||||
registerAdditionalLanguage("vbExt", [".vbs"], "vb", monaco)
|
||||
registerAdditionalLanguage("iniExt", [".inf", ".gitconfig", ".gitattributes", ".editorconfig"], "ini", monaco)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,6 +4,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<AssemblyName>PowerToys.Common.UI</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -29,34 +29,28 @@ namespace Microsoft.PowerToys.FilePreviewCommon
|
||||
new XmlFormatter(),
|
||||
}.AsReadOnly();
|
||||
|
||||
private static string? _monacoDirectory;
|
||||
private static readonly Lazy<string> _monacoDirectory = new(GetRuntimeMonacoDirectory);
|
||||
|
||||
public static string GetRuntimeMonacoDirectory()
|
||||
/// <summary>
|
||||
/// Gets the path of the Monaco assets folder.
|
||||
/// </summary>
|
||||
public static string MonacoDirectory => _monacoDirectory.Value;
|
||||
|
||||
private static string GetRuntimeMonacoDirectory()
|
||||
{
|
||||
string codeBase = Assembly.GetExecutingAssembly().Location;
|
||||
string path = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(codeBase) ?? string.Empty, "Assets", "Monaco"));
|
||||
if (Path.Exists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're likely in WinUI3Apps directory and need to go back to the base directory.
|
||||
return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(codeBase) ?? string.Empty, "..", "Assets", "Monaco"));
|
||||
}
|
||||
}
|
||||
string exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty;
|
||||
|
||||
public static string MonacoDirectory
|
||||
{
|
||||
get
|
||||
// If the executable is within "WinUI3Apps", correct the path first.
|
||||
if (Path.GetFileName(exePath) == "WinUI3Apps")
|
||||
{
|
||||
if (string.IsNullOrEmpty(_monacoDirectory))
|
||||
{
|
||||
_monacoDirectory = GetRuntimeMonacoDirectory();
|
||||
}
|
||||
|
||||
return _monacoDirectory;
|
||||
exePath = Path.Combine(exePath, "..");
|
||||
}
|
||||
|
||||
string monacoPath = Path.Combine(exePath, "Assets", "Monaco");
|
||||
|
||||
return Directory.Exists(monacoPath) ?
|
||||
monacoPath :
|
||||
throw new DirectoryNotFoundException($"Monaco assets directory not found at {monacoPath}");
|
||||
}
|
||||
|
||||
public static JsonDocument GetLanguages()
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
@@ -23,15 +22,14 @@ namespace ManagedCommon
|
||||
|
||||
public static string LoadLanguage()
|
||||
{
|
||||
FileSystem fileSystem = new FileSystem();
|
||||
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var file = localAppDataDir + SettingsFilePath + SettingsFile;
|
||||
|
||||
if (fileSystem.File.Exists(file))
|
||||
if (File.Exists(file))
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream inputStream = fileSystem.File.Open(file, FileMode.Open);
|
||||
var inputStream = File.Open(file, FileMode.Open);
|
||||
StreamReader reader = new StreamReader(inputStream);
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO.Abstractions;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using PowerToys.Interop;
|
||||
|
||||
@@ -14,7 +15,6 @@ namespace ManagedCommon
|
||||
{
|
||||
public static class Logger
|
||||
{
|
||||
private static readonly IFileSystem _fileSystem = new FileSystem();
|
||||
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
|
||||
private static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location).ProductVersion;
|
||||
|
||||
@@ -41,28 +41,30 @@ namespace ManagedCommon
|
||||
applicationLogPath = Constants.AppDataPath() + applicationLogPath + "\\" + Version;
|
||||
}
|
||||
|
||||
if (!_fileSystem.Directory.Exists(applicationLogPath))
|
||||
if (!Directory.Exists(applicationLogPath))
|
||||
{
|
||||
_fileSystem.Directory.CreateDirectory(applicationLogPath);
|
||||
Directory.CreateDirectory(applicationLogPath);
|
||||
}
|
||||
|
||||
var logFilePath = _fileSystem.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) + ".txt");
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
|
||||
|
||||
Trace.AutoFlush = true;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogError(string message)
|
||||
{
|
||||
Log(message, Error);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogError(string message, Exception ex)
|
||||
{
|
||||
if (ex == null)
|
||||
{
|
||||
LogError(message);
|
||||
Log(message, Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -85,26 +87,31 @@ namespace ManagedCommon
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogWarning(string message)
|
||||
{
|
||||
Log(message, Warning);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogInfo(string message)
|
||||
{
|
||||
Log(message, Info);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogDebug(string message)
|
||||
{
|
||||
Log(message, Debug);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static void LogTrace()
|
||||
{
|
||||
Log(string.Empty, TraceFlag);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void Log(string message, string type)
|
||||
{
|
||||
Trace.WriteLine("[" + DateTime.Now.TimeOfDay + "] [" + type + "] " + GetCallerInfo());
|
||||
@@ -117,13 +124,49 @@ namespace ManagedCommon
|
||||
Trace.Unindent();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static string GetCallerInfo()
|
||||
{
|
||||
StackTrace stackTrace = new();
|
||||
|
||||
var methodName = stackTrace.GetFrame(3)?.GetMethod();
|
||||
var className = methodName?.DeclaringType.Name;
|
||||
return className + "::" + methodName?.Name;
|
||||
var callerMethod = GetCallerMethod(stackTrace);
|
||||
|
||||
return $"{callerMethod?.DeclaringType?.Name}::{callerMethod.Name}";
|
||||
}
|
||||
|
||||
private static MethodBase GetCallerMethod(StackTrace stackTrace)
|
||||
{
|
||||
const int topFrame = 3;
|
||||
|
||||
var topMethod = stackTrace.GetFrame(topFrame)?.GetMethod();
|
||||
|
||||
try
|
||||
{
|
||||
if (topMethod?.Name == nameof(IAsyncStateMachine.MoveNext) && typeof(IAsyncStateMachine).IsAssignableFrom(topMethod?.DeclaringType))
|
||||
{
|
||||
// Async method; return actual method as determined by heuristic:
|
||||
// "Nearest method on stack to async state-machine's MoveNext() in same namespace but in a different type".
|
||||
// There are tighter ways of determining the actual method, but this is good enough and probably faster.
|
||||
for (int deepFrame = topFrame + 1; deepFrame < stackTrace.FrameCount; deepFrame++)
|
||||
{
|
||||
var deepMethod = stackTrace.GetFrame(deepFrame)?.GetMethod();
|
||||
|
||||
if (deepMethod?.DeclaringType != topMethod?.DeclaringType && deepMethod?.DeclaringType?.Namespace == topMethod?.DeclaringType?.Namespace)
|
||||
{
|
||||
return deepMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore exceptions in Release. The code above won't throw, but if it does, we don't want to crash the app.
|
||||
#if DEBUG
|
||||
throw;
|
||||
#endif
|
||||
}
|
||||
|
||||
return topMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="System.Management" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Microsoft.PowerToys.Telemetry
|
||||
|
||||
private readonly bool telemetryEnabled = DataDiagnosticsSettings.GetEnabledValue(); // This is the global telemetry setting on whether to log events
|
||||
private readonly bool telemetryRecordingEnabled = DataDiagnosticsSettings.GetViewEnabledValue(); // This is the setting for recording telemetry events to disk for viewing
|
||||
private readonly string etwFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\PowerToys\", "etw");
|
||||
private string etwFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\PowerToys\", "etw");
|
||||
private bool disposedValue;
|
||||
private string sessionName;
|
||||
private string etwFilePath;
|
||||
@@ -49,6 +49,18 @@ namespace Microsoft.PowerToys.Telemetry
|
||||
/// Initializes a new instance of the <see cref="ETWTrace"/> class.
|
||||
/// </summary>
|
||||
public ETWTrace()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
public ETWTrace(string etwPath)
|
||||
{
|
||||
this.etwFolderPath = etwPath;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
if (File.Exists(etwFolderPath))
|
||||
{
|
||||
|
||||
@@ -178,7 +178,8 @@ void notifications::show_toast_with_activations(std::wstring message,
|
||||
std::wstring title,
|
||||
std::wstring_view background_handler_id,
|
||||
std::vector<action_t> actions,
|
||||
toast_params params)
|
||||
toast_params params,
|
||||
std::wstring launch_uri)
|
||||
{
|
||||
// DO NOT LOCALIZE any string in this function, because they're XML tags and a subject to
|
||||
// https://learn.microsoft.com/windows/uwp/design/shell/tiles-and-notifications/toast-xml-schema
|
||||
@@ -189,7 +190,18 @@ void notifications::show_toast_with_activations(std::wstring message,
|
||||
// We must set toast's title and contents immediately, because some of the toasts we send could be snoozed.
|
||||
// Windows instantiates the snoozed toast from scratch before showing it again, so all bindings that were set
|
||||
// using NotificationData would be empty.
|
||||
toast_xml += LR"(<?xml version="1.0"?><toast><visual><binding template="ToastGeneric">)";
|
||||
// Add the launch attribute if launch_uri is provided, otherwise omit it
|
||||
toast_xml += LR"(<?xml version="1.0"?>)";
|
||||
if (!launch_uri.empty())
|
||||
{
|
||||
toast_xml += LR"(<toast launch=")" + launch_uri + LR"(" activationType="protocol">)"; // Use the launch URI if provided
|
||||
}
|
||||
else
|
||||
{
|
||||
toast_xml += LR"(<toast>)"; // No launch attribute if empty
|
||||
}
|
||||
|
||||
toast_xml += LR"(<visual><binding template="ToastGeneric">)";
|
||||
toast_xml += LR"(<text id="1">)";
|
||||
toast_xml += std::move(title);
|
||||
toast_xml += LR"(</text>)";
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace notifications
|
||||
using action_t = std::variant<link_button, background_activated_button, snooze_button>;
|
||||
|
||||
void show_toast(std::wstring plaintext_message, std::wstring title, toast_params params = {});
|
||||
void show_toast_with_activations(std::wstring plaintext_message, std::wstring title, std::wstring_view background_handler_id, std::vector<action_t> actions, toast_params params = {});
|
||||
void show_toast_with_activations(std::wstring plaintext_message, std::wstring title, std::wstring_view background_handler_id, std::vector<action_t> actions, toast_params params = {}, std::wstring launch_uri = L"");
|
||||
void update_toast_progress_bar(std::wstring_view tag, progress_bar_params params);
|
||||
void remove_toasts_by_tag(std::wstring_view tag);
|
||||
void remove_all_scheduled_toasts();
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace AdvancedPaste.Settings
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private readonly TaskScheduler _taskScheduler;
|
||||
private readonly IFileSystemWatcher _watcher;
|
||||
private readonly object _loadingSettingsLock = new();
|
||||
private readonly Lock _loadingSettingsLock = new();
|
||||
private readonly List<PasteFormats> _additionalActions;
|
||||
private readonly List<AdvancedPasteCustomAction> _customActions;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<PublishDir>$(PowerToysRoot)\$(Platform)\$(Configuration)\WinUI3Apps</PublishDir>
|
||||
|
||||
@@ -276,7 +276,7 @@ namespace Hosts.Tests
|
||||
|
||||
service.RemoveReadOnlyAttribute();
|
||||
|
||||
var readOnly = fileSystem.FileInfo.FromFileName(service.HostsFilePath).Attributes.HasFlag(FileAttributes.ReadOnly);
|
||||
var readOnly = fileSystem.FileInfo.New(service.HostsFilePath).Attributes.HasFlag(FileAttributes.ReadOnly);
|
||||
Assert.IsFalse(readOnly);
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ namespace Hosts.Tests
|
||||
|
||||
await service.WriteAsync("# Empty hosts file", Enumerable.Empty<Entry>());
|
||||
|
||||
var hidden = fileSystem.FileInfo.FromFileName(service.HostsFilePath).Attributes.HasFlag(FileAttributes.Hidden);
|
||||
var hidden = fileSystem.FileInfo.New(service.HostsFilePath).Attributes.HasFlag(FileAttributes.Hidden);
|
||||
Assert.IsTrue(hidden);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
@@ -9,7 +10,7 @@ using System.IO.Abstractions;
|
||||
|
||||
namespace Hosts.Tests.Mocks
|
||||
{
|
||||
public class MockFileSystemWatcher : FileSystemWatcherBase
|
||||
public partial class MockFileSystemWatcher : FileSystemWatcherBase
|
||||
{
|
||||
public override bool IncludeSubdirectories { get; set; }
|
||||
|
||||
@@ -27,26 +28,35 @@ namespace Hosts.Tests.Mocks
|
||||
|
||||
public override ISynchronizeInvoke SynchronizingObject { get; set; }
|
||||
|
||||
public override Collection<string> Filters => throw new System.NotImplementedException();
|
||||
public override Collection<string> Filters => throw new NotImplementedException();
|
||||
|
||||
public override WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType) => default;
|
||||
public override IFileSystem FileSystem => throw new NotImplementedException();
|
||||
|
||||
public override WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int timeout) => default;
|
||||
public override IContainer Container => throw new NotImplementedException();
|
||||
|
||||
public MockFileSystemWatcher(string path) => Path = path;
|
||||
public override void BeginInit() => throw new NotImplementedException();
|
||||
|
||||
public override void EndInit() => throw new NotImplementedException();
|
||||
|
||||
public override IWaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, TimeSpan timeout) => throw new NotImplementedException();
|
||||
|
||||
public override IWaitForChangedResult WaitForChanged(WatcherChangeTypes changeType) => throw new NotImplementedException();
|
||||
|
||||
public override IWaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int timeout) => throw new NotImplementedException();
|
||||
|
||||
public MockFileSystemWatcher()
|
||||
{
|
||||
}
|
||||
|
||||
public MockFileSystemWatcher(string path)
|
||||
{
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public MockFileSystemWatcher(string path, string filter)
|
||||
{
|
||||
Path = path;
|
||||
Filter = filter;
|
||||
}
|
||||
|
||||
public override void BeginInit()
|
||||
{
|
||||
}
|
||||
|
||||
public override void EndInit()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,22 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
|
||||
namespace Hosts.Tests.Mocks
|
||||
{
|
||||
public class MockFileSystemWatcherFactory : IFileSystemWatcherFactory
|
||||
{
|
||||
public IFileSystemWatcher CreateNew() => new MockFileSystemWatcher(null);
|
||||
public IFileSystem FileSystem => throw new NotImplementedException();
|
||||
|
||||
public IFileSystemWatcher CreateNew(string path) => new MockFileSystemWatcher(path);
|
||||
public IFileSystemWatcher New() => new MockFileSystemWatcher();
|
||||
|
||||
public IFileSystemWatcher CreateNew(string path, string filter) => new MockFileSystemWatcher(path, filter);
|
||||
public IFileSystemWatcher New(string path) => new MockFileSystemWatcher(path);
|
||||
|
||||
public IFileSystemWatcher FromPath(string path) => new MockFileSystemWatcher(path);
|
||||
public IFileSystemWatcher New(string path, string filter) => new MockFileSystemWatcher(path, filter);
|
||||
|
||||
public IFileSystemWatcher Wrap(FileSystemWatcher fileSystemWatcher) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Hosts.Helpers
|
||||
public static void WaitForEventLoop(string eventName, Action callback)
|
||||
{
|
||||
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
new Thread(() =>
|
||||
var t = new Thread(() =>
|
||||
{
|
||||
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
|
||||
while (true)
|
||||
@@ -24,7 +24,10 @@ namespace Hosts.Helpers
|
||||
dispatcherQueue.TryEnqueue(() => callback());
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
});
|
||||
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Hosts.Settings
|
||||
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private readonly IFileSystemWatcher _watcher;
|
||||
private readonly object _loadingSettingsLock = new object();
|
||||
private readonly Lock _loadingSettingsLock = new Lock();
|
||||
|
||||
public bool ShowStartupWarning { get; private set; }
|
||||
|
||||
|
||||
@@ -216,6 +216,12 @@ public:
|
||||
m_hShowAdminEvent = nullptr;
|
||||
}
|
||||
|
||||
if (m_hTerminateEvent)
|
||||
{
|
||||
CloseHandle(m_hTerminateEvent);
|
||||
m_hTerminateEvent = nullptr;
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
@@ -280,6 +286,7 @@ public:
|
||||
SetEvent(m_hTerminateEvent);
|
||||
WaitForSingleObject(m_hProcess, 1500);
|
||||
TerminateProcess(m_hProcess, 1);
|
||||
ResetEvent(m_hTerminateEvent);
|
||||
}
|
||||
|
||||
m_enabled = false;
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace HostsUILib.Helpers
|
||||
|
||||
_hostsFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"System32\drivers\etc\hosts");
|
||||
|
||||
_fileSystemWatcher = _fileSystem.FileSystemWatcher.CreateNew();
|
||||
_fileSystemWatcher = _fileSystem.FileSystemWatcher.New();
|
||||
_fileSystemWatcher.Path = _fileSystem.Path.GetDirectoryName(HostsFilePath);
|
||||
_fileSystemWatcher.Filter = _fileSystem.Path.GetFileName(HostsFilePath);
|
||||
_fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
|
||||
@@ -130,7 +130,7 @@ namespace HostsUILib.Helpers
|
||||
throw new NotRunningElevatedException();
|
||||
}
|
||||
|
||||
if (_fileSystem.FileInfo.FromFileName(HostsFilePath).IsReadOnly)
|
||||
if (_fileSystem.FileInfo.New(HostsFilePath).IsReadOnly)
|
||||
{
|
||||
throw new ReadOnlyHostsException();
|
||||
}
|
||||
@@ -200,7 +200,7 @@ namespace HostsUILib.Helpers
|
||||
}
|
||||
|
||||
// FileMode.OpenOrCreate is necessary to prevent UnauthorizedAccessException when the hosts file is hidden
|
||||
using var stream = _fileSystem.FileStream.Create(HostsFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, _defaultBufferSize, FileOptions.Asynchronous);
|
||||
using var stream = _fileSystem.FileStream.New(HostsFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, _defaultBufferSize, FileOptions.Asynchronous);
|
||||
using var writer = new StreamWriter(stream, Encoding);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
@@ -305,7 +305,7 @@ namespace HostsUILib.Helpers
|
||||
|
||||
public void RemoveReadOnlyAttribute()
|
||||
{
|
||||
var fileInfo = _fileSystem.FileInfo.FromFileName(HostsFilePath);
|
||||
var fileInfo = _fileSystem.FileInfo.New(HostsFilePath);
|
||||
if (fileInfo.IsReadOnly)
|
||||
{
|
||||
fileInfo.IsReadOnly = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" />
|
||||
<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">
|
||||
@@ -141,7 +141,7 @@
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
@@ -153,7 +153,7 @@
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2739.15\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.240923002\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.6.241114003\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -4,5 +4,5 @@
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.2428" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.6.240923002" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.6.241114003" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -2,8 +2,9 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using MouseJump.Common.Helpers;
|
||||
using MouseJump.Common.Imaging;
|
||||
@@ -16,7 +17,7 @@ namespace MouseJump.Common.UnitTests.Helpers;
|
||||
public static class DrawingHelperTests
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class GetPreviewLayoutTests
|
||||
public sealed class RenderPreviewTests
|
||||
{
|
||||
public sealed class TestCase
|
||||
{
|
||||
@@ -46,7 +47,7 @@ public static class DrawingHelperTests
|
||||
yield return new object[]
|
||||
{
|
||||
new TestCase(
|
||||
previewStyle: StyleHelper.DefaultPreviewStyle,
|
||||
previewStyle: StyleHelper.BezelledPreviewStyle,
|
||||
screens: new List<RectangleInfo>()
|
||||
{
|
||||
new(0, 0, 500, 500),
|
||||
@@ -62,7 +63,7 @@ public static class DrawingHelperTests
|
||||
yield return new object[]
|
||||
{
|
||||
new TestCase(
|
||||
previewStyle: StyleHelper.DefaultPreviewStyle,
|
||||
previewStyle: StyleHelper.BezelledPreviewStyle,
|
||||
screens: new List<RectangleInfo>()
|
||||
{
|
||||
new(5120, 349, 1920, 1080),
|
||||
@@ -79,7 +80,7 @@ public static class DrawingHelperTests
|
||||
public void RunTestCases(TestCase data)
|
||||
{
|
||||
// load the fake desktop image
|
||||
using var desktopImage = GetPreviewLayoutTests.LoadImageResource(data.DesktopImageFilename);
|
||||
using var desktopImage = RenderPreviewTests.LoadImageResource(data.DesktopImageFilename);
|
||||
|
||||
// draw the preview image
|
||||
var previewLayout = LayoutHelper.GetPreviewLayout(
|
||||
@@ -90,28 +91,29 @@ public static class DrawingHelperTests
|
||||
using var actual = DrawingHelper.RenderPreview(previewLayout, imageCopyService);
|
||||
|
||||
// load the expected image
|
||||
var expected = GetPreviewLayoutTests.LoadImageResource(data.ExpectedImageFilename);
|
||||
var expected = RenderPreviewTests.LoadImageResource(data.ExpectedImageFilename);
|
||||
|
||||
// compare the images
|
||||
var screens = System.Windows.Forms.Screen.AllScreens;
|
||||
AssertImagesEqual(expected, actual);
|
||||
}
|
||||
|
||||
private static Bitmap LoadImageResource(string filename)
|
||||
{
|
||||
// assume embedded resources are in the same source folder as this
|
||||
// class, and the namespace hierarchy matches the folder structure.
|
||||
// that way we can build resource names from the current namespace
|
||||
var resourcePrefix = typeof(DrawingHelperTests).Namespace;
|
||||
var resourceName = $"{resourcePrefix}.{filename}";
|
||||
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var assemblyName = new AssemblyName(assembly.FullName ?? throw new InvalidOperationException());
|
||||
var resourceName = $"{typeof(DrawingHelperTests).Namespace}.{filename.Replace("/", ".")}";
|
||||
var resourceNames = assembly.GetManifestResourceNames();
|
||||
if (!resourceNames.Contains(resourceName))
|
||||
{
|
||||
var message = $"Embedded resource '{resourceName}' does not exist. " +
|
||||
"Valid resource names are: \r\n" + string.Join("\r\n", resourceNames);
|
||||
throw new InvalidOperationException(message);
|
||||
var message = new StringBuilder();
|
||||
message.AppendLine(CultureInfo.InvariantCulture, $"Embedded resource '{resourceName}' does not exist.");
|
||||
message.AppendLine($"Known resources:");
|
||||
foreach (var name in resourceNames)
|
||||
{
|
||||
message.AppendLine(name);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(message.ToString());
|
||||
}
|
||||
|
||||
var stream = assembly.GetManifestResourceStream(resourceName)
|
||||
@@ -121,7 +123,7 @@ public static class DrawingHelperTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Naive / brute force image comparison - we can optimise this later :-)
|
||||
/// Naive / brute force image comparison - we can optimize this later :-)
|
||||
/// </summary>
|
||||
private static void AssertImagesEqual(Bitmap expected, Bitmap actual)
|
||||
{
|
||||
|
||||
@@ -129,7 +129,7 @@ public static class LayoutHelperTests
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
// happy path - single screen with 50% scaling,
|
||||
// *has* a preview borders but *no* screenshot borders
|
||||
// *has* a preview border but *no* screenshot borders
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
@@ -160,7 +160,7 @@ public static class LayoutHelperTests
|
||||
new(0, 0, 1024, 768),
|
||||
};
|
||||
var activatedLocation = new PointInfo(512, 384);
|
||||
var previewLayout = new PreviewLayout(
|
||||
var expectedResult = new PreviewLayout(
|
||||
virtualScreen: new(0, 0, 1024, 768),
|
||||
screens: screens,
|
||||
activatedScreenIndex: 0,
|
||||
@@ -183,7 +183,7 @@ public static class LayoutHelperTests
|
||||
contentBounds: new(6, 6, 512, 384)
|
||||
),
|
||||
});
|
||||
yield return new object[] { new TestCase(previewStyle, screens, activatedLocation, previewLayout) };
|
||||
yield return new object[] { new TestCase(previewStyle, screens, activatedLocation, expectedResult) };
|
||||
|
||||
// happy path - single screen with 50% scaling,
|
||||
// *no* preview borders but *has* screenshot borders
|
||||
@@ -217,7 +217,7 @@ public static class LayoutHelperTests
|
||||
new(0, 0, 1024, 768),
|
||||
};
|
||||
activatedLocation = new PointInfo(512, 384);
|
||||
previewLayout = new PreviewLayout(
|
||||
expectedResult = new PreviewLayout(
|
||||
virtualScreen: new(0, 0, 1024, 768),
|
||||
screens: screens,
|
||||
activatedScreenIndex: 0,
|
||||
@@ -240,7 +240,59 @@ public static class LayoutHelperTests
|
||||
contentBounds: new(6, 6, 500, 372)
|
||||
),
|
||||
});
|
||||
yield return new object[] { new TestCase(previewStyle, screens, activatedLocation, previewLayout) };
|
||||
yield return new object[] { new TestCase(previewStyle, screens, activatedLocation, expectedResult) };
|
||||
|
||||
// rounding error check - single screen with 33% scaling,
|
||||
// no borders, check to make sure form scales to exactly
|
||||
// fill the canvas size with no rounding errors.
|
||||
//
|
||||
// in this test the preview width is 300 and the desktop is
|
||||
// 900, so the scaling factor is 1/3, but this gets rounded
|
||||
// to 0.3333333333333333333333333333, and 900 times this value
|
||||
// is 299.99999999999999999999999997. if we don't scale correctly
|
||||
// the resulting form width might only be 299 pixels instead of 300
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | 0 |
|
||||
// | |
|
||||
// +----------------+
|
||||
previewStyle = new PreviewStyle(
|
||||
canvasSize: new(
|
||||
width: 300,
|
||||
height: 200
|
||||
),
|
||||
canvasStyle: BoxStyle.Empty,
|
||||
screenStyle: BoxStyle.Empty);
|
||||
screens = new List<RectangleInfo>
|
||||
{
|
||||
new(0, 0, 900, 200),
|
||||
};
|
||||
activatedLocation = new PointInfo(450, 100);
|
||||
expectedResult = new PreviewLayout(
|
||||
virtualScreen: new(0, 0, 900, 200),
|
||||
screens: screens,
|
||||
activatedScreenIndex: 0,
|
||||
formBounds: new(300, 66.5m, 300, 67),
|
||||
previewStyle: previewStyle,
|
||||
previewBounds: new(
|
||||
outerBounds: new(0, 0, 300, 67),
|
||||
marginBounds: new(0, 0, 300, 67),
|
||||
borderBounds: new(0, 0, 300, 67),
|
||||
paddingBounds: new(0, 0, 300, 67),
|
||||
contentBounds: new(0, 0, 300, 67)
|
||||
),
|
||||
screenshotBounds: new()
|
||||
{
|
||||
new(
|
||||
outerBounds: new(0, 0, 300, 67),
|
||||
marginBounds: new(0, 0, 300, 67),
|
||||
borderBounds: new(0, 0, 300, 67),
|
||||
paddingBounds: new(0, 0, 300, 67),
|
||||
contentBounds: new(0, 0, 300, 67)
|
||||
),
|
||||
});
|
||||
yield return new object[] { new TestCase(previewStyle, screens, activatedLocation, expectedResult) };
|
||||
|
||||
// primary monitor not topmost / leftmost - if there are screens
|
||||
// that are further left or higher up than the primary monitor
|
||||
@@ -291,7 +343,7 @@ public static class LayoutHelperTests
|
||||
new(0, 0, 5120, 1440),
|
||||
};
|
||||
activatedLocation = new(-960, 60);
|
||||
previewLayout = new PreviewLayout(
|
||||
expectedResult = new PreviewLayout(
|
||||
virtualScreen: new(-1920, -480, 7040, 1920),
|
||||
screens: screens,
|
||||
activatedScreenIndex: 0,
|
||||
@@ -321,7 +373,7 @@ public static class LayoutHelperTests
|
||||
contentBounds: new(204, 60, 500, 132)
|
||||
),
|
||||
});
|
||||
yield return new object[] { new TestCase(previewStyle, screens, activatedLocation, previewLayout) };
|
||||
yield return new object[] { new TestCase(previewStyle, screens, activatedLocation, expectedResult) };
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 202 KiB |
@@ -15,45 +15,49 @@ public static class SizeInfoTests
|
||||
{
|
||||
public sealed class TestCase
|
||||
{
|
||||
public TestCase(SizeInfo obj, SizeInfo bounds, SizeInfo expectedResult)
|
||||
public TestCase(SizeInfo source, SizeInfo bounds, SizeInfo expectedResult, decimal scalingRatio)
|
||||
{
|
||||
this.Obj = obj;
|
||||
this.Source = source;
|
||||
this.Bounds = bounds;
|
||||
this.ExpectedResult = expectedResult;
|
||||
this.ScalingRatio = scalingRatio;
|
||||
}
|
||||
|
||||
public SizeInfo Obj { get; }
|
||||
public SizeInfo Source { get; }
|
||||
|
||||
public SizeInfo Bounds { get; }
|
||||
|
||||
public SizeInfo ExpectedResult { get; }
|
||||
|
||||
public decimal ScalingRatio { get; }
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
// identity tests
|
||||
yield return new object[] { new TestCase(new(512, 384), new(512, 384), new(512, 384)), };
|
||||
yield return new object[] { new TestCase(new(1024, 768), new(1024, 768), new(1024, 768)), };
|
||||
yield return new object[] { new TestCase(new(512, 384), new(512, 384), new(512, 384), 1), };
|
||||
yield return new object[] { new TestCase(new(1024, 768), new(1024, 768), new(1024, 768), 1), };
|
||||
|
||||
// general tests
|
||||
yield return new object[] { new TestCase(new(512, 384), new(2048, 1536), new(2048, 1536)), };
|
||||
yield return new object[] { new TestCase(new(2048, 1536), new(1024, 768), new(1024, 768)), };
|
||||
yield return new object[] { new TestCase(new(512, 384), new(2048, 1536), new(2048, 1536), 4), };
|
||||
yield return new object[] { new TestCase(new(2048, 1536), new(1024, 768), new(1024, 768), 0.5m), };
|
||||
|
||||
// scale to fit width
|
||||
yield return new object[] { new TestCase(new(512, 384), new(2048, 3072), new(2048, 1536)), };
|
||||
yield return new object[] { new TestCase(new(512, 384), new(2048, 3072), new(2048, 1536), 4), };
|
||||
|
||||
// scale to fit height
|
||||
yield return new object[] { new TestCase(new(512, 384), new(4096, 1536), new(2048, 1536)), };
|
||||
yield return new object[] { new TestCase(new(512, 384), new(4096, 1536), new(2048, 1536), 4), };
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DynamicData(nameof(GetTestCases), DynamicDataSourceType.Method)]
|
||||
public void RunTestCases(TestCase data)
|
||||
{
|
||||
var actual = data.Obj.ScaleToFit(data.Bounds);
|
||||
var actual = data.Source.ScaleToFit(data.Bounds, out var scalingRatio);
|
||||
var expected = data.ExpectedResult;
|
||||
Assert.AreEqual(expected.Width, actual.Width);
|
||||
Assert.AreEqual(expected.Height, actual.Height);
|
||||
Assert.AreEqual(scalingRatio, data.ScalingRatio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
namespace MouseJump.Common.Helpers;
|
||||
|
||||
public static class ConfigHelper
|
||||
{
|
||||
public static Color? ToUnnamedColor(Color? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var color = value.Value;
|
||||
return Color.FromArgb(color.A, color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static string? SerializeToConfigColorString(Color? value)
|
||||
{
|
||||
if (!value.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var color = value.Value;
|
||||
return color switch
|
||||
{
|
||||
Color { IsNamedColor: true } =>
|
||||
$"{nameof(Color)}.{color.Name}",
|
||||
Color { IsSystemColor: true } =>
|
||||
$"{nameof(SystemColors)}.{color.Name}",
|
||||
_ =>
|
||||
$"#{color.R:X2}{color.G:X2}{color.B:X2}",
|
||||
};
|
||||
}
|
||||
|
||||
public static Color? DeserializeFromConfigColorString(string? value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// e.g. "#AABBCC"
|
||||
if (value.StartsWith('#'))
|
||||
{
|
||||
var culture = CultureInfo.InvariantCulture;
|
||||
if ((value.Length == 7)
|
||||
&& int.TryParse(value[1..3], NumberStyles.HexNumber, culture, out var r)
|
||||
&& int.TryParse(value[3..5], NumberStyles.HexNumber, culture, out var g)
|
||||
&& int.TryParse(value[5..7], NumberStyles.HexNumber, culture, out var b))
|
||||
{
|
||||
return Color.FromArgb(0xFF, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
const StringComparison comparison = StringComparison.InvariantCulture;
|
||||
|
||||
// e.g. "Color.Red"
|
||||
const string colorPrefix = $"{nameof(Color)}.";
|
||||
if (value.StartsWith(colorPrefix, comparison))
|
||||
{
|
||||
var colorName = value[colorPrefix.Length..];
|
||||
var property = typeof(Color).GetProperties()
|
||||
.SingleOrDefault(property => property.Name == colorName);
|
||||
if (property is not null)
|
||||
{
|
||||
return (Color?)property.GetValue(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
// e.g. "SystemColors.Highlight"
|
||||
const string systemColorPrefix = $"{nameof(SystemColors)}.";
|
||||
if (value.StartsWith(systemColorPrefix, comparison))
|
||||
{
|
||||
var colorName = value[systemColorPrefix.Length..];
|
||||
var property = typeof(SystemColors).GetProperties()
|
||||
.SingleOrDefault(property => property.Name == colorName);
|
||||
if (property is not null)
|
||||
{
|
||||
return (Color?)property.GetValue(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -102,8 +102,13 @@ public static class DrawingHelper
|
||||
return;
|
||||
}
|
||||
|
||||
if (borderStyle.Color is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// draw the main box border
|
||||
using var borderBrush = new SolidBrush(borderStyle.Color);
|
||||
using var borderBrush = new SolidBrush(borderStyle.Color.Value);
|
||||
var borderRegion = new Region(boxBounds.BorderBounds.ToRectangle());
|
||||
borderRegion.Exclude(boxBounds.PaddingBounds.ToRectangle());
|
||||
graphics.FillRegion(borderBrush, borderRegion);
|
||||
|
||||
@@ -46,16 +46,13 @@ public static class LayoutHelper
|
||||
.Shrink(previewStyle.CanvasStyle.BorderStyle)
|
||||
.Shrink(previewStyle.CanvasStyle.PaddingStyle);
|
||||
|
||||
// scale the virtual screen to fit inside the content area
|
||||
var screenScalingRatio = builder.VirtualScreen.Size
|
||||
.ScaleToFitRatio(maxContentSize);
|
||||
|
||||
// work out the actual size of the "content area" by scaling the virtual screen
|
||||
// to fit inside the maximum content area while maintaining its aspect ration.
|
||||
// we'll also offset it to allow for any margins, borders and padding
|
||||
var contentBounds = builder.VirtualScreen.Size
|
||||
.Scale(screenScalingRatio)
|
||||
.Floor()
|
||||
.ScaleToFit(maxContentSize, out var scalingRatio)
|
||||
.Round()
|
||||
.Clamp(maxContentSize)
|
||||
.PlaceAt(0, 0)
|
||||
.Offset(previewStyle.CanvasStyle.MarginStyle.Left, previewStyle.CanvasStyle.MarginStyle.Top)
|
||||
.Offset(previewStyle.CanvasStyle.BorderStyle.Left, previewStyle.CanvasStyle.BorderStyle.Top)
|
||||
@@ -82,16 +79,16 @@ public static class LayoutHelper
|
||||
screen => LayoutHelper.GetBoxBoundsFromOuterBounds(
|
||||
screen
|
||||
.Offset(builder.VirtualScreen.Location.ToSize().Invert())
|
||||
.Scale(screenScalingRatio)
|
||||
.Scale(scalingRatio)
|
||||
.Offset(builder.PreviewBounds.ContentBounds.Location.ToSize())
|
||||
.Truncate(),
|
||||
.Round(),
|
||||
previewStyle.ScreenStyle))
|
||||
.ToList();
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
internal static RectangleInfo GetCombinedScreenBounds(List<RectangleInfo> screens)
|
||||
public static RectangleInfo GetCombinedScreenBounds(List<RectangleInfo> screens)
|
||||
{
|
||||
return screens.Skip(1).Aggregate(
|
||||
seed: screens.First(),
|
||||
|
||||
@@ -102,7 +102,7 @@ public static class MouseHelper
|
||||
/// See https://github.com/microsoft/PowerToys/issues/24523
|
||||
/// https://github.com/microsoft/PowerToys/pull/24527
|
||||
/// </remarks>
|
||||
internal static void SimulateMouseMovementEvent(PointInfo location)
|
||||
private static void SimulateMouseMovementEvent(PointInfo location)
|
||||
{
|
||||
var inputs = new User32.INPUT[]
|
||||
{
|
||||
|
||||
@@ -10,49 +10,9 @@ namespace MouseJump.Common.Helpers;
|
||||
public static class StyleHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Default v2 preview style
|
||||
/// Compact (legacy) preview style
|
||||
/// </summary>
|
||||
public static readonly PreviewStyle DefaultPreviewStyle = new(
|
||||
canvasSize: new(
|
||||
width: 1600,
|
||||
height: 1200
|
||||
),
|
||||
canvasStyle: new(
|
||||
marginStyle: MarginStyle.Empty,
|
||||
borderStyle: new(
|
||||
color: SystemColors.Highlight,
|
||||
all: 6,
|
||||
depth: 0
|
||||
),
|
||||
paddingStyle: new(
|
||||
all: 4
|
||||
),
|
||||
backgroundStyle: new(
|
||||
color1: Color.FromArgb(0xFF, 0x0D, 0x57, 0xD2),
|
||||
color2: Color.FromArgb(0xFF, 0x03, 0x44, 0xC0)
|
||||
)
|
||||
),
|
||||
screenStyle: new(
|
||||
marginStyle: new(
|
||||
all: 4
|
||||
),
|
||||
borderStyle: new(
|
||||
color: Color.FromArgb(0xFF, 0x22, 0x22, 0x22),
|
||||
all: 12,
|
||||
depth: 4
|
||||
),
|
||||
paddingStyle: PaddingStyle.Empty,
|
||||
backgroundStyle: new(
|
||||
color1: Color.MidnightBlue,
|
||||
color2: Color.MidnightBlue
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Legacy preview style
|
||||
/// </summary>
|
||||
public static readonly PreviewStyle LegacyPreviewStyle = new(
|
||||
public static readonly PreviewStyle CompactPreviewStyle = new(
|
||||
canvasSize: new(
|
||||
width: 1600,
|
||||
height: 1200
|
||||
@@ -89,6 +49,46 @@ public static class StyleHelper
|
||||
)
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Bezelled preview style
|
||||
/// </summary>
|
||||
public static readonly PreviewStyle BezelledPreviewStyle = new(
|
||||
canvasSize: new(
|
||||
width: 1600,
|
||||
height: 1200
|
||||
),
|
||||
canvasStyle: new(
|
||||
marginStyle: MarginStyle.Empty,
|
||||
borderStyle: new(
|
||||
color: SystemColors.Highlight,
|
||||
all: 6,
|
||||
depth: 0
|
||||
),
|
||||
paddingStyle: new(
|
||||
all: 4
|
||||
),
|
||||
backgroundStyle: new(
|
||||
color1: Color.FromArgb(0xFF, 0x0D, 0x57, 0xD2),
|
||||
color2: Color.FromArgb(0xFF, 0x03, 0x44, 0xC0)
|
||||
)
|
||||
),
|
||||
screenStyle: new(
|
||||
marginStyle: new(
|
||||
all: 4
|
||||
),
|
||||
borderStyle: new(
|
||||
color: Color.FromArgb(0xFF, 0x22, 0x22, 0x22),
|
||||
all: 12,
|
||||
depth: 4
|
||||
),
|
||||
paddingStyle: PaddingStyle.Empty,
|
||||
backgroundStyle: new(
|
||||
color1: Color.MidnightBlue,
|
||||
color2: Color.MidnightBlue
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
public static PreviewStyle WithCanvasSize(this PreviewStyle previewStyle, SizeInfo canvasSize)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(previewStyle);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// 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.Drawing.Drawing2D;
|
||||
|
||||
using MouseJump.Common.Models.Drawing;
|
||||
|
||||
namespace MouseJump.Common.Imaging;
|
||||
@@ -31,6 +33,11 @@ public sealed class StaticImageRegionCopyService : IImageRegionCopyService
|
||||
RectangleInfo sourceBounds,
|
||||
RectangleInfo targetBounds)
|
||||
{
|
||||
// prevent the background bleeding through into screen images
|
||||
// (see https://github.com/mikeclayton/FancyMouse/issues/44)
|
||||
targetGraphics.PixelOffsetMode = PixelOffsetMode.Half;
|
||||
targetGraphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
|
||||
targetGraphics.DrawImage(
|
||||
image: this.SourceImage,
|
||||
destRect: targetBounds.ToRectangle(),
|
||||
|
||||
@@ -203,6 +203,15 @@ public sealed class RectangleInfo
|
||||
public RectangleInfo Offset(decimal dx, decimal dy) =>
|
||||
new(this.X + dx, this.Y + dy, this.Width, this.Height);
|
||||
|
||||
public RectangleInfo Round() =>
|
||||
this.Round(0);
|
||||
|
||||
public RectangleInfo Round(int decimals) => new(
|
||||
Math.Round(this.X, decimals),
|
||||
Math.Round(this.Y, decimals),
|
||||
Math.Round(this.Width, decimals),
|
||||
Math.Round(this.Height, decimals));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="RectangleInfo"/> that is a scaled version of the current rectangle.
|
||||
/// The dimensions of the new rectangle are calculated by multiplying the current rectangle's dimensions by the scaling factor.
|
||||
|
||||
@@ -12,6 +12,8 @@ public sealed class ScreenInfo
|
||||
{
|
||||
public ScreenInfo(int handle, bool primary, RectangleInfo displayArea, RectangleInfo workingArea)
|
||||
{
|
||||
// this.Handle is a HMONITOR that has been cast to an int because we don't want
|
||||
// to expose the HMONITOR type outside the current assembly.
|
||||
this.Handle = handle;
|
||||
this.Primary = primary;
|
||||
this.DisplayArea = displayArea ?? throw new ArgumentNullException(nameof(displayArea));
|
||||
|
||||
@@ -33,6 +33,20 @@ public sealed class SizeInfo
|
||||
get;
|
||||
}
|
||||
|
||||
public SizeInfo Clamp(SizeInfo max)
|
||||
{
|
||||
return new(
|
||||
width: Math.Clamp(this.Width, 0, max.Width),
|
||||
height: Math.Clamp(this.Height, 0, max.Height));
|
||||
}
|
||||
|
||||
public SizeInfo Clamp(decimal maxWidth, decimal maxHeight)
|
||||
{
|
||||
return new(
|
||||
width: Math.Clamp(this.Width, 0, maxWidth),
|
||||
height: Math.Clamp(this.Height, 0, maxHeight));
|
||||
}
|
||||
|
||||
public SizeInfo Enlarge(BorderStyle border) =>
|
||||
new(
|
||||
this.Width + border.Horizontal,
|
||||
@@ -43,6 +57,17 @@ public sealed class SizeInfo
|
||||
this.Width + padding.Horizontal,
|
||||
this.Height + padding.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Rounds down the width and height of this size to the nearest whole number.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="SizeInfo"/> instance with floored dimensions.</returns>
|
||||
public SizeInfo Floor()
|
||||
{
|
||||
return new SizeInfo(
|
||||
Math.Floor(this.Width),
|
||||
Math.Floor(this.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the intersection of this size with another size, resulting in a size that represents
|
||||
/// the overlapping dimensions. Both sizes must be non-negative.
|
||||
@@ -69,19 +94,6 @@ public sealed class SizeInfo
|
||||
public SizeInfo Invert() =>
|
||||
new(-this.Width, -this.Height);
|
||||
|
||||
public SizeInfo Scale(decimal scalingFactor) => new(
|
||||
this.Width * scalingFactor,
|
||||
this.Height * scalingFactor);
|
||||
|
||||
public SizeInfo Shrink(BorderStyle border) =>
|
||||
new(this.Width - border.Horizontal, this.Height - border.Vertical);
|
||||
|
||||
public SizeInfo Shrink(MarginStyle margin) =>
|
||||
new(this.Width - margin.Horizontal, this.Height - margin.Vertical);
|
||||
|
||||
public SizeInfo Shrink(PaddingStyle padding) =>
|
||||
new(this.Width - padding.Horizontal, this.Height - padding.Vertical);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RectangleInfo"/> instance representing a rectangle with this size,
|
||||
/// positioned at the specified coordinates.
|
||||
@@ -92,32 +104,39 @@ public sealed class SizeInfo
|
||||
public RectangleInfo PlaceAt(decimal x, decimal y) =>
|
||||
new(x, y, this.Width, this.Height);
|
||||
|
||||
public SizeInfo Round() =>
|
||||
this.Round(0);
|
||||
|
||||
public SizeInfo Round(int decimals) => new(
|
||||
Math.Round(this.Width, decimals),
|
||||
Math.Round(this.Height, decimals));
|
||||
|
||||
public SizeInfo Scale(decimal scalingFactor) => new(
|
||||
this.Width * scalingFactor,
|
||||
this.Height * scalingFactor);
|
||||
|
||||
/// <summary>
|
||||
/// Scales this size to fit within the bounds of another size, while maintaining the aspect ratio.
|
||||
/// </summary>
|
||||
/// <param name="bounds">The size to fit this size into.</param>
|
||||
/// <returns>A new <see cref="SizeInfo"/> instance representing the scaled size.</returns>
|
||||
public SizeInfo ScaleToFit(SizeInfo bounds)
|
||||
public SizeInfo ScaleToFit(SizeInfo bounds, out decimal scalingRatio)
|
||||
{
|
||||
var widthRatio = bounds.Width / this.Width;
|
||||
var heightRatio = bounds.Height / this.Height;
|
||||
return widthRatio.CompareTo(heightRatio) switch
|
||||
switch (widthRatio.CompareTo(heightRatio))
|
||||
{
|
||||
< 0 => new(bounds.Width, this.Height * widthRatio),
|
||||
0 => bounds,
|
||||
> 0 => new(this.Width * heightRatio, bounds.Height),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rounds down the width and height of this size to the nearest whole number.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="SizeInfo"/> instance with floored dimensions.</returns>
|
||||
public SizeInfo Floor()
|
||||
{
|
||||
return new SizeInfo(
|
||||
Math.Floor(this.Width),
|
||||
Math.Floor(this.Height));
|
||||
case < 0:
|
||||
scalingRatio = widthRatio;
|
||||
return new(bounds.Width, this.Height * widthRatio);
|
||||
case 0:
|
||||
// widthRatio and heightRatio are the same, so just pick one
|
||||
scalingRatio = widthRatio;
|
||||
return bounds;
|
||||
case > 0:
|
||||
scalingRatio = heightRatio;
|
||||
return new(this.Width * heightRatio, bounds.Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -140,6 +159,15 @@ public sealed class SizeInfo
|
||||
return scalingRatio;
|
||||
}
|
||||
|
||||
public SizeInfo Shrink(BorderStyle border) =>
|
||||
new(this.Width - border.Horizontal, this.Height - border.Vertical);
|
||||
|
||||
public SizeInfo Shrink(MarginStyle margin) =>
|
||||
new(this.Width - margin.Horizontal, this.Height - margin.Vertical);
|
||||
|
||||
public SizeInfo Shrink(PaddingStyle padding) =>
|
||||
new(this.Width - padding.Horizontal, this.Height - padding.Vertical);
|
||||
|
||||
public Size ToSize() => new((int)this.Width, (int)this.Height);
|
||||
|
||||
public Point ToPoint() => new((int)this.Width, (int)this.Height);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace MouseJump.Common.Models.Settings;
|
||||
|
||||
public enum PreviewType
|
||||
{
|
||||
Custom = 0,
|
||||
Compact = 1,
|
||||
Bezelled = 2,
|
||||
}
|
||||
@@ -9,14 +9,14 @@ namespace MouseJump.Common.Models.Styles;
|
||||
/// </summary>
|
||||
public sealed class BorderStyle
|
||||
{
|
||||
public static readonly BorderStyle Empty = new(Color.Transparent, 0, 0);
|
||||
public static readonly BorderStyle Empty = new(null, 0, 0);
|
||||
|
||||
public BorderStyle(Color color, decimal all, decimal depth)
|
||||
public BorderStyle(Color? color, decimal all, decimal depth)
|
||||
: this(color, all, all, all, all, depth)
|
||||
{
|
||||
}
|
||||
|
||||
public BorderStyle(Color color, decimal left, decimal top, decimal right, decimal bottom, decimal depth)
|
||||
public BorderStyle(Color? color, decimal left, decimal top, decimal right, decimal bottom, decimal depth)
|
||||
{
|
||||
this.Color = color;
|
||||
this.Left = left;
|
||||
@@ -26,7 +26,7 @@ public sealed class BorderStyle
|
||||
this.Depth = depth;
|
||||
}
|
||||
|
||||
public Color Color
|
||||
public Color? Color
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ using System.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using MouseJump.Common.Helpers;
|
||||
using MouseJump.Common.Models.Drawing;
|
||||
using MouseJump.Common.Models.Settings;
|
||||
using MouseJump.Common.Models.Styles;
|
||||
|
||||
namespace MouseJumpUI.Helpers;
|
||||
|
||||
@@ -93,4 +97,65 @@ internal sealed class SettingsHelper
|
||||
{
|
||||
this.CurrentSettings = this.LoadSettings();
|
||||
}
|
||||
|
||||
public static PreviewStyle GetActivePreviewStyle(MouseJumpSettings settings)
|
||||
{
|
||||
var previewType = Enum.TryParse<PreviewType>(settings.Properties.PreviewType, true, out var previewTypeResult)
|
||||
? previewTypeResult
|
||||
: PreviewType.Bezelled;
|
||||
|
||||
var canvasSize = new SizeInfo(
|
||||
settings.Properties.ThumbnailSize.Width,
|
||||
settings.Properties.ThumbnailSize.Height);
|
||||
|
||||
var properties = settings.Properties;
|
||||
|
||||
var previewStyle = previewType switch
|
||||
{
|
||||
PreviewType.Compact => StyleHelper.CompactPreviewStyle.WithCanvasSize(canvasSize),
|
||||
PreviewType.Bezelled => StyleHelper.BezelledPreviewStyle.WithCanvasSize(canvasSize),
|
||||
PreviewType.Custom => new PreviewStyle(
|
||||
canvasSize: canvasSize,
|
||||
canvasStyle: new(
|
||||
marginStyle: new(0),
|
||||
borderStyle: new(
|
||||
color: ConfigHelper.DeserializeFromConfigColorString(
|
||||
properties.BorderColor),
|
||||
all: properties.BorderThickness,
|
||||
depth: properties.Border3dDepth
|
||||
),
|
||||
paddingStyle: new(
|
||||
all: properties.BorderPadding
|
||||
),
|
||||
backgroundStyle: new(
|
||||
color1: ConfigHelper.DeserializeFromConfigColorString(
|
||||
properties.BackgroundColor1),
|
||||
color2: ConfigHelper.DeserializeFromConfigColorString(
|
||||
properties.BackgroundColor2)
|
||||
)
|
||||
),
|
||||
screenStyle: new(
|
||||
marginStyle: new(
|
||||
all: properties.ScreenMargin
|
||||
),
|
||||
borderStyle: new(
|
||||
color: ConfigHelper.DeserializeFromConfigColorString(
|
||||
properties.BezelColor),
|
||||
all: properties.BezelThickness,
|
||||
depth: properties.Bezel3dDepth
|
||||
),
|
||||
paddingStyle: new(0),
|
||||
backgroundStyle: new(
|
||||
color1: ConfigHelper.DeserializeFromConfigColorString(
|
||||
properties.ScreenColor1),
|
||||
color2: ConfigHelper.DeserializeFromConfigColorString(
|
||||
properties.ScreenColor2)
|
||||
)
|
||||
)),
|
||||
_ => throw new InvalidOperationException(
|
||||
$"Unhandled {nameof(PreviewType)} '{previewType}'"),
|
||||
};
|
||||
|
||||
return previewStyle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace MouseJumpUI.Helpers;
|
||||
|
||||
internal sealed class ThrottledActionInvoker
|
||||
{
|
||||
private readonly object _invokerLock = new();
|
||||
private readonly Lock _invokerLock = new();
|
||||
private readonly DispatcherTimer _timer;
|
||||
|
||||
private Action? _actionToRun;
|
||||
|
||||
@@ -183,12 +183,9 @@ internal sealed partial class MainForm : Form
|
||||
var appSettings = this.SettingsHelper.CurrentSettings ?? throw new InvalidOperationException();
|
||||
var screens = ScreenHelper.GetAllScreens().Select(screen => screen.DisplayArea).ToList();
|
||||
var activatedLocation = MouseHelper.GetCursorPosition();
|
||||
|
||||
this.PreviewLayout = LayoutHelper.GetPreviewLayout(
|
||||
previewStyle: StyleHelper.LegacyPreviewStyle.WithCanvasSize(
|
||||
new(
|
||||
appSettings.Properties.ThumbnailSize.Width,
|
||||
appSettings.Properties.ThumbnailSize.Height
|
||||
)),
|
||||
previewStyle: SettingsHelper.GetActivePreviewStyle(appSettings),
|
||||
screens: screens,
|
||||
activatedLocation: activatedLocation);
|
||||
|
||||
|
||||
@@ -1,60 +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.Windows.Forms;
|
||||
|
||||
namespace MouseJumpUI.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Windows.Forms.Padding object with some extra utility methods.
|
||||
/// </summary>
|
||||
public sealed class PaddingInfo
|
||||
{
|
||||
public PaddingInfo(decimal all)
|
||||
: this(all, all, all, all)
|
||||
{
|
||||
}
|
||||
|
||||
public PaddingInfo(decimal left, decimal top, decimal right, decimal bottom)
|
||||
{
|
||||
this.Left = left;
|
||||
this.Top = top;
|
||||
this.Right = right;
|
||||
this.Bottom = bottom;
|
||||
}
|
||||
|
||||
public decimal Left
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Top
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Right
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Bottom
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Horizontal => this.Left + this.Right;
|
||||
|
||||
public decimal Vertical => this.Top + this.Bottom;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Left)}={this.Left}," +
|
||||
$"{nameof(this.Top)}={this.Top}," +
|
||||
$"{nameof(this.Right)}={this.Right}," +
|
||||
$"{nameof(this.Bottom)}={this.Bottom}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -1,53 +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.Drawing;
|
||||
|
||||
namespace MouseJumpUI.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Drawing.Point object with some extra utility methods.
|
||||
/// </summary>
|
||||
public sealed class PointInfo
|
||||
{
|
||||
public PointInfo(decimal x, decimal y)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
}
|
||||
|
||||
public PointInfo(Point point)
|
||||
: this(point.X, point.Y)
|
||||
{
|
||||
}
|
||||
|
||||
public decimal X
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Y
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public SizeInfo ToSize()
|
||||
{
|
||||
return new((int)this.X, (int)this.Y);
|
||||
}
|
||||
|
||||
public PointInfo Scale(decimal scalingFactor) => new(this.X * scalingFactor, this.Y * scalingFactor);
|
||||
|
||||
public PointInfo Offset(PointInfo amount) => new(this.X + amount.X, this.Y + amount.Y);
|
||||
|
||||
public Point ToPoint() => new((int)this.X, (int)this.Y);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.X)}={this.X}," +
|
||||
$"{nameof(this.Y)}={this.Y}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -1,131 +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.Drawing;
|
||||
|
||||
namespace MouseJumpUI.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Drawing.Rectangle object with some extra utility methods.
|
||||
/// </summary>
|
||||
public sealed class RectangleInfo
|
||||
{
|
||||
public RectangleInfo(decimal x, decimal y, decimal width, decimal height)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.Width = width;
|
||||
this.Height = height;
|
||||
}
|
||||
|
||||
public RectangleInfo(Rectangle rectangle)
|
||||
: this(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public RectangleInfo(Point location, SizeInfo size)
|
||||
: this(location.X, location.Y, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public RectangleInfo(SizeInfo size)
|
||||
: this(0, 0, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public decimal X
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Y
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Width
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Height
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Left => this.X;
|
||||
|
||||
public decimal Top => this.Y;
|
||||
|
||||
public decimal Right => this.X + this.Width;
|
||||
|
||||
public decimal Bottom => this.Y + this.Height;
|
||||
|
||||
public SizeInfo Size => new(this.Width, this.Height);
|
||||
|
||||
public PointInfo Location => new(this.X, this.Y);
|
||||
|
||||
public decimal Area => this.Width * this.Height;
|
||||
|
||||
/// <remarks>
|
||||
/// Adapted from https://github.com/dotnet/runtime
|
||||
/// See https://github.com/dotnet/runtime/blob/dfd618dc648ba9b11dd0f8034f78113d69f223cd/src/libraries/System.Drawing.Primitives/src/System/Drawing/Rectangle.cs
|
||||
/// </remarks>
|
||||
public bool Contains(RectangleInfo rect) =>
|
||||
(this.X <= rect.X) && (rect.X + rect.Width <= this.X + this.Width) &&
|
||||
(this.Y <= rect.Y) && (rect.Y + rect.Height <= this.Y + this.Height);
|
||||
|
||||
public RectangleInfo Enlarge(PaddingInfo padding) => new(
|
||||
this.X + padding.Left,
|
||||
this.Y + padding.Top,
|
||||
this.Width + padding.Horizontal,
|
||||
this.Height + padding.Vertical);
|
||||
|
||||
public RectangleInfo Offset(SizeInfo amount) => this.Offset(amount.Width, amount.Height);
|
||||
|
||||
public RectangleInfo Offset(decimal dx, decimal dy) => new(this.X + dx, this.Y + dy, this.Width, this.Height);
|
||||
|
||||
public RectangleInfo Scale(decimal scalingFactor) => new(
|
||||
this.X * scalingFactor,
|
||||
this.Y * scalingFactor,
|
||||
this.Width * scalingFactor,
|
||||
this.Height * scalingFactor);
|
||||
|
||||
public RectangleInfo Center(PointInfo point) => new(
|
||||
x: point.X - (this.Width / 2),
|
||||
y: point.Y - (this.Height / 2),
|
||||
width: this.Width,
|
||||
height: this.Height);
|
||||
|
||||
public PointInfo Midpoint => new(
|
||||
x: this.X + (this.Width / 2),
|
||||
y: this.Y + (this.Height / 2));
|
||||
|
||||
public RectangleInfo Clamp(RectangleInfo outer)
|
||||
{
|
||||
if ((this.Width > outer.Width) || (this.Height > outer.Height))
|
||||
{
|
||||
throw new ArgumentException($"Value cannot be larger than {nameof(outer)}.");
|
||||
}
|
||||
|
||||
return new(
|
||||
x: Math.Clamp(this.X, outer.X, outer.Right - this.Width),
|
||||
y: Math.Clamp(this.Y, outer.Y, outer.Bottom - this.Height),
|
||||
width: this.Width,
|
||||
height: this.Height);
|
||||
}
|
||||
|
||||
public Rectangle ToRectangle() => new((int)this.X, (int)this.Y, (int)this.Width, (int)this.Height);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Left)}={this.Left}," +
|
||||
$"{nameof(this.Top)}={this.Top}," +
|
||||
$"{nameof(this.Width)}={this.Width}," +
|
||||
$"{nameof(this.Height)}={this.Height}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -1,87 +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.Drawing;
|
||||
|
||||
namespace MouseJumpUI.Models.Drawing;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Drawing.Size object with some extra utility methods.
|
||||
/// </summary>
|
||||
public sealed class SizeInfo
|
||||
{
|
||||
public SizeInfo(decimal width, decimal height)
|
||||
{
|
||||
this.Width = width;
|
||||
this.Height = height;
|
||||
}
|
||||
|
||||
public SizeInfo(Size size)
|
||||
: this(size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
|
||||
public decimal Width
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public decimal Height
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public SizeInfo Negate() => new(-this.Width, -this.Height);
|
||||
|
||||
public SizeInfo Shrink(PaddingInfo padding) => new(this.Width - padding.Horizontal, this.Height - padding.Vertical);
|
||||
|
||||
public SizeInfo Intersect(SizeInfo size) => new(
|
||||
Math.Min(this.Width, size.Width),
|
||||
Math.Min(this.Height, size.Height));
|
||||
|
||||
public RectangleInfo PlaceAt(decimal x, decimal y) => new(x, y, this.Width, this.Height);
|
||||
|
||||
public SizeInfo ScaleToFit(SizeInfo bounds)
|
||||
{
|
||||
var widthRatio = bounds.Width / this.Width;
|
||||
var heightRatio = bounds.Height / this.Height;
|
||||
return widthRatio.CompareTo(heightRatio) switch
|
||||
{
|
||||
< 0 => new(bounds.Width, this.Height * widthRatio),
|
||||
0 => bounds,
|
||||
> 0 => new(this.Width * heightRatio, bounds.Height),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the scaling ratio to scale obj by so that it fits inside the specified bounds
|
||||
/// without distorting the aspect ratio.
|
||||
/// </summary>
|
||||
public decimal ScaleToFitRatio(SizeInfo bounds)
|
||||
{
|
||||
if (bounds.Width == 0 || bounds.Height == 0)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(bounds.Width)} or {nameof(bounds.Height)} cannot be zero", nameof(bounds));
|
||||
}
|
||||
|
||||
var widthRatio = bounds.Width / this.Width;
|
||||
var heightRatio = bounds.Height / this.Height;
|
||||
var scalingRatio = Math.Min(widthRatio, heightRatio);
|
||||
|
||||
return scalingRatio;
|
||||
}
|
||||
|
||||
public Size ToSize() => new((int)this.Width, (int)this.Height);
|
||||
|
||||
public Point ToPoint() => new((int)this.Width, (int)this.Height);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" +
|
||||
$"{nameof(this.Width)}={this.Width}," +
|
||||
$"{nameof(this.Height)}={this.Height}" +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@@ -1,123 +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.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
using MouseJumpUI.Models.Drawing;
|
||||
using MouseJumpUI.Models.Screen;
|
||||
|
||||
namespace MouseJumpUI.Models.Layout;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a collection of values needed for calculating the MainForm layout.
|
||||
/// </summary>
|
||||
public sealed class LayoutConfig
|
||||
{
|
||||
public LayoutConfig(
|
||||
RectangleInfo virtualScreenBounds,
|
||||
List<ScreenInfo> screens,
|
||||
PointInfo activatedLocation,
|
||||
int activatedScreenIndex,
|
||||
int activatedScreenNumber,
|
||||
SizeInfo maximumFormSize,
|
||||
PaddingInfo formPadding,
|
||||
PaddingInfo previewPadding)
|
||||
{
|
||||
// make sure the virtual screen entirely contains all of the individual screen bounds
|
||||
ArgumentNullException.ThrowIfNull(virtualScreenBounds);
|
||||
ArgumentNullException.ThrowIfNull(screens);
|
||||
if (screens.Any(screen => !virtualScreenBounds.Contains(screen.Bounds)))
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(virtualScreenBounds)}' must contain all of the screens in '{nameof(screens)}'", nameof(virtualScreenBounds));
|
||||
}
|
||||
|
||||
this.VirtualScreenBounds = virtualScreenBounds;
|
||||
this.Screens = new(screens.ToList());
|
||||
this.ActivatedLocation = activatedLocation;
|
||||
this.ActivatedScreenIndex = activatedScreenIndex;
|
||||
this.ActivatedScreenNumber = activatedScreenNumber;
|
||||
this.MaximumFormSize = maximumFormSize;
|
||||
this.FormPadding = formPadding;
|
||||
this.PreviewPadding = previewPadding;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coordinates of the entire virtual screen.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Virtual Screen is the bounding rectangle of all the monitors.
|
||||
/// https://learn.microsoft.com/en-us/windows/win32/gdi/the-virtual-screen
|
||||
/// </remarks>
|
||||
public RectangleInfo VirtualScreenBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection containing the individual screens connected to the system.
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<ScreenInfo> Screens
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the point where the cursor was located when the form was activated.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// The preview form will be centered on this location unless there are any
|
||||
/// constraints such as being too close to edge of a screen, in which case
|
||||
/// the form will be displayed centered as close as possible to this location.
|
||||
/// </summary>
|
||||
public PointInfo ActivatedLocation
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the screen the cursor was on when the form was activated.
|
||||
/// The value is an index into the ScreenBounds array and is 0-indexed as a result.
|
||||
/// </summary>
|
||||
public int ActivatedScreenIndex
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the screen number the cursor was on when the form was activated.
|
||||
/// The value matches the screen numbering scheme in the "Display Settings" dialog
|
||||
/// and is 1-indexed as a result.
|
||||
/// </summary>
|
||||
public int ActivatedScreenNumber
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum size of the screen preview form.
|
||||
/// </summary>
|
||||
public SizeInfo MaximumFormSize
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the padding border around the screen preview form.
|
||||
/// </summary>
|
||||
public PaddingInfo FormPadding
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the padding border inside the screen preview image.
|
||||
/// </summary>
|
||||
public PaddingInfo PreviewPadding
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +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.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
using MouseJumpUI.Models.Drawing;
|
||||
|
||||
namespace MouseJumpUI.Models.Layout;
|
||||
|
||||
public sealed class LayoutInfo
|
||||
{
|
||||
public sealed class Builder
|
||||
{
|
||||
public Builder()
|
||||
{
|
||||
this.ScreenBounds = new();
|
||||
}
|
||||
|
||||
public LayoutConfig? LayoutConfig
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public RectangleInfo? FormBounds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public RectangleInfo? PreviewBounds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public List<RectangleInfo> ScreenBounds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public RectangleInfo? ActivatedScreenBounds
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public LayoutInfo Build()
|
||||
{
|
||||
return new LayoutInfo(
|
||||
layoutConfig: this.LayoutConfig ?? throw new InvalidOperationException(),
|
||||
formBounds: this.FormBounds ?? throw new InvalidOperationException(),
|
||||
previewBounds: this.PreviewBounds ?? throw new InvalidOperationException(),
|
||||
screenBounds: this.ScreenBounds ?? throw new InvalidOperationException(),
|
||||
activatedScreenBounds: this.ActivatedScreenBounds ?? throw new InvalidOperationException());
|
||||
}
|
||||
}
|
||||
|
||||
public LayoutInfo(
|
||||
LayoutConfig layoutConfig,
|
||||
RectangleInfo formBounds,
|
||||
RectangleInfo previewBounds,
|
||||
IEnumerable<RectangleInfo> screenBounds,
|
||||
RectangleInfo activatedScreenBounds)
|
||||
{
|
||||
this.LayoutConfig = layoutConfig ?? throw new ArgumentNullException(nameof(layoutConfig));
|
||||
this.FormBounds = formBounds ?? throw new ArgumentNullException(nameof(formBounds));
|
||||
this.PreviewBounds = previewBounds ?? throw new ArgumentNullException(nameof(previewBounds));
|
||||
this.ScreenBounds = new(
|
||||
(screenBounds ?? throw new ArgumentNullException(nameof(screenBounds)))
|
||||
.ToList());
|
||||
this.ActivatedScreenBounds = activatedScreenBounds ?? throw new ArgumentNullException(nameof(activatedScreenBounds));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original LayoutConfig settings used to calculate coordinates.
|
||||
/// </summary>
|
||||
public LayoutConfig LayoutConfig
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size and location of the preview form.
|
||||
/// </summary>
|
||||
public RectangleInfo FormBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size and location of the preview image.
|
||||
/// </summary>
|
||||
public RectangleInfo PreviewBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<RectangleInfo> ScreenBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo ActivatedScreenBounds
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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 MouseJumpUI.Models.Drawing;
|
||||
|
||||
namespace MouseJumpUI.Models.Screen;
|
||||
|
||||
/// <summary>
|
||||
/// Immutable version of a System.Windows.Forms.Screen object so we don't need to
|
||||
/// take a dependency on WinForms just for screen info.
|
||||
/// </summary>
|
||||
public sealed class ScreenInfo
|
||||
{
|
||||
internal ScreenInfo(int handle, bool primary, RectangleInfo displayArea, RectangleInfo workingArea)
|
||||
{
|
||||
this.Handle = handle;
|
||||
this.Primary = primary;
|
||||
this.DisplayArea = displayArea ?? throw new ArgumentNullException(nameof(displayArea));
|
||||
this.WorkingArea = workingArea ?? throw new ArgumentNullException(nameof(workingArea));
|
||||
}
|
||||
|
||||
public int Handle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public bool Primary
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo DisplayArea
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public RectangleInfo Bounds =>
|
||||
this.DisplayArea;
|
||||
|
||||
public RectangleInfo WorkingArea
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Threading;
|
||||
@@ -97,29 +95,4 @@ internal static class Program
|
||||
cancellationTokenSource.Cancel();
|
||||
Application.Exit();
|
||||
}
|
||||
|
||||
private static MouseJumpSettings ReadSettings()
|
||||
{
|
||||
var settingsUtils = new SettingsUtils();
|
||||
var settingsPath = settingsUtils.GetSettingsFilePath(MouseJumpSettings.ModuleName);
|
||||
if (!File.Exists(settingsPath))
|
||||
{
|
||||
var scaffoldSettings = new MouseJumpSettings();
|
||||
settingsUtils.SaveSettings(JsonSerializer.Serialize(scaffoldSettings), MouseJumpSettings.ModuleName);
|
||||
}
|
||||
|
||||
var settings = new MouseJumpSettings();
|
||||
try
|
||||
{
|
||||
settings = settingsUtils.GetSettings<MouseJumpSettings>(MouseJumpSettings.ModuleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMessage = $"There was a problem reading the configuration file. Error: {ex.GetType()} {ex.Message}";
|
||||
Logger.LogInfo(errorMessage);
|
||||
Logger.LogDebug(errorMessage);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +368,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly object ClipboardThreadOldLock = new();
|
||||
private static readonly Lock ClipboardThreadOldLock = new();
|
||||
private static System.Threading.Thread clipboardThreadOld;
|
||||
|
||||
internal static void GetRemoteClipboard(string postAction)
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
public class Thread
|
||||
{
|
||||
private static readonly object ThreadsLock = new();
|
||||
private static readonly Lock ThreadsLock = new();
|
||||
private static List<System.Threading.Thread> threads;
|
||||
|
||||
private readonly System.Threading.Thread thread;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
internal partial class Common
|
||||
{
|
||||
private static readonly object McMatrixLock = new();
|
||||
private static readonly Lock McMatrixLock = new();
|
||||
|
||||
internal const byte MAX_MACHINE = 4;
|
||||
internal const byte MAX_SOCKET = MAX_MACHINE * 2;
|
||||
|
||||
@@ -474,7 +474,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly object InputSimulationLock = new();
|
||||
private static readonly Lock InputSimulationLock = new();
|
||||
|
||||
internal static void DoSomethingInTheInputSimulationThread(ThreadStart target)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace MouseWithoutBorders.Class
|
||||
{
|
||||
@@ -36,12 +37,12 @@ namespace MouseWithoutBorders.Class
|
||||
/// </remarks>
|
||||
internal class MachinePool
|
||||
{
|
||||
private readonly object @lock;
|
||||
private readonly Lock @lock;
|
||||
private readonly List<MachineInf> list;
|
||||
|
||||
public MachinePool()
|
||||
{
|
||||
@lock = new object();
|
||||
@lock = new Lock();
|
||||
list = new List<MachineInf>();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@@ -44,7 +45,7 @@ namespace MouseWithoutBorders.Class
|
||||
internal bool Changed;
|
||||
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private readonly object _loadingSettingsLock = new object();
|
||||
private readonly Lock _loadingSettingsLock = new Lock();
|
||||
private readonly IFileSystemWatcher _watcher;
|
||||
|
||||
private MouseWithoutBordersProperties _properties;
|
||||
|
||||
@@ -826,7 +826,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, List<IPAddress>> BadIPs = new();
|
||||
private static readonly object BadIPsLock = new();
|
||||
private static readonly Lock BadIPsLock = new();
|
||||
|
||||
private static bool IsBadIP(string machineName, IPAddress ip)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("The thickness of the border around the field")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public int BorderSize
|
||||
{
|
||||
get => _borderSize;
|
||||
@@ -33,6 +34,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("The color of the border around the field")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Color BorderColor
|
||||
{
|
||||
get => _borderColor;
|
||||
@@ -47,6 +49,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("The color of the border around the field when it has focus")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Color FocusColor
|
||||
{
|
||||
get => _focusColor;
|
||||
@@ -59,12 +62,14 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Behavior")]
|
||||
[Description("The maximum number of characters that can be typed in the field")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public int MaximumLength
|
||||
{
|
||||
get => InnerField.MaxLength;
|
||||
set => InnerField.MaxLength = value;
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public override string Text
|
||||
{
|
||||
get => InnerField.Text;
|
||||
|
||||
@@ -19,12 +19,14 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("Image to show when Mouse is pressed on button")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Image DownImage { get; set; }
|
||||
|
||||
private Image _normalImage;
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("Image to show when button is in normal state")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Image NormalImage
|
||||
{
|
||||
get => _normalImage;
|
||||
@@ -37,10 +39,12 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("Image to show when Mouse hovers over button")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Image HoverImage { get; set; }
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("Image to show when button is disabled")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Image DisabledImage { get; set; }
|
||||
|
||||
private bool _hovering;
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("The bounding rectangle of the check image in local co-ordinates")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Point ImageLocation
|
||||
{
|
||||
get => _imageLocation;
|
||||
@@ -28,6 +29,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
private Point _textLocation;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Point TextLocation
|
||||
{
|
||||
get => _textLocation;
|
||||
@@ -47,6 +49,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("Image to show when Mouse is pressed on button")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Image CheckedImage
|
||||
{
|
||||
get => _checkedImage;
|
||||
@@ -61,6 +64,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
[Category("Appearance")]
|
||||
[Description("Image to show when button is in normal state")]
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public Image UncheckedImage
|
||||
{
|
||||
get => _uncheckedImage;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
// <summary>
|
||||
@@ -34,12 +35,14 @@ namespace MouseWithoutBorders
|
||||
MachineEnabled = false;
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal string MachineName
|
||||
{
|
||||
get => textBoxName.Text;
|
||||
set => textBoxName.Text = value;
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal bool MachineEnabled
|
||||
{
|
||||
get => checkBoxEnabled.Checked;
|
||||
@@ -52,6 +55,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
internal bool Editable
|
||||
{
|
||||
set => textBoxName.Enabled = value;
|
||||
@@ -59,6 +63,7 @@ namespace MouseWithoutBorders
|
||||
// get { return textBoxName.Enabled; }
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
internal bool CheckAble
|
||||
{
|
||||
set
|
||||
@@ -73,6 +78,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
internal bool LocalHost
|
||||
{
|
||||
// get { return localhost; }
|
||||
@@ -165,6 +171,7 @@ namespace MouseWithoutBorders
|
||||
return rv;
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal SocketStatus StatusClient
|
||||
{
|
||||
get => statusClient;
|
||||
@@ -182,6 +189,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal SocketStatus StatusServer
|
||||
{
|
||||
get => statusServer;
|
||||
|
||||
@@ -12,6 +12,7 @@ using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
// <summary>
|
||||
@@ -30,7 +31,7 @@ namespace MouseWithoutBorders.Core;
|
||||
internal static class Logger
|
||||
{
|
||||
internal static readonly string[] AllLogs = new string[MAX_LOG];
|
||||
private static readonly object AllLogsLock = new();
|
||||
private static readonly Lock AllLogsLock = new();
|
||||
internal static readonly ConcurrentDictionary<string, int> LogCounter = new();
|
||||
private const int MAX_LOG = 10000;
|
||||
private static int allLogsIndex;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@@ -32,6 +33,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
private int _animationFrame;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public bool ReturnToSettings { get; set; }
|
||||
|
||||
public SetupPage3a()
|
||||
|
||||
@@ -58,12 +58,16 @@ namespace MouseWithoutBorders
|
||||
private Timer helperTimer;
|
||||
#pragma warning restore CA2213
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal int CurIcon { get; set; }
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal NotifyIcon NotifyIcon { get; set; }
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal System.Windows.Forms.ToolStripMenuItem MenuAllPC { get; set; }
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
internal System.Windows.Forms.ContextMenuStrip MainMenu { get; set; }
|
||||
|
||||
internal FrmScreen()
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace MouseWithoutBorders
|
||||
public partial class FormHelper : System.Windows.Forms.Form
|
||||
{
|
||||
private readonly List<FocusArea> focusZone = new();
|
||||
private readonly object bmScreenLock = new();
|
||||
private readonly Lock bmScreenLock = new();
|
||||
private long lastClipboardEventTime;
|
||||
|
||||
private IClipboardHelper remoteClipboardHelper;
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h new.base.rc new.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{0db0f63a-d2f8-4da3-a650-2d0b8724218e}</ProjectGuid>
|
||||
<RootNamespace>NewPlusShellExtensionWin10</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutDir>
|
||||
<TargetName>PowerToys.NewPlus.ShellExtension.win10</TargetName>
|
||||
<LinkIncremental />
|
||||
<IgnoreImportLibrary />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;NEWPLUSSHELLEXTENSIONWIN10_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories);..\NewShellExtensionContextMenu</AdditionalIncludeDirectories>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>runtimeobject.lib;$(CoreLibraryDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;NEWPLUSSHELLEXTENSIONWIN10_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories);..\NewShellExtensionContextMenu</AdditionalIncludeDirectories>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>runtimeobject.lib;$(CoreLibraryDependencies)</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>dll.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\constants.h" />
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\new_utilities.h" />
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\settings.h" />
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\shell_context_sub_menu.h" />
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\shell_context_sub_menu_item.h" />
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\template_folder.h" />
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\template_item.h" />
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\trace.h" />
|
||||
<ClInclude Include="dll_main.h" />
|
||||
<ClInclude Include="Generated Files\resource.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.base.h" />
|
||||
<ClInclude Include="shell_context_menu_win10.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\new_utilities.cpp" />
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\powertoys_module.cpp" />
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\settings.cpp" />
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\shell_context_sub_menu.cpp" />
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\shell_context_sub_menu_item.cpp" />
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\template_folder.cpp" />
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\template_item.cpp" />
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\trace.cpp" />
|
||||
<ClCompile Include="dll_main.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shell_context_menu_win10.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files\new.rc" />
|
||||
<None Include="new.base.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="resources.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\Telemetry\EtwTrace\EtwTrace.vcxproj">
|
||||
<Project>{8f021b46-362b-485c-bfba-ccf83e820cbd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
|
||||
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="dll.def" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.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'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{4cea4fff-ccef-4b62-9e46-f33da2b9a0cc}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shell_context_menu_win10.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.base.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Generated Files\resource.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\new_utilities.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\shell_context_sub_menu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\shell_context_sub_menu_item.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\template_folder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\template_item.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\constants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dll_main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\NewShellExtensionContextMenu\settings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dll_main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shell_context_menu_win10.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\template_item.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\template_folder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\shell_context_sub_menu.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\shell_context_sub_menu_item.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\powertoys_module.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\settings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\NewShellExtensionContextMenu\new_utilities.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files\new.rc">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="dll.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="new.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resources.resx">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
LIBRARY
|
||||
|
||||
EXPORTS
|
||||
DllGetClassObject PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllGetActivationFactory PRIVATE
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "shell_context_menu_win10.h"
|
||||
#include "dll_main.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include <common/Telemetry/EtwTrace/EtwTrace.h>
|
||||
|
||||
HMODULE module_instance_handle = 0;
|
||||
Shared::Trace::ETWTrace trace(L"NewPlusShellExtension_Win10");
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE module_handle, DWORD ul_reason_for_call, LPVOID reserved)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
module_instance_handle = module_handle;
|
||||
Trace::RegisterProvider();
|
||||
newplus::utilities::init_logger();
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ IActivationFactory** factory)
|
||||
{
|
||||
return Module<ModuleType::InProc>::GetModule().GetActivationFactory(activatableClassId, factory);
|
||||
}
|
||||
|
||||
STDAPI DllCanUnloadNow()
|
||||
{
|
||||
return Module<InProc>::GetModule().GetObjectCount() == 0 ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDAPI DllGetClassObject(_In_ REFCLSID ref_class_id, _In_ REFIID ref_interface_id, _Outptr_ LPVOID FAR* object)
|
||||
{
|
||||
return Module<InProc>::GetModule().GetClassObject(ref_class_id, ref_interface_id, object);
|
||||
}
|
||||
|
||||
CoCreatableClass(shell_context_menu_win10)
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/Telemetry/EtwTrace/EtwTrace.h>
|
||||
|
||||
extern HMODULE module_instance_handle;
|
||||
extern Shared::Trace::ETWTrace trace;
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <windows.h>
|
||||
#include "Generated Files/resource.h"
|
||||
#include "../../../../common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -0,0 +1,3 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
39
src/modules/NewPlus/NewShellExtensionContextMenu.win10/pch.h
Normal file
39
src/modules/NewPlus/NewShellExtensionContextMenu.win10/pch.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Precompiled header file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMCX
|
||||
#define NOHELP
|
||||
#define NOCOMM
|
||||
|
||||
// Windows and STL
|
||||
#include <Shobjidl.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <vector>
|
||||
#include <system_error>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <atlbase.h>
|
||||
#include <wrl.h>
|
||||
#include <wrl/module.h>
|
||||
#include <wrl/client.h>
|
||||
#include <unknwn.h>
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
// PowerToys project common
|
||||
#include <ProjectTelemetry.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/logger/logger_settings.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <common/Themes/theme_helpers.h>
|
||||
|
||||
// New project specific
|
||||
#include "dll_main.h"
|
||||
#include "template_folder.h"
|
||||
#include "settings.h"
|
||||
#include "new_utilities.h"
|
||||
@@ -0,0 +1,12 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys.New+"
|
||||
#define INTERNAL_NAME "PowerToys.New+"
|
||||
#define ORIGINAL_FILENAME "PowerToys.NewPlus.ShellExtension.win10.dll"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
||||
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="context_menu_item_new" xml:space="preserve">
|
||||
<value>New+</value>
|
||||
<comment>The main context menu item that users click on. This should be localized to match New in Windows. e.g. Danish it would become Ny+</comment>
|
||||
</data>
|
||||
<data name="context_menu_item_open_templates" xml:space="preserve">
|
||||
<value>Open templates</value>
|
||||
<comment>The menu item in the context menu that enables user to open the folder that contains their templates.</comment>
|
||||
</data>
|
||||
<data name="default_template_sub_folder_name_where_templates_are_stored" xml:space="preserve">
|
||||
<value>Templates</value>
|
||||
<comment>Default subfolder name where templates are stored.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,270 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "shell_context_menu_win10.h"
|
||||
#include "shell_context_sub_menu.h"
|
||||
#include "shell_context_sub_menu_item.h"
|
||||
#include "new_utilities.h"
|
||||
#include "settings.h"
|
||||
#include "trace.h"
|
||||
#include "Generated Files/resource.h"
|
||||
#include <common/Themes/icon_helpers.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace newplus;
|
||||
|
||||
shell_context_menu_win10::~shell_context_menu_win10()
|
||||
{
|
||||
for (const auto& handle : bitmap_handles)
|
||||
{
|
||||
DeleteObject(handle);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma region IShellExtInit
|
||||
IFACEMETHODIMP shell_context_menu_win10::Initialize(PCIDLIST_ABSOLUTE, IDataObject*, HKEY)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IContextMenu
|
||||
IFACEMETHODIMP shell_context_menu_win10::QueryContextMenu(HMENU menu_handle, UINT menu_index, UINT menu_first_cmd_id, UINT, UINT menu_flags)
|
||||
{
|
||||
if (!NewSettingsInstance().GetEnabled()
|
||||
|| package::IsWin11OrGreater()
|
||||
)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (menu_flags & CMF_DEFAULTONLY)
|
||||
{
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Create the initial context popup menu containing the list of templates and open templates action
|
||||
int menu_id = menu_first_cmd_id;
|
||||
MENUITEMINFO newplus_main_context_menu_item;
|
||||
HMENU sub_menu_of_templates = CreatePopupMenu();
|
||||
int sub_menu_index = 0;
|
||||
|
||||
// Determine the New+ Template folder location
|
||||
const std::filesystem::path template_folder_root = utilities::get_new_template_folder_location();
|
||||
|
||||
// Create the New+ Template folder location if it doesn't exist (very rare scenario)
|
||||
utilities::create_folder_if_not_exist(template_folder_root);
|
||||
|
||||
// Scan the folder for any files and folders (the templates)
|
||||
templates = new template_folder(template_folder_root);
|
||||
templates->rescan_template_folder();
|
||||
const auto number_of_templates = templates->list_of_templates.size();
|
||||
|
||||
// Create the New+ menu item and point to the initial context popup menu
|
||||
static const std::wstring localized_context_menu_item =
|
||||
GET_RESOURCE_STRING_FALLBACK(IDS_CONTEXT_MENU_ITEM_NEW, L"New+");
|
||||
wchar_t newplus_menu_name[20] = { 0 };
|
||||
wcscpy_s(newplus_menu_name, ARRAYSIZE(newplus_menu_name), localized_context_menu_item.c_str());
|
||||
newplus_main_context_menu_item.cbSize = sizeof(MENUITEMINFOW);
|
||||
newplus_main_context_menu_item.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU;
|
||||
newplus_main_context_menu_item.wID = menu_id;
|
||||
newplus_main_context_menu_item.fType = MFT_STRING;
|
||||
newplus_main_context_menu_item.dwTypeData = (PWSTR)newplus_menu_name;
|
||||
newplus_main_context_menu_item.hSubMenu = sub_menu_of_templates;
|
||||
const auto newplus_icon_index = 0;
|
||||
|
||||
if (bitmap_handles.size() == 0)
|
||||
{
|
||||
const std::wstring icon_file = utilities::get_new_icon_resource_filepath(
|
||||
module_instance_handle, ThemeHelpers::GetAppTheme())
|
||||
.c_str();
|
||||
HICON local_icon_handle = static_cast<HICON>(
|
||||
LoadImage(NULL, icon_file.c_str(), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_LOADFROMFILE));
|
||||
|
||||
if (local_icon_handle)
|
||||
{
|
||||
bitmap_handles.push_back(CreateBitmapFromIcon(local_icon_handle));
|
||||
DestroyIcon(local_icon_handle);
|
||||
}
|
||||
}
|
||||
if (bitmap_handles.size() > newplus_icon_index && bitmap_handles[newplus_icon_index])
|
||||
{
|
||||
newplus_main_context_menu_item.fMask |= MIIM_BITMAP;
|
||||
newplus_main_context_menu_item.hbmpItem = bitmap_handles[newplus_icon_index];
|
||||
}
|
||||
|
||||
menu_id++;
|
||||
|
||||
// Add template items to context menu
|
||||
int index = 0;
|
||||
for (; index < number_of_templates; index++)
|
||||
{
|
||||
const auto template_item = templates->get_template_item(index);
|
||||
add_template_item_to_context_menu(sub_menu_of_templates, sub_menu_index, template_item, menu_id, index);
|
||||
menu_id++;
|
||||
sub_menu_index++;
|
||||
}
|
||||
|
||||
// Add separator to context menu
|
||||
add_separator_to_context_menu(sub_menu_of_templates, sub_menu_index);
|
||||
sub_menu_index++;
|
||||
|
||||
// Add "Open templates" item to context menu
|
||||
add_open_templates_to_context_menu(sub_menu_of_templates, sub_menu_index, template_folder_root, menu_id, index);
|
||||
menu_id++;
|
||||
|
||||
if (!InsertMenuItem(menu_handle, menu_index, TRUE, &newplus_main_context_menu_item))
|
||||
{
|
||||
Logger::error(L"QueryContextMenu() failed. {}", get_last_error_or_default(GetLastError()));
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return the amount if entries inserted
|
||||
const auto number_of_items_inserted = menu_id - menu_first_cmd_id;
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, number_of_items_inserted);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
Logger::error(ex.what());
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
void shell_context_menu_win10::add_open_templates_to_context_menu(HMENU sub_menu_of_templates, int sub_menu_index, const std::filesystem::path& template_folder_root, int menu_id, int index)
|
||||
{
|
||||
static const std::wstring localized_context_menu_item_open_templates =
|
||||
GET_RESOURCE_STRING_FALLBACK(IDS_CONTEXT_MENU_ITEM_OPEN_TEMPLATES, L"Open templates");
|
||||
wchar_t menu_name_open[256] = { 0 };
|
||||
wcscpy_s(menu_name_open, ARRAYSIZE(menu_name_open), localized_context_menu_item_open_templates.c_str());
|
||||
const auto open_folder_item = Make<template_folder_context_menu_item>(template_folder_root);
|
||||
MENUITEMINFO newplus_menu_item_open_templates;
|
||||
newplus_menu_item_open_templates.cbSize = sizeof(MENUITEMINFO);
|
||||
newplus_menu_item_open_templates.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
|
||||
newplus_menu_item_open_templates.wID = menu_id;
|
||||
newplus_menu_item_open_templates.fType = MFT_STRING;
|
||||
newplus_menu_item_open_templates.dwTypeData = (PWSTR)menu_name_open;
|
||||
|
||||
const auto open_templates_icon_index = index + 1;
|
||||
if (bitmap_handles.size() <= open_templates_icon_index)
|
||||
{
|
||||
const std::wstring icon_file = utilities::get_open_templates_icon_resource_filepath(
|
||||
module_instance_handle, ThemeHelpers::GetAppTheme())
|
||||
.c_str();
|
||||
HICON open_template_icon_handle = static_cast<HICON>(
|
||||
LoadImage(NULL, icon_file.c_str(), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_LOADFROMFILE));
|
||||
if (open_template_icon_handle)
|
||||
{
|
||||
bitmap_handles.push_back(CreateBitmapFromIcon(open_template_icon_handle));
|
||||
DestroyIcon(open_template_icon_handle);
|
||||
}
|
||||
}
|
||||
if (bitmap_handles.size() > open_templates_icon_index && bitmap_handles[open_templates_icon_index])
|
||||
{
|
||||
newplus_menu_item_open_templates.fMask |= MIIM_BITMAP;
|
||||
newplus_menu_item_open_templates.hbmpItem = bitmap_handles[open_templates_icon_index];
|
||||
}
|
||||
|
||||
InsertMenuItem(sub_menu_of_templates, sub_menu_index, TRUE, &newplus_menu_item_open_templates);
|
||||
}
|
||||
|
||||
void shell_context_menu_win10::add_separator_to_context_menu(HMENU sub_menu_of_templates, int sub_menu_index)
|
||||
{
|
||||
MENUITEMINFO menu_item_separator;
|
||||
menu_item_separator.cbSize = sizeof(MENUITEMINFO);
|
||||
menu_item_separator.fMask = MIIM_FTYPE;
|
||||
menu_item_separator.fType = MFT_SEPARATOR;
|
||||
InsertMenuItem(sub_menu_of_templates, sub_menu_index, TRUE, &menu_item_separator);
|
||||
}
|
||||
|
||||
void shell_context_menu_win10::add_template_item_to_context_menu(HMENU sub_menu_of_templates, int sub_menu_index, newplus::template_item* const template_item, int menu_id, int index)
|
||||
{
|
||||
wchar_t menu_name[256] = { 0 };
|
||||
wcscpy_s(menu_name, ARRAYSIZE(menu_name), template_item->get_menu_title(!utilities::get_newplus_setting_hide_extension(), !utilities::get_newplus_setting_hide_starting_digits()).c_str());
|
||||
MENUITEMINFO newplus_menu_item_template;
|
||||
newplus_menu_item_template.cbSize = sizeof(MENUITEMINFO);
|
||||
newplus_menu_item_template.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_DATA;
|
||||
newplus_menu_item_template.wID = menu_id;
|
||||
newplus_menu_item_template.fType = MFT_STRING;
|
||||
newplus_menu_item_template.dwTypeData = (PWSTR)menu_name;
|
||||
const auto current_template_icon_index = index + 1;
|
||||
if (bitmap_handles.size() <= current_template_icon_index)
|
||||
{
|
||||
HICON template_icon_handle = template_item->get_explorer_icon_handle();
|
||||
if (template_icon_handle)
|
||||
{
|
||||
bitmap_handles.push_back(CreateBitmapFromIcon(template_icon_handle));
|
||||
DestroyIcon(template_icon_handle);
|
||||
}
|
||||
}
|
||||
if (bitmap_handles.size() > current_template_icon_index && bitmap_handles[current_template_icon_index])
|
||||
{
|
||||
newplus_menu_item_template.fMask |= MIIM_BITMAP;
|
||||
newplus_menu_item_template.hbmpItem = bitmap_handles[current_template_icon_index];
|
||||
}
|
||||
|
||||
InsertMenuItem(sub_menu_of_templates, sub_menu_index, TRUE, &newplus_menu_item_template);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP shell_context_menu_win10::InvokeCommand(CMINVOKECOMMANDINFO* params)
|
||||
{
|
||||
if (!params)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Get selected menu item (a template or the "Open templates" item)
|
||||
const auto selected_menu_item_index = LOWORD(params->lpVerb) - 1;
|
||||
if (selected_menu_item_index < 0)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const auto number_of_templates = templates->list_of_templates.size();
|
||||
const bool is_template_item = selected_menu_item_index < number_of_templates;
|
||||
|
||||
// Save how many item templates we have so it can be sent later when we do something with New+.
|
||||
// It will be sent when the user does something, similar to Windows 11 context menu.
|
||||
newplus::utilities::set_saved_number_of_templates(static_cast<size_t>(number_of_templates));
|
||||
|
||||
if (is_template_item)
|
||||
{
|
||||
// It's a template menu item
|
||||
const auto template_entry = templates->get_template_item(selected_menu_item_index);
|
||||
|
||||
return newplus::utilities::copy_template(template_entry, site_of_folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's the "Open templates" menu item
|
||||
const std::filesystem::path template_folder_root = utilities::get_new_template_folder_location();
|
||||
|
||||
return newplus::utilities::open_template_folder(template_folder_root);
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP shell_context_menu_win10::GetCommandString(UINT_PTR, UINT, UINT*, CHAR*, UINT)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IObjectWithSite
|
||||
IFACEMETHODIMP shell_context_menu_win10::SetSite(_In_ IUnknown* site) noexcept
|
||||
{
|
||||
this->site_of_folder = site;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
IFACEMETHODIMP shell_context_menu_win10::GetSite(_In_ REFIID riid, _COM_Outptr_ void** returned_site) noexcept
|
||||
{
|
||||
return this->site_of_folder.CopyTo(riid, returned_site);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
#include <template_folder.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
#define NEW_SHELL_EXTENSION_EXPLORER_COMMAND_WIN10_UUID "FF90D477-E32A-4BE8-8CC5-A502A97F5401"
|
||||
|
||||
// File Explorer context menu "New+" for Windows 10
|
||||
class __declspec(uuid(NEW_SHELL_EXTENSION_EXPLORER_COMMAND_WIN10_UUID)) shell_context_menu_win10 :
|
||||
public RuntimeClass<
|
||||
RuntimeClassFlags<ClassicCom>,
|
||||
IShellExtInit,
|
||||
IContextMenu,
|
||||
IObjectWithSite>
|
||||
{
|
||||
public:
|
||||
~shell_context_menu_win10();
|
||||
|
||||
#pragma region IShellExtInit
|
||||
IFACEMETHODIMP Initialize(_In_opt_ PCIDLIST_ABSOLUTE, _In_ IDataObject*, HKEY);
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IContextMenu
|
||||
IFACEMETHODIMP QueryContextMenu(HMENU menu_handle, UINT menu_index, UINT menu_first_cmd_id, UINT, UINT menu_flags);
|
||||
IFACEMETHODIMP InvokeCommand(CMINVOKECOMMANDINFO* pici);
|
||||
IFACEMETHODIMP GetCommandString(UINT_PTR, UINT, UINT*, CHAR*, UINT);
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IObjectWithSite
|
||||
IFACEMETHODIMP SetSite(_In_ IUnknown* site) noexcept;
|
||||
IFACEMETHODIMP GetSite(_In_ REFIID riid, _COM_Outptr_ void** site) noexcept;
|
||||
#pragma endregion
|
||||
|
||||
protected:
|
||||
void add_open_templates_to_context_menu(HMENU sub_menu_of_templates, int sub_menu_index, const std::filesystem::path& template_folder_root, int menu_id, int index);
|
||||
void add_separator_to_context_menu(HMENU sub_menu_of_templates, int sub_menu_index);
|
||||
void add_template_item_to_context_menu(HMENU sub_menu_of_templates, int sub_menu_index, newplus::template_item* const template_item, int menu_id, int index);
|
||||
|
||||
HINSTANCE instance_handle = 0;
|
||||
ComPtr<IUnknown> site_of_folder;
|
||||
newplus::template_folder* templates = nullptr;
|
||||
std::vector<HBITMAP> bitmap_handles;
|
||||
};
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 186 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 186 KiB |
@@ -128,6 +128,7 @@ MakeAppx.exe pack /d . /p $(OutDir)NewPlusPackage.msix /nv</Command>
|
||||
<ClInclude Include="template_item.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="new_utilities.cpp" />
|
||||
<ClCompile Include="shell_context_menu.cpp" />
|
||||
<ClCompile Include="shell_context_sub_menu.cpp" />
|
||||
<ClCompile Include="shell_context_sub_menu_item.cpp" />
|
||||
@@ -227,7 +228,7 @@ MakeAppx.exe pack /d . /p $(OutDir)NewPlusPackage.msix /nv</Command>
|
||||
<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')" />
|
||||
<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>
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="new_utilities.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="template_folder.h">
|
||||
@@ -123,9 +126,6 @@
|
||||
<None Include="AppxManifest.xml">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\NewPlus\New.ico">
|
||||
<Filter>Asset Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\NewPlus\SmallTile.png">
|
||||
<Filter>Asset Files</Filter>
|
||||
</None>
|
||||
@@ -190,14 +190,8 @@
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="TemplateExamples\Example folder\Another example txt file.txt">
|
||||
<Filter>Template Examples\Example folder</Filter>
|
||||
</Text>
|
||||
<Text Include="TemplateExamples\Example folder\Example txt file.txt">
|
||||
<Filter>Template Examples\Example folder</Filter>
|
||||
</Text>
|
||||
<Text Include="TemplateExamples\Any files or folders placed in the template folder are available via New+.txt">
|
||||
<Filter>Template Examples</Filter>
|
||||
</Text>
|
||||
<CopyFileToFolders Include="TemplateExamples\Any files or folders placed in the template folder are available via New+.txt" />
|
||||
<CopyFileToFolders Include="TemplateExamples\Example folder\Example txt file.txt" />
|
||||
<CopyFileToFolders Include="TemplateExamples\Example folder\Another example txt file.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "pch.h"
|
||||
#include "new_utilities.h"
|
||||
|
||||
// HACK: Store number of templates when generating the menu entries to send later.
|
||||
size_t saved_number_of_templates = -1;
|
||||
size_t newplus::utilities::get_saved_number_of_templates()
|
||||
{
|
||||
return saved_number_of_templates;
|
||||
}
|
||||
void newplus::utilities::set_saved_number_of_templates(size_t templates)
|
||||
{
|
||||
saved_number_of_templates = templates;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user