mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-09 22:06:51 +01:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8ad4fa804 | ||
|
|
5d77874382 | ||
|
|
5b1e5107ee | ||
|
|
1be3b6c087 | ||
|
|
63625a1cee | ||
|
|
4fee37c35a | ||
|
|
d40367a860 | ||
|
|
84def18ed5 | ||
|
|
ac14ad3458 | ||
|
|
0a9e889b1b | ||
|
|
7479ef6e65 | ||
|
|
3652e3627a | ||
|
|
07c4972c2c | ||
|
|
9e3ac70897 | ||
|
|
1b27500231 | ||
|
|
16a1fb7981 | ||
|
|
ca97e01d59 | ||
|
|
70d3d5f16e | ||
|
|
af6916a538 | ||
|
|
0c00106d5a | ||
|
|
96642b6525 | ||
|
|
9bea986f3d | ||
|
|
6fdc86ed2d | ||
|
|
78d53ffb10 | ||
|
|
7d8af7bbbb | ||
|
|
7808033436 | ||
|
|
98cfeb0776 | ||
|
|
a3e193e56e | ||
|
|
d668a659b5 | ||
|
|
fb8765b54d | ||
|
|
b9f6ef6ee4 | ||
|
|
7457ff5202 | ||
|
|
fb36e6ced9 | ||
|
|
f1ca65ca78 | ||
|
|
b7c8bb201b | ||
|
|
c1e8b70a64 | ||
|
|
0ddff0fcf7 | ||
|
|
c87d8c37e1 | ||
|
|
c24000ec41 | ||
|
|
2ca70e31c9 | ||
|
|
d27ac581ac | ||
|
|
5159c76976 | ||
|
|
8d2ee4a8d2 | ||
|
|
5bcc6fbd86 |
6
.github/CODEOWNERS
vendored
6
.github/CODEOWNERS
vendored
@@ -4,7 +4,7 @@
|
||||
/.github/actions/spell-check/
|
||||
|
||||
# locking down pipeline folder
|
||||
/.pipelines @crutkas @DHowett @ethanfangg
|
||||
/.pipelines/ @crutkas @DHowett @ethanfangg
|
||||
|
||||
# locking down nuget config
|
||||
nuget.config @crutkas @DHowett @ethanfangg
|
||||
@@ -12,5 +12,5 @@ packages.config @crutkas @DHowett @ethanfangg
|
||||
|
||||
# locking down files that should not change
|
||||
LICENSE @crutkas @DHowett @ethanfangg
|
||||
SECURITY.MD @crutkas @DHowett @ethanfangg
|
||||
CODE_OF_CONDUCT.MD @crutkas @DHowett @ethanfangg
|
||||
SECURITY.md @crutkas @DHowett @ethanfangg
|
||||
CODE_OF_CONDUCT.md @crutkas @DHowett @ethanfangg
|
||||
|
||||
2
.github/actions/spell-check/allow/names.txt
vendored
2
.github/actions/spell-check/allow/names.txt
vendored
@@ -28,6 +28,7 @@ videoconference
|
||||
|
||||
# USERS
|
||||
|
||||
8LWXpg
|
||||
Adoumie
|
||||
Advaith
|
||||
alekhyareddy
|
||||
@@ -143,6 +144,7 @@ TBM
|
||||
tilovell
|
||||
Triet
|
||||
waaverecords
|
||||
Xpg
|
||||
ycv
|
||||
Yuniardi
|
||||
yuyoyuppe
|
||||
|
||||
35
.github/actions/spell-check/expect.txt
vendored
35
.github/actions/spell-check/expect.txt
vendored
@@ -200,6 +200,7 @@ CMINVOKECOMMANDINFO
|
||||
CMINVOKECOMMANDINFOEX
|
||||
CMock
|
||||
CMONITORS
|
||||
cmph
|
||||
cmpgt
|
||||
cne
|
||||
CNF
|
||||
@@ -220,7 +221,6 @@ comdlg
|
||||
comexp
|
||||
cominterop
|
||||
commandline
|
||||
COMMANDTITLE
|
||||
commctrl
|
||||
commdlg
|
||||
compmgmt
|
||||
@@ -244,6 +244,7 @@ copiedcolorrepresentation
|
||||
cotaskmem
|
||||
COULDNOT
|
||||
countof
|
||||
cph
|
||||
CPower
|
||||
cppblog
|
||||
cppruntime
|
||||
@@ -428,8 +429,8 @@ ENDSESSION
|
||||
ENTERSIZEMOVE
|
||||
ENU
|
||||
EOAC
|
||||
epu
|
||||
EPO
|
||||
epu
|
||||
ERASEBKGND
|
||||
EREOF
|
||||
EResize
|
||||
@@ -484,7 +485,6 @@ FILEFLAGSMASK
|
||||
FILELOCKSMITH
|
||||
FILELOCKSMITHCONTEXTMENU
|
||||
FILELOCKSMITHEXT
|
||||
FILELOCKSMITHLIB
|
||||
FILELOCKSMITHLIBINTEROP
|
||||
FILEMUSTEXIST
|
||||
FILEOP
|
||||
@@ -500,6 +500,7 @@ findfast
|
||||
FIXEDFILEINFO
|
||||
flac
|
||||
flyouts
|
||||
FMask
|
||||
FOF
|
||||
FOFX
|
||||
FOLDERID
|
||||
@@ -521,7 +522,6 @@ GCLP
|
||||
gdi
|
||||
gdiplus
|
||||
GDISCALED
|
||||
gdnbaselines
|
||||
GEmoji
|
||||
GETCLIENTAREAANIMATION
|
||||
GETDESKWALLPAPER
|
||||
@@ -541,7 +541,6 @@ gpedit
|
||||
gpo
|
||||
GPOCA
|
||||
gpp
|
||||
GPT
|
||||
gpu
|
||||
GSM
|
||||
gtm
|
||||
@@ -701,7 +700,6 @@ INSTALLSTARTMENUSHORTCUT
|
||||
INSTALLSTATE
|
||||
Inste
|
||||
Intelli
|
||||
interactable
|
||||
Interlop
|
||||
INTRESOURCE
|
||||
INVALIDARG
|
||||
@@ -730,7 +728,6 @@ IWeb
|
||||
IWIC
|
||||
iwr
|
||||
IYUV
|
||||
JArray
|
||||
jfi
|
||||
jfif
|
||||
jgeosdfsdsgmkedfgdfgdfgbkmhcgcflmi
|
||||
@@ -760,8 +757,8 @@ keyremaps
|
||||
keyvault
|
||||
KILLFOCUS
|
||||
killrunner
|
||||
kmph
|
||||
Knownfolders
|
||||
ksh
|
||||
KSPROPERTY
|
||||
Kybd
|
||||
languagesjson
|
||||
@@ -797,7 +794,6 @@ LOADFROMFILE
|
||||
LOBYTE
|
||||
LOCALDISPLAY
|
||||
LOCALPACKAGE
|
||||
localport
|
||||
LOCALSYSTEM
|
||||
LOCATIONCHANGE
|
||||
LOGFONT
|
||||
@@ -811,6 +807,7 @@ LOWORD
|
||||
lparam
|
||||
LPBITMAPINFOHEADER
|
||||
LPCITEMIDLIST
|
||||
lpcmi
|
||||
LPCMINVOKECOMMANDINFO
|
||||
LPCREATESTRUCT
|
||||
LPCRECT
|
||||
@@ -835,6 +832,7 @@ lptpm
|
||||
LPTR
|
||||
LPTSTR
|
||||
LPW
|
||||
lpwcx
|
||||
lpwndpl
|
||||
LReader
|
||||
LRESULT
|
||||
@@ -852,10 +850,10 @@ lwin
|
||||
LZero
|
||||
majortype
|
||||
makecab
|
||||
MAKELANGID
|
||||
MAKEINTRESOURCE
|
||||
MAKEINTRESOURCEA
|
||||
MAKEINTRESOURCEW
|
||||
MAKELANGID
|
||||
makepri
|
||||
manifestdependency
|
||||
MAPPEDTOSAMEKEY
|
||||
@@ -875,7 +873,6 @@ mdwn
|
||||
MEDIASUBTYPE
|
||||
mediatype
|
||||
mef
|
||||
MENUBREAK
|
||||
MENUITEMINFO
|
||||
MENUITEMINFOW
|
||||
MERGECOPY
|
||||
@@ -1038,6 +1035,7 @@ NOSEARCH
|
||||
NOSENDCHANGING
|
||||
NOSIZE
|
||||
NOTIFICATIONSDLL
|
||||
NOTIFYICONDATA
|
||||
NOTIFYICONDATAW
|
||||
NOTIMPL
|
||||
notlike
|
||||
@@ -1074,7 +1072,6 @@ oldtheme
|
||||
oleaut
|
||||
OLECHAR
|
||||
onebranch
|
||||
OOBEPT
|
||||
opencode
|
||||
OPENFILENAME
|
||||
opensource
|
||||
@@ -1098,7 +1095,6 @@ OVERLAPPEDWINDOW
|
||||
overlaywindow
|
||||
Oversampling
|
||||
OWNDC
|
||||
OWNERDRAW
|
||||
Packagemanager
|
||||
PACL
|
||||
PAINTSTRUCT
|
||||
@@ -1112,7 +1108,6 @@ PARTIALCONFIRMATIONDIALOGTITLE
|
||||
PATCOPY
|
||||
pathcch
|
||||
PATHMUSTEXIST
|
||||
Pathto
|
||||
PATINVERT
|
||||
PATPAINT
|
||||
PAUDIO
|
||||
@@ -1161,6 +1156,7 @@ ploca
|
||||
plocm
|
||||
pluginsmodel
|
||||
PMSIHANDLE
|
||||
pnid
|
||||
Pnp
|
||||
Popups
|
||||
POPUPWINDOW
|
||||
@@ -1253,8 +1249,6 @@ QUERYENDSESSION
|
||||
QUERYOPEN
|
||||
QUEUESYNC
|
||||
QUNS
|
||||
qwertyuiopasdfghjklzxcvbnm
|
||||
qwrtyuiopsghjklzxvnm
|
||||
raf
|
||||
RAII
|
||||
RAlt
|
||||
@@ -1271,7 +1265,6 @@ RECTDESTINATION
|
||||
rectp
|
||||
RECTSOURCE
|
||||
recyclebin
|
||||
redirectedfrom
|
||||
Redist
|
||||
redistributable
|
||||
reencode
|
||||
@@ -1353,8 +1346,6 @@ runas
|
||||
rundll
|
||||
rungameid
|
||||
RUNLEVEL
|
||||
runsettings
|
||||
runspace
|
||||
runtimeclass
|
||||
runtimeobject
|
||||
runtimepack
|
||||
@@ -1375,6 +1366,7 @@ SCID
|
||||
Scip
|
||||
scipbe
|
||||
Scode
|
||||
screensaver
|
||||
screenshots
|
||||
scrollviewer
|
||||
sddl
|
||||
@@ -1587,7 +1579,6 @@ TDevice
|
||||
telem
|
||||
telephon
|
||||
templatenamespace
|
||||
testhost
|
||||
testprocess
|
||||
TEXCOORD
|
||||
TEXTEXTRACTOR
|
||||
@@ -1612,7 +1603,6 @@ tlb
|
||||
tlbimp
|
||||
TMPVAR
|
||||
TNP
|
||||
toggleswitch
|
||||
Toolhelp
|
||||
toolkitconverters
|
||||
Toolset
|
||||
@@ -1642,9 +1632,11 @@ TYPESHORTCUT
|
||||
UAC
|
||||
UAL
|
||||
uap
|
||||
UCallback
|
||||
udit
|
||||
uefi
|
||||
uesc
|
||||
UFlags
|
||||
UHash
|
||||
UIA
|
||||
UIEx
|
||||
@@ -1682,6 +1674,7 @@ USESHOWWINDOW
|
||||
USESTDHANDLES
|
||||
USRDLL
|
||||
UType
|
||||
uuidv
|
||||
uwp
|
||||
uxtheme
|
||||
vabdq
|
||||
|
||||
2
.github/workflows/package-submissions.yml
vendored
2
.github/workflows/package-submissions.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
$installerMachineX64Url = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*x64' | Select -ExpandProperty browser_download_url
|
||||
$installerUserArmUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysUserSetup.*arm64' | Select -ExpandProperty browser_download_url
|
||||
$installerMachineArmUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'PowerToysSetup.*arm64' | Select -ExpandProperty browser_download_url
|
||||
$ver = $targetRelease.tag_name.Trim("v")
|
||||
$ver = $targetRelease.tag_name -ireplace '^v'
|
||||
|
||||
# getting latest wingetcreate file
|
||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||
|
||||
33
.github/workflows/similarIssues.yml
vendored
33
.github/workflows/similarIssues.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: GitGudSimilarIssues comments
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
getSimilarIssues:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
message: ${{ steps.getBody.outputs.message }}
|
||||
steps:
|
||||
- id: getBody
|
||||
uses: craigloewen-msft/GitGudSimilarIssues@main
|
||||
with:
|
||||
issueTitle: ${{ github.event.issue.title }}
|
||||
issueBody: ${{ github.event.issue.body }}
|
||||
repo: ${{ github.repository }}
|
||||
similarityTolerance: "0.75"
|
||||
add-comment:
|
||||
needs: getSimilarIssues
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
if: needs.getSimilarIssues.outputs.message != ''
|
||||
steps:
|
||||
- name: Add comment
|
||||
run: gh issue comment "$NUMBER" --repo "$REPO" --body "$BODY"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
REPO: ${{ github.repository }}
|
||||
BODY: ${{ needs.getSimilarIssues.outputs.message }}
|
||||
@@ -246,7 +246,7 @@ steps:
|
||||
inputs:
|
||||
testResultsFormat: VSTest
|
||||
testResultsFiles: '**/*.trx'
|
||||
condition: always()
|
||||
condition: ne(variables['BuildPlatform'],'arm64')
|
||||
|
||||
# Native dlls
|
||||
- task: VSTest@2
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
<PreferredToolArchitecture Condition="'$(PROCESSOR_ARCHITECTURE)' == 'ARM64' or '$(PROCESSOR_ARCHITEW6432)' == 'ARM64'">arm64</PreferredToolArchitecture>
|
||||
<VcpkgEnabled>false</VcpkgEnabled>
|
||||
<ReplaceWildcardsInProjectItems>true</ReplaceWildcardsInProjectItems>
|
||||
<ExternalIncludePath>$(MSBuildThisFileFullPath)\..\deps\;$(MSBuildThisFileFullPath)\..\packages\;$(ExternalIncludePath)</ExternalIncludePath>
|
||||
<!-- Enable control flow guard for C++ projects that don't consume any C++ files -->
|
||||
<!-- This covers the case where a .dll exports a .lib, but doesn't have any ClCompile entries. -->
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<UsePrecompiledHeaders Condition="'$(TF_BUILD)' != ''">false</UsePrecompiledHeaders>
|
||||
|
||||
<!-- Change this to bust the cache -->
|
||||
<MSBuildCacheCacheUniverse Condition="'$(MSBuildCacheCacheUniverse)' == ''">202407100737</MSBuildCacheCacheUniverse>
|
||||
<MSBuildCacheCacheUniverse Condition="'$(MSBuildCacheCacheUniverse)' == ''">202407200737</MSBuildCacheCacheUniverse>
|
||||
|
||||
<!--
|
||||
Visual Studio telemetry reads various ApplicationInsights.config files and other files after the project is finished, likely in a detached process.
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
|
||||
<PackageVersion Include="ControlzEx" Version="6.0.0" />
|
||||
<PackageVersion Include="coverlet.collector" Version="1.3.0" />
|
||||
<PackageVersion Include="DotNetSeleniumExtras.WaitHelpers" Version="3.11.0" />
|
||||
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
|
||||
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />
|
||||
@@ -28,19 +27,18 @@
|
||||
<PackageVersion Include="Mages" Version="2.0.2" />
|
||||
<PackageVersion Include="Markdig.Signed" Version="0.34.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.7" />
|
||||
<PackageVersion Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.336902" />
|
||||
<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.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2365.46" />
|
||||
<!-- 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.1" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="8.0.7" />
|
||||
<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. -->
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.0.4" />
|
||||
@@ -52,8 +50,7 @@
|
||||
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
|
||||
<!-- Moq to stay below v4.20 due to behavior change. need to be sure fixed -->
|
||||
<PackageVersion Include="Moq" Version="4.18.4" />
|
||||
<PackageVersion Include="MSTest.TestAdapter" Version="3.2.0" />
|
||||
<PackageVersion Include="MSTest.TestFramework" Version="3.2.0" />
|
||||
<PackageVersion Include="MSTest" Version="3.5.0" />
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageVersion Include="NLog" Version="5.0.4" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||
@@ -79,12 +76,13 @@
|
||||
<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.Reactive" Version="6.0.0-preview.9" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="8.0.0" />
|
||||
<!-- Package System.Security.Cryptography.ProtectedData 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.Security.Cryptography.ProtectedData" Version="8.0.0" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="8.0.4" />
|
||||
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
||||
<PackageVersion Include="UnitsNet" Version="5.50.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
@@ -98,4 +96,4 @@
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Client" Version="2.4.17140001" />
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Contract" Version="3.0.16990001" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
11
NOTICE.md
11
NOTICE.md
@@ -1318,17 +1318,16 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Mages 2.0.2
|
||||
- Markdig.Signed 0.34.0
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 8.0.0
|
||||
- Microsoft.Data.Sqlite 8.0.0
|
||||
- Microsoft.Data.Sqlite 8.0.7
|
||||
- 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.NET.Test.Sdk 17.8.0
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2365.46
|
||||
- Microsoft.Win32.SystemEvents 8.0.0
|
||||
- Microsoft.Windows.Compatibility 8.0.1
|
||||
- Microsoft.Windows.Compatibility 8.0.7
|
||||
- Microsoft.Windows.CsWin32 0.2.46-beta
|
||||
- Microsoft.Windows.CsWinRT 2.0.4
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
|
||||
@@ -1338,8 +1337,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
|
||||
- ModernWpfUI 0.9.4
|
||||
- Moq 4.18.4
|
||||
- MSTest.TestAdapter 3.2.0
|
||||
- MSTest.TestFramework 3.2.0
|
||||
- MSTest 3.5.0
|
||||
- NLog.Extensions.Logging 5.3.8
|
||||
- NLog.Schema 5.2.8
|
||||
- ReverseMarkdown 4.1.0
|
||||
@@ -1359,11 +1357,12 @@ EXHIBIT A -Mozilla Public License.
|
||||
- System.IO.Abstractions 17.2.3
|
||||
- System.IO.Abstractions.TestingHelpers 17.2.3
|
||||
- System.Management 8.0.0
|
||||
- System.Reactive 6.0.0-preview.9
|
||||
- System.Reactive 6.0.1
|
||||
- System.Runtime.Caching 8.0.0
|
||||
- System.Security.Cryptography.ProtectedData 8.0.0
|
||||
- System.ServiceProcess.ServiceController 8.0.0
|
||||
- System.Text.Encoding.CodePages 8.0.0
|
||||
- System.Text.Json 8.0.4
|
||||
- UnicodeInformation 2.6.0
|
||||
- UnitsNet 5.50.0
|
||||
- UTF.Unknown 2.5.1
|
||||
|
||||
@@ -171,6 +171,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\.editorconfig = src\.editorconfig
|
||||
.vsconfig = .vsconfig
|
||||
Cpp.Build.props = Cpp.Build.props
|
||||
Directory.Build.props = Directory.Build.props
|
||||
Directory.Build.targets = Directory.Build.targets
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
|
||||
22
README.md
22
README.md
@@ -8,8 +8,8 @@
|
||||
|
||||
| Architecture | Solution (Main) | Solution (Stable) | Installer (Main) |
|
||||
|--------------|-----------------|-------------------|------------------|
|
||||
| x64 | [](https://dev.azure.com/ms/PowerToys/_build/latest?definitionId=219&branchName=main&jobName=Build%20x64%20Release) | [](https://dev.azure.com/ms/PowerToys/_build/latest?definitionId=219&branchName=stable) | [](https://dev.azure.com/microsoft/Dart/_build/latest?definitionId=76541&branchName=main) |
|
||||
| ARM64 | [](https://dev.azure.com/ms/PowerToys/_build/latest?definitionId=219&branchName=main) | [](https://dev.azure.com/ms/PowerToys/_build/latest?definitionId=219&branchName=stable) | [](https://dev.azure.com/microsoft/Dart/_build/latest?definitionId=76541&branchName=main) |
|
||||
| x64 | [](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=main) | [](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=stable) | [](https://dev.azure.com/microsoft/Dart/_build/latest?definitionId=76541&branchName=main) |
|
||||
| ARM64 | [](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=main) | [](https://dev.azure.com/shine-oss/PowerToys/_build/latest?definitionId=3&branchName=main) | [](https://dev.azure.com/microsoft/Dart/_build/latest?definitionId=76541&branchName=main) |
|
||||
|
||||
## About
|
||||
|
||||
@@ -43,17 +43,17 @@ Go to the [Microsoft PowerToys GitHub releases page][github-release-link] and cl
|
||||
<!-- 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.83%22
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.82%22
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysUserSetup-0.82.0-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysUserSetup-0.82.0-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysSetup-0.82.0-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.0/PowerToysSetup-0.82.0-arm64.exe
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.1/PowerToysUserSetup-0.82.1-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.1/PowerToysUserSetup-0.82.1-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.1/PowerToysSetup-0.82.1-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.82.1/PowerToysSetup-0.82.1-arm64.exe
|
||||
|
||||
| Description | Filename | sha256 hash |
|
||||
|----------------|----------|-------------|
|
||||
| Per user - x64 | [PowerToysUserSetup-0.82.0-x64.exe][ptUserX64] | 295E2A4622C7E347D3E1BAEA6B36BECC328B566496678F1F87DE3F8A12A7F89A |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.82.0-arm64.exe][ptUserArm64] | 55D25D068C6148F0A15C7806B9F813224ABA9C461943F42BB2A8B0E22D28240C |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.82.0-x64.exe][ptMachineX64] | 01B59C00BB43C25BEFEF274755875717AB4DEAB57C0354AB96CF5B1DA4837C9A |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.82.0-arm64.exe][ptMachineArm64] | 1F642B50962516127793C4D3556BF4FC24B9738BAC2F362CAA3BFF8B0C3AF97F |
|
||||
| Per user - x64 | [PowerToysUserSetup-0.82.1-x64.exe][ptUserX64] | B594C9A32125079186DCE776431E2DC77B896774D2AEE2ACF51BAB8791683485 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.82.1-arm64.exe][ptUserArm64] | 41C1D9C0E8FA7EFFCE6F605C92C143AE933F8C999A2933A4D9D1115B16F14F67 |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.82.1-x64.exe][ptMachineX64] | B8FA7E7C8F88B69E070E234F561D32807634E2E9D782EDBB9DC35F3A454F2264 |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.82.1-arm64.exe][ptMachineArm64] | 58F22306F22CF9878C6DDE6AC128388DF4DFF78B76165E38A695490E55B3C8C4 |
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
@@ -151,7 +151,7 @@ In this release, we focused on stability and improvements.
|
||||
### Installer
|
||||
|
||||
- Fixed the remaining install failures when the folders the DSC module is to be installed in isn't accessible by the WiX installer for user scope installations.
|
||||
- Fixed an issue causing ARM 64 uninstall process to not correctly finding powershell 7 to run uninstall scripts.
|
||||
- Fixed an issue causing ARM64 uninstall process to not correctly find powershell 7 to run uninstall scripts.
|
||||
|
||||
### Peek
|
||||
|
||||
|
||||
@@ -71,12 +71,14 @@ The following formats are currently available:
|
||||
- All available settings for the plugin are defined in the [`TimeDateSettings`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/TimeDateSettings.cs) class of the plugin. The settings can be accessed everywhere in the plugin code via the static class instance `TimeDateSettings.Instance`.
|
||||
- We have the following settings that the user can configure to change the behavior of the plugin:
|
||||
|
||||
| Key | Default value | Name | Description |
|
||||
|--------------|-----------|------------|------------|
|
||||
| `OnlyDateTimeNowGlobal` | `true` | Show only 'Time', 'Date', and 'Now' result for system time on global queries | Regardless of this setting, for global queries the first word of the query has to be a complete match. |
|
||||
| `TimeWithSeconds` | `false` | Show time with seconds | This setting applies to the 'Time' and 'Now' result. |
|
||||
| `DateWithWeekday` | `false` | Show date with weekday and name of month | This setting applies to the 'Date' and 'Now' result. |
|
||||
| `HideNumberMessageOnGlobalQuery` | `false` | Hide 'Invalid number input' error message on global queries | |
|
||||
| Key | Type | Default value | Name | Description |
|
||||
|--------------|--------------|-----------|------------|------------|
|
||||
| `CalendarFirstWeekRule` | Combo box | `-1` (Use system settings) | First week of the year | Configure the calendar rule for the first week of the year. |
|
||||
| `FirstDayOfWeek` | Combo box | `-1` (Use system settings) | First day of the week | |
|
||||
| `OnlyDateTimeNowGlobal` | Checkbox | `true` | Show only 'Time', 'Date', and 'Now' result for system time on global queries | Regardless of this setting, for global queries the first word of the query has to be a complete match. |
|
||||
| `TimeWithSeconds` | Checkbox | `false` | Show time with seconds | This setting applies to the 'Time' and 'Now' result. |
|
||||
| `DateWithWeekday` | Checkbox | `false` | Show date with weekday and name of month | This setting applies to the 'Date' and 'Now' result. |
|
||||
| `HideNumberMessageOnGlobalQuery` | Checkbox | `false` | Hide 'Invalid number input' error message on global queries | |
|
||||
|
||||
|
||||
## Classes
|
||||
@@ -97,6 +99,7 @@ The following formats are currently available:
|
||||
|
||||
### [`TimeAndDateHelper.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/TimeAndDateHelper.cs)
|
||||
- The [`TimeAndDateHelper`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/TimeAndDateHelper.cs) class contains methods to format/convert date and time formats/strings.
|
||||
- And it contains methods to return the `first week day` and `first week of the year rule` based on the current plugin settings.
|
||||
|
||||
### [`TimeDateSettings.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/TimeDateSettings.cs)
|
||||
- The [`TimeDateSettings`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/TimeDateSettings.cs) class provides access to all optional plugin settings.
|
||||
@@ -129,11 +132,6 @@ On global queries the high score returned by `FuzzySearch` has negative impacts
|
||||
## [Unit Tests](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests)
|
||||
We have a [Unit Test project](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests) that executes various test to ensure that the plugin works as expected.
|
||||
|
||||
### [`TimeDateResultTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/TimeDateResultTests.cs)
|
||||
- The [`TimeDateResultTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/TimeDateResultTests.cs) class contains tests to validate that the time and date values are correctly formatted/calculated.
|
||||
- That we can execute the tests at any time on any machine, we use a specified date/time value and set the thread culture always to `en-us` while executing the tests.
|
||||
- Some tests contain checks that calculate the expected result at runtime instead of using an expected value written fix in the code. This is done to get valid results on every machine at any time.
|
||||
|
||||
### [`ImageTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/ImageTests.cs)
|
||||
- The [`ImageTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/ImageTests.cs) class contains tests to validate that each result shows the expected and correct image.
|
||||
- That we can execute the tests at any time on any machine, we set the thread culture always to `en-us` while executing the tests.
|
||||
@@ -147,4 +145,13 @@ We have a [Unit Test project](/src/modules/launcher/Plugins/Microsoft.PowerToys.
|
||||
|
||||
### [`StringParserTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/StringParserTests.cs)
|
||||
- The [`StringParserTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/StringParserTests.cs) class contains tests to validate that the typed string gets converted correctly into a `DateTime` object.
|
||||
- That we can execute the tests at any time on any machine, we set the thread culture always to `en-us` while executing the tests.
|
||||
- That we can execute the tests at any time on any machine, we set the thread culture always to `en-us` while executing the tests.
|
||||
|
||||
### [`TimeAndDateHelperTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/TimeAndDateHelperTests.cs)
|
||||
- The [`TimeAndDateHelperTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/TimeAndDateHelperTests.cs) class contains tests to validate important methods form the `TimeAndDateHelper` class that are not used for string parsing.
|
||||
|
||||
### [`TimeDateResultTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/TimeDateResultTests.cs)
|
||||
- The [`TimeDateResultTests.cs`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests/TimeDateResultTests.cs) class contains tests to validate that the time and date values are correctly formatted/calculated.
|
||||
- That we can execute the tests at any time on any machine, we use a specified date/time value and set the thread culture always to `en-us` while executing the tests.
|
||||
- Some tests use custom settings for the first day of week and the first week of year. (This is done in the tests for the affected results to validate them for different settings/cultures.)
|
||||
- Some tests contain checks that calculate the expected result at runtime instead of using an expected value written fix in the code. This is done to get valid results on every machine at any time.
|
||||
@@ -1,21 +1,34 @@
|
||||
---
|
||||
last-update: 3-20-2022
|
||||
last-update: 7-16-2024
|
||||
---
|
||||
|
||||
# PowerToys Awake Changelog
|
||||
|
||||
## Builds
|
||||
|
||||
The build ID can be found in `Program.cs` in the `BuildId` variable - it is a unique identifier for the current builds that allows better diagnostics (we can look up the build ID from the logs) and offers a way to triage Awake-specific issues faster independent of the PowerToys version. The build ID does not carry any significance beyond that within the PowerToys code base.
|
||||
The build ID can be found in `Core\Constants.cs` in the `BuildId` variable - it is a unique identifier for the current builds that allows better diagnostics (we can look up the build ID from the logs) and offers a way to triage Awake-specific issues faster independent of the PowerToys version. The build ID does not carry any significance beyond that within the PowerToys code base.
|
||||
|
||||
The build ID moniker is made up of two components - a reference to a [Halo](https://en.wikipedia.org/wiki/Halo_(franchise)) character, and the date when the work on the specific build started in the format of `MMDDYYYY`.
|
||||
|
||||
| Build ID | Build Date |
|
||||
|:----------------------------------------------------------|:-----------------|
|
||||
| [`DAISY023_04102024`](#DAISY023_04102024-april-10-2024) | April 10, 2024 |
|
||||
| [`ATRIOX_04132023`](#ATRIOX_04132023-april-13-2023) | April 13, 2023 |
|
||||
| [`LIBRARIAN_03202022`](#librarian_03202022-march-20-2022) | March 20, 2022 |
|
||||
| `ARBITER_01312022` | January 31, 2022 |
|
||||
|
||||
### `DAISY023_04102024` (April 10, 2024)
|
||||
|
||||
>[!NOTE]
|
||||
>See pull request: [Awake Update - `DAISY023_04102024`](https://github.com/microsoft/PowerToys/pull/32378)
|
||||
|
||||
- [#33630](https://github.com/microsoft/PowerToys/issues/33630) When in the UI and you select `0` as hours and `0` as minutes in `TIMED` awake mode, the UI becomes non-responsive whenever you try to get back to timed after it rolls back to `PASSIVE`.
|
||||
- [#12714](https://github.com/microsoft/PowerToys/issues/12714) Adds the option to keep track of Awake state through tray tooltip.
|
||||
- [#11996](https://github.com/microsoft/PowerToys/issues/11996) Adds custom icons support for mode changes in Awake.
|
||||
- Removes the dependency on `System.Windows.Forms` and instead uses native Windows APIs to create the tray icon.
|
||||
- Removes redundant/unused code that impacted application performance.
|
||||
- Updates dependent packages to their latest versions (`Microsoft.Windows.CsWinRT` and `System.Reactive`).
|
||||
|
||||
### `ATRIOX_04132023` (April 13, 2023)
|
||||
|
||||
- Moves from using `Task.Run` to spin up threads to actually using a blocking queue that properly sets thread parameters on the same thread.
|
||||
|
||||
@@ -36,6 +36,8 @@ Contact the developers of a plugin directly for assistance with a specific plugi
|
||||
| [WebSearchShortcut](https://github.com/Daydreamer-riri/PowerToys-Run-WebSearchShortcut) | [Riri](https://github.com/Daydreamer-riri) | Select a specific search engine to perform searches. |
|
||||
| [UnicodeInput](https://github.com/nathancartlidge/powertoys-run-unicode) | [nathancartlidge](https://github.com/nathancartlidge) | Copy Unicode characters to the clipboard |
|
||||
| [PowerHexInspector](https://github.com/NaroZeol/PowerHexInspector) | [NaroZeol](https://github.com/NaroZeol) | Peek other forms of an input number |
|
||||
| [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 |
|
||||
|
||||
## Extending software plugins
|
||||
|
||||
@@ -47,6 +49,7 @@ Below are community created plugins that target a website or software. They are
|
||||
| [Edge Workspaces](https://github.com/quachpas/PowerToys-Run-EdgeWorkspaces) | [quachpas](https://github.com/quachpas) | Open Microsoft Edge workspaces|
|
||||
| [Everything](https://github.com/lin-ycv/EverythingPowerToys) | [Yu Chieh (Victor) Lin](https://github.com/Lin-ycv) | Get search results from Everything |
|
||||
| [GitKraken](https://github.com/davidegiacometti/PowerToys-Run-GitKraken) | [davidegiacometti](https://github.com/davidegiacometti) | Open GitKraken repositories |
|
||||
| [RDP](https://github.com/anthony81799/PowerToysRun-RDP)) | [anthony81799](https://github.com/anthony81799) | Open Remote Desktop connections |
|
||||
| [Visual Studio Recents](https://github.com/davidegiacometti/PowerToys-Run-VisualStudio) | [davidegiacometti](https://github.com/davidegiacometti) | Open Visual Studio recents |
|
||||
| [WinGet](https://github.com/bostrot/PowerToysRunPluginWinget) | [bostrot](https://github.com/bostrot) | Search and install packages from WinGet |
|
||||
| [Scoop](https://github.com/Quriz/PowerToysRunScoop) | [Quriz](https://github.com/Quriz) | Search and install packages from Scoop |
|
||||
|
||||
@@ -76,4 +76,12 @@
|
||||
<Error Condition="!Exists('..\wix.props')"
|
||||
Text="$([System.String]::Format('$(ErrorText)', '..\wix.props'))" />
|
||||
</Target>
|
||||
|
||||
<!-- Prevents NU1503 -->
|
||||
<Target Name="_IsProjectRestoreSupported" Returns="@(_ValidProjectsForRestore)">
|
||||
<ItemGroup>
|
||||
<_ValidProjectsForRestore Include="$(MSBuildProjectFullPath)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="Restore" />
|
||||
</Project>
|
||||
@@ -185,4 +185,12 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
|
||||
<Target Name="BeforeBuild">
|
||||
<HeatDirectory Directory="..\..\src\common\FilePreviewCommon\Assets\Monaco\monacoSRC" PreprocessorVariable="var.MonacoSRCHarvestPath" OutputFile="MonacoSRC.wxs" ComponentGroupName="MonacoSRCHeatGenerated" DirectoryRefId="MonacoPreviewHandlerMonacoSRCFolder" AutogenerateGuids="false" GenerateGuidsNow="true" ToolPath="$(WixToolPath)" RunAsSeparateProcess="true" SuppressFragments="false" SuppressRegistry="false" SuppressRootDirectory="true"/>
|
||||
</Target>
|
||||
|
||||
<!-- Prevents NU1503 -->
|
||||
<Target Name="_IsProjectRestoreSupported" Returns="@(_ValidProjectsForRestore)">
|
||||
<ItemGroup>
|
||||
<_ValidProjectsForRestore Include="$(MSBuildProjectFullPath)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="Restore" />
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.MSBuildCache.AzurePipelines" version="0.1.271-preview" />
|
||||
<package id="Microsoft.MSBuildCache.Local" version="0.1.271-preview" />
|
||||
<package id="Microsoft.MSBuildCache.SharedCompilation" version="0.1.271-preview" />
|
||||
<package id="Microsoft.MSBuildCache.AzurePipelines" version="0.1.283-preview" />
|
||||
<package id="Microsoft.MSBuildCache.Local" version="0.1.283-preview" />
|
||||
<package id="Microsoft.MSBuildCache.SharedCompilation" version="0.1.283-preview" />
|
||||
</packages>
|
||||
@@ -9,7 +9,7 @@
|
||||
// `theme` can be "vs" for light theme or "vs-dark" for dark theme
|
||||
// `lang` is the language of the file
|
||||
// `wrap` if the editor is wrapping or not
|
||||
|
||||
|
||||
var theme = ("[[PT_THEME]]" == "dark") ? "vs-dark" : "vs";
|
||||
var lang = "[[PT_LANG]]";
|
||||
var wrap = ([[PT_WRAP]] == 1) ? true : false;
|
||||
@@ -19,11 +19,29 @@
|
||||
var stickyScroll = ([[PT_STICKY_SCROLL]] == 1) ? true : false;
|
||||
|
||||
var fontSize = [[PT_FONT_SIZE]];
|
||||
|
||||
var contextMenu = ([[PT_CONTEXTMENU]] == 1) ? true : false;
|
||||
|
||||
var editor;
|
||||
|
||||
// Code taken from https://stackoverflow.com/a/30106551/14774889
|
||||
var code = decodeURIComponent(atob(base64code).split('').map(function(c) {
|
||||
var code = decodeURIComponent(atob(base64code).split('').map(function (c) {
|
||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
||||
}).join(''));
|
||||
|
||||
function runToggleTextWrapCommand() {
|
||||
if (wrap) {
|
||||
editor.updateOptions({ wordWrap: 'off' })
|
||||
} else {
|
||||
editor.updateOptions({ wordWrap: 'on' })
|
||||
}
|
||||
wrap = !wrap;
|
||||
}
|
||||
|
||||
function runCopyCommand() {
|
||||
editor.focus();
|
||||
document.execCommand('copy');
|
||||
}
|
||||
|
||||
</script>
|
||||
<!-- Set browser to Edge-->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
@@ -33,32 +51,33 @@
|
||||
<title>Previewer for developer Files</title>
|
||||
<style>
|
||||
/* Fits content to window size */
|
||||
html, body{
|
||||
padding:0;
|
||||
html, body {
|
||||
padding: 0;
|
||||
}
|
||||
#container,.monaco-editor {
|
||||
position:fixed;
|
||||
height:100%;
|
||||
left:0;
|
||||
top:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
|
||||
#container, .monaco-editor {
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.overflowingContentWidgets{
|
||||
|
||||
.overflowingContentWidgets {
|
||||
/*Hides alert box */
|
||||
display:none!important
|
||||
}
|
||||
display: none !important
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body oncontextmenu="onContextMenu()">
|
||||
<body>
|
||||
<!-- Container for the editor -->
|
||||
<div id="container"></div>
|
||||
<!-- Script -->
|
||||
<script src="http://[[PT_URL]]/monacoSRC/min/vs/loader.js"></script>
|
||||
<script src="http://[[PT_URL]]/monacoSpecialLanguages.js" type="module"></script>
|
||||
<script type="module">
|
||||
var editor;
|
||||
<script type="module">
|
||||
import { registerAdditionalLanguages } from 'http://[[PT_URL]]/monacoSpecialLanguages.js';
|
||||
import { customTokenColors } from 'http://[[PT_URL]]/customTokenColors.js';
|
||||
require.config({ paths: { vs: 'http://[[PT_URL]]/monacoSRC/min/vs' } });
|
||||
@@ -80,8 +99,9 @@
|
||||
language: lang, // Sets language of the code
|
||||
readOnly: true, // Sets to readonly
|
||||
theme: 'theme', // Sets editor theme
|
||||
minimap: {enabled: false}, // Disables minimap
|
||||
minimap: { enabled: false }, // Disables minimap
|
||||
lineNumbersMinChars: '3', // Width of the line numbers
|
||||
contextmenu: contextMenu,
|
||||
scrollbar: {
|
||||
// Deactivate shadows
|
||||
shadows: false,
|
||||
@@ -90,7 +110,7 @@
|
||||
vertical: 'auto',
|
||||
horizontal: 'auto',
|
||||
},
|
||||
stickyScroll: {enabled: stickyScroll},
|
||||
stickyScroll: { enabled: stickyScroll },
|
||||
fontSize: fontSize,
|
||||
wordWrap: (wrap ? 'on' : 'off') // Word wraps
|
||||
});
|
||||
@@ -117,12 +137,7 @@
|
||||
// Method that will be executed when the action is triggered.
|
||||
// @param editor The editor instance is passed in as a convenience
|
||||
run: function (ed) {
|
||||
if (wrap) {
|
||||
editor.updateOptions({ wordWrap: 'off' })
|
||||
} else {
|
||||
editor.updateOptions({ wordWrap: 'on' })
|
||||
}
|
||||
wrap = !wrap;
|
||||
runToggleTextWrapCommand();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -151,4 +166,4 @@
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -176,4 +176,40 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getAllowedAdvancedPasteOnlineAIModelsValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbClipboardSharingEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbClipboardSharingEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbFileTransferEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbFileTransferEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbUseOriginalUserInterfaceValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbUseOriginalUserInterfaceValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbDisallowBlockingScreensaverValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbDisallowBlockingScreensaverValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbSameSubnetOnlyValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbSameSubnetOnlyValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbValidateRemoteIpValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbValidateRemoteIpValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMwbDisableUserDefinedIpMappingRulesValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMwbDisableUserDefinedIpMappingRulesValue());
|
||||
}
|
||||
winrt::hstring GPOWrapper::GetConfiguredMwbPolicyDefinedIpMappingRules()
|
||||
{
|
||||
// Assuming powertoys_gpo::getConfiguredMwbPolicyDefinedIpMappingRules() returns a std::wstring
|
||||
std::wstring rules = powertoys_gpo::getConfiguredMwbPolicyDefinedIpMappingRules();
|
||||
|
||||
// Convert std::wstring to winrt::hstring
|
||||
return to_hstring(rules.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,14 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbClipboardSharingEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbFileTransferEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbUseOriginalUserInterfaceValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisallowBlockingScreensaverValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbSameSubnetOnlyValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbValidateRemoteIpValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisableUserDefinedIpMappingRulesValue();
|
||||
static winrt::hstring GPOWrapper::GetConfiguredMwbPolicyDefinedIpMappingRules();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,14 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
static GpoRuleConfigured GetAllowedAdvancedPasteOnlineAIModelsValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbClipboardSharingEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbFileTransferEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbUseOriginalUserInterfaceValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisallowBlockingScreensaverValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbSameSubnetOnlyValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbValidateRemoteIpValue();
|
||||
static GpoRuleConfigured GetConfiguredMwbDisableUserDefinedIpMappingRulesValue();
|
||||
static String GetConfiguredMwbPolicyDefinedIpMappingRules();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,15 @@ namespace UnitTestsVersionHelper
|
||||
Assert::AreEqual(25ull, sut->minor);
|
||||
Assert::AreEqual(1ull, sut->revision);
|
||||
}
|
||||
TEST_METHOD (stringConstructorShouldProperlyInitializationVersionNumbersWithUppercaseV)
|
||||
{
|
||||
auto sut = VersionHelper::fromString(L"V2.25.1");
|
||||
Assert::IsTrue(sut.has_value());
|
||||
|
||||
Assert::AreEqual(2ull, sut->major);
|
||||
Assert::AreEqual(25ull, sut->minor);
|
||||
Assert::AreEqual(1ull, sut->revision);
|
||||
}
|
||||
TEST_METHOD (emptyStringNotAccepted)
|
||||
{
|
||||
auto sut = VersionHelper::fromString("");
|
||||
|
||||
@@ -47,9 +47,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Windows.h>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace powertoys_gpo {
|
||||
enum gpo_rule_configured_t {
|
||||
@@ -71,11 +72,25 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS = L"PowerLauncherAllPluginsEnabledState";
|
||||
const std::wstring POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS = L"AllowPowerToysAdvancedPasteOnlineAIModels";
|
||||
const std::wstring POLICY_MWB_CLIPBOARD_SHARING_ENABLED = L"MwbClipboardSharingEnabled";
|
||||
const std::wstring POLICY_MWB_FILE_TRANSFER_ENABLED = L"MwbFileTransferEnabled";
|
||||
const std::wstring POLICY_MWB_USE_ORIGINAL_USER_INTERFACE = L"MwbUseOriginalUserInterface";
|
||||
const std::wstring POLICY_MWB_DISALLOW_BLOCKING_SCREENSAVER = L"MwbDisallowBlockingScreensaver";
|
||||
const std::wstring POLICY_MWB_SAME_SUBNET_ONLY = L"MwbSameSubnetOnly";
|
||||
const std::wstring POLICY_MWB_VALIDATE_REMOTE_IP = L"MwbValidateRemoteIp";
|
||||
const std::wstring POLICY_MWB_DISABLE_USER_DEFINED_IP_MAPPING_RULES = L"MwbDisableUserDefinedIpMappingRules";
|
||||
const std::wstring POLICY_MWB_POLICY_DEFINED_IP_MAPPING_RULES = L"MwbPolicyDefinedIpMappingRules";
|
||||
|
||||
inline std::optional<std::wstring> readRegistryStringValue(HKEY hRootKey, const std::wstring& subKey, const std::wstring& value_name)
|
||||
inline std::optional<std::wstring> readRegistryStringValue(HKEY hRootKey, const std::wstring& subKey, const std::wstring& value_name, const bool is_multi_line_text = false)
|
||||
{
|
||||
// Set value type
|
||||
DWORD reg_value_type = REG_SZ;
|
||||
DWORD reg_flags = RRF_RT_REG_SZ;
|
||||
if (is_multi_line_text)
|
||||
{
|
||||
reg_value_type = REG_MULTI_SZ;
|
||||
reg_flags = RRF_RT_REG_MULTI_SZ;
|
||||
}
|
||||
|
||||
DWORD string_buffer_capacity;
|
||||
// Request required buffer capacity / string length
|
||||
@@ -97,8 +112,26 @@ namespace powertoys_gpo {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Convert buffer to std::wstring, delete buffer and return REG_SZ value
|
||||
std::wstring string_value = temp_buffer;
|
||||
// Convert buffer to std::wstring
|
||||
std::wstring string_value = L"";
|
||||
if (reg_value_type == REG_MULTI_SZ)
|
||||
{
|
||||
// If it is REG_MULTI_SZ handle this way
|
||||
wchar_t* currentString = temp_buffer;
|
||||
while (*currentString != L'\0')
|
||||
{
|
||||
// If first entry then assign the string, else add to the string
|
||||
string_value = (string_value == L"") ? currentString : (string_value + L"\r\n" + currentString);
|
||||
currentString += wcslen(currentString) + 1; // Move to the next string
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it is REG_SZ handle this way
|
||||
string_value = temp_buffer;
|
||||
}
|
||||
|
||||
// delete buffer, return string value
|
||||
delete temp_buffer;
|
||||
return string_value;
|
||||
}
|
||||
@@ -475,4 +508,59 @@ namespace powertoys_gpo {
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_ALLOW_ADVANCED_PASTE_ONLINE_AI_MODELS);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbClipboardSharingEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_MWB_CLIPBOARD_SHARING_ENABLED);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbFileTransferEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_MWB_FILE_TRANSFER_ENABLED);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbUseOriginalUserInterfaceValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_MWB_USE_ORIGINAL_USER_INTERFACE);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbDisallowBlockingScreensaverValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_MWB_DISALLOW_BLOCKING_SCREENSAVER);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbSameSubnetOnlyValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_MWB_SAME_SUBNET_ONLY);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbValidateRemoteIpValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_MWB_VALIDATE_REMOTE_IP);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredMwbDisableUserDefinedIpMappingRulesValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_MWB_DISABLE_USER_DEFINED_IP_MAPPING_RULES);
|
||||
}
|
||||
|
||||
inline std::wstring getConfiguredMwbPolicyDefinedIpMappingRules()
|
||||
{
|
||||
// Important: HKLM has priority over HKCU
|
||||
auto mapping_rules = readRegistryStringValue(HKEY_LOCAL_MACHINE, POLICIES_PATH, POLICY_MWB_POLICY_DEFINED_IP_MAPPING_RULES, true);
|
||||
if (!mapping_rules.has_value())
|
||||
{
|
||||
mapping_rules = readRegistryStringValue(HKEY_CURRENT_USER, POLICIES_PATH, POLICY_MWB_POLICY_DEFINED_IP_MAPPING_RULES, true);
|
||||
}
|
||||
|
||||
// return value
|
||||
if (mapping_rules.has_value())
|
||||
{
|
||||
return mapping_rules.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::wstring ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ struct Constants;
|
||||
template<>
|
||||
struct Constants<char>
|
||||
{
|
||||
static inline const char* V = "v";
|
||||
static inline const char* LOWER_V = "v";
|
||||
static inline const char* UPPER_V = "V";
|
||||
static inline const char* DOT = ".";
|
||||
static inline const char SPACE = ' ';
|
||||
};
|
||||
@@ -26,7 +27,8 @@ struct Constants<char>
|
||||
template<>
|
||||
struct Constants<wchar_t>
|
||||
{
|
||||
static inline const wchar_t* V = L"v";
|
||||
static inline const wchar_t* LOWER_V = L"v";
|
||||
static inline const wchar_t* UPPER_V = L"V";
|
||||
static inline const wchar_t* DOT = L".";
|
||||
static inline const wchar_t SPACE = L' ';
|
||||
};
|
||||
@@ -36,7 +38,8 @@ std::optional<VersionHelper> fromString(std::basic_string_view<CharT> str)
|
||||
{
|
||||
try
|
||||
{
|
||||
str = left_trim<CharT>(trim<CharT>(str), Constants<CharT>::V);
|
||||
str = left_trim<CharT>(trim<CharT>(str), Constants<CharT>::LOWER_V);
|
||||
str = left_trim<CharT>(trim<CharT>(str), Constants<CharT>::UPPER_V);
|
||||
std::basic_string<CharT> spacedStr{ str };
|
||||
replace_chars<CharT>(spacedStr, Constants<CharT>::DOT, Constants<CharT>::SPACE);
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.10" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.11" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyNamespaces>
|
||||
<target prefix="powertoys" namespace="Microsoft.Policies.PowerToys" />
|
||||
</policyNamespaces>
|
||||
<resources minRequiredRevision="1.10"/><!-- Last changed with PowerToys v0.81.1 -->
|
||||
<resources minRequiredRevision="1.11"/><!-- Last changed with PowerToys v0.83.0 -->
|
||||
<supportedOn>
|
||||
<definitions>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0)"/>
|
||||
@@ -19,6 +19,7 @@
|
||||
<definition name="SUPPORTED_POWERTOYS_0_78_0" displayName="$(string.SUPPORTED_POWERTOYS_0_78_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_81_0" displayName="$(string.SUPPORTED_POWERTOYS_0_81_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_81_1" displayName="$(string.SUPPORTED_POWERTOYS_0_81_1)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_83_0" displayName="$(string.SUPPORTED_POWERTOYS_0_83_0)"/>
|
||||
</definitions>
|
||||
</supportedOn>
|
||||
<categories>
|
||||
@@ -32,10 +33,17 @@
|
||||
<category name="AdvancedPaste" displayName="$(string.AdvancedPaste)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
</category>
|
||||
<category name="MouseWithoutBorders" displayName="$(string.MouseWithoutBorders)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
</category>
|
||||
<category name="GeneralSettings" displayName="$(string.GeneralSettings)">
|
||||
<parentCategory ref="PowerToys" />
|
||||
</category>
|
||||
</categories>
|
||||
<policies>
|
||||
|
||||
<policy name="ConfigureGlobalUtilityEnabledState" class="Both" displayName="$(string.ConfigureGlobalUtilityEnabledState)" explainText="$(string.ConfigureGlobalUtilityEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="ConfigureGlobalUtilityEnabledState">
|
||||
<!--The name (id) of the policy is different to sort it as first policy in edit dialog. The order is sorted alphabetically based on the "name" property.-->
|
||||
<policy name="ConfigureAllUtilityGlobalEnabledState" class="Both" displayName="$(string.ConfigureAllUtilityGlobalEnabledState)" explainText="$(string.ConfigureAllUtilityGlobalEnabledStateDescription)" key="Software\Policies\PowerToys" valueName="ConfigureGlobalUtilityEnabledState">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
|
||||
<enabledValue>
|
||||
@@ -467,7 +475,7 @@
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="AllowExperimentation" class="Both" displayName="$(string.AllowExperimentation)" explainText="$(string.AllowExperimentationDescription)" key="Software\Policies\PowerToys" valueName="AllowExperimentation">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<parentCategory ref="GeneralSettings" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_68_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
@@ -503,5 +511,83 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbClipboardSharingEnabled" class="Both" displayName="$(string.MwbClipboardSharingEnabled)" explainText="$(string.MwbClipboardSharingEnabledDescription)" key="Software\Policies\PowerToys" valueName="MwbClipboardSharingEnabled">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbFileTransferEnabled" class="Both" displayName="$(string.MwbFileTransferEnabled)" explainText="$(string.MwbFileTransferEnabledDescription)" key="Software\Policies\PowerToys" valueName="MwbFileTransferEnabled">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbUseOriginalUserInterface" class="Both" displayName="$(string.MwbUseOriginalUserInterface)" explainText="$(string.MwbUseOriginalUserInterfaceDescription)" key="Software\Policies\PowerToys" valueName="MwbUseOriginalUserInterface">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbDisallowBlockingScreensaver" class="Both" displayName="$(string.MwbDisallowBlockingScreensaver)" explainText="$(string.MwbDisallowBlockingScreensaverDescription)" key="Software\Policies\PowerToys" valueName="MwbDisallowBlockingScreensaver">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbSameSubnetOnly" class="Both" displayName="$(string.MwbSameSubnetOnly)" explainText="$(string.MwbSameSubnetOnlyDescription)" key="Software\Policies\PowerToys" valueName="MwbSameSubnetOnly">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbValidateRemoteIp" class="Both" displayName="$(string.MwbValidateRemoteIp)" explainText="$(string.MwbValidateRemoteIpDescription)" key="Software\Policies\PowerToys" valueName="MwbValidateRemoteIp">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbDisableUserDefinedIpMappingRules" class="Both" displayName="$(string.MwbDisableUserDefinedIpMappingRules)" explainText="$(string.MwbDisableUserDefinedIpMappingRulesDescription)" key="Software\Policies\PowerToys" valueName="MwbDisableUserDefinedIpMappingRules">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="MwbPolicyDefinedIpMappingRules" class="Both" displayName="$(string.MwbPolicyDefinedIpMappingRules)" explainText="$(string.MwbPolicyDefinedIpMappingRulesDescription)" presentation="$(presentation.MwbPolicyDefinedIpMappingRules)" key="Software\Policies\PowerToys">
|
||||
<parentCategory ref="MouseWithoutBorders" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_83_0" />
|
||||
<elements>
|
||||
<!--Max length means here max length per line. We support 65 characters per line. (A string containing the hostname, a space and an IPv6 Address is max. 55 characters long.)-->
|
||||
<multiText id="MwbPolicyDefinedIpMappingsList" valueName="MwbPolicyDefinedIpMappingRules" maxLength="65" required="true"/>
|
||||
</elements>
|
||||
</policy>
|
||||
</policies>
|
||||
</policyDefinitions>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.10" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.11" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<displayName>PowerToys</displayName>
|
||||
<description>PowerToys</description>
|
||||
<resources>
|
||||
@@ -10,6 +10,8 @@
|
||||
<string id="InstallerUpdates">Installer and Updates</string>
|
||||
<string id="PowerToysRun">PowerToys Run</string>
|
||||
<string id="AdvancedPaste">Advanced Paste</string>
|
||||
<string id="MouseWithoutBorders">Mouse Without Borders</string>
|
||||
<string id="GeneralSettings">General settings</string>
|
||||
|
||||
<string id="SUPPORTED_POWERTOYS_0_64_0">PowerToys version 0.64.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_68_0">PowerToys version 0.68.0 or later</string>
|
||||
@@ -22,8 +24,9 @@
|
||||
<string id="SUPPORTED_POWERTOYS_0_78_0">PowerToys version 0.78.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_81_0">PowerToys version 0.81.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_81_1">PowerToys version 0.81.1 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_83_0">PowerToys version 0.83.0 or later</string>
|
||||
|
||||
<string id="ConfigureGlobalUtilityEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
<string id="ConfigureAllUtilityGlobalEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
|
||||
If you enable this setting, all utilities will be always enabled and the user won't be able to disable it.
|
||||
|
||||
@@ -121,13 +124,72 @@ You can set the enabled state for all plugins not configured by this policy usin
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
</string>
|
||||
<string id="AllowPowerToysAdvancedPasteOnlineAIModelsDescription">This policy configures the enabled disable state for using Advanced Paste online AI models.
|
||||
<string id="AllowPowerToysAdvancedPasteOnlineAIModelsDescription">This policy allows you to disable Advanced Paste online AI models.
|
||||
|
||||
If you enable or don't configure this policy, the user takes control over the enabled state of the Enable paste with AI Advanced Paste setting.
|
||||
|
||||
If you disable this policy, the user won't be able to enable Enable paste with AI Advanced Paste setting and use Advanced Paste AI prompt nor set up the Open AI key in PowerToys Settings.
|
||||
</string>
|
||||
<string id="ConfigureGlobalUtilityEnabledState">Configure global utility enabled state</string>
|
||||
<string id="MwbClipboardSharingEnabledDescription">This policy configures if the user can share the clipboard between machines.
|
||||
|
||||
If you enable or don't configure this policy, the user takes control over the clipboard sharing setting.
|
||||
|
||||
If you disable this policy, the user won't be able to enable the clipboard sharing setting.
|
||||
</string>
|
||||
<string id="MwbFileTransferEnabledDescription">This policy configures if the user can transfer files between machines.
|
||||
|
||||
If you enable or don't configure this policy, the user takes control over the file sharing setting.
|
||||
|
||||
If you disable this policy, the user won't be able to enable the file sharing Settings.
|
||||
|
||||
Note: The file sharing feature depends on the clipboard sharing feature. Disabling clipboard sharing automatically disables file sharing too.
|
||||
</string>
|
||||
<string id="MwbUseOriginalUserInterfaceDescription">This policy configures if the user can use the old Mouse Without Borders user interface.
|
||||
|
||||
If you enable or don't configure this policy, the user takes control over the setting and can enable or disable the old user interface.
|
||||
|
||||
If you disable this policy, the user won't be able to enable the old user interface.
|
||||
</string>
|
||||
<string id="MwbDisallowBlockingScreensaverDescription">This policy configures if the user is allowed to disable the screensaver on the remote machines.
|
||||
|
||||
If you enable this policy, the user won't be able to enable the "block screensaver" screensaver setting and the screensaver is not blocked.
|
||||
|
||||
If you disable or don't configure this policy, the user takes control over the setting and can block the screensaver.
|
||||
</string>
|
||||
|
||||
<string id="MwbSameSubnetOnlyDescription">This policy configures if connections are only allowed in the same subnet.
|
||||
|
||||
If you enable this policy, the setting is enabled and only connections in the same subnet are allowed.
|
||||
|
||||
If you disable this policy, the setting is disabled and all connections are allowed.
|
||||
|
||||
If you don't configure this policy, the user takes control over the setting and can enable or disable it.
|
||||
</string>
|
||||
<string id="MwbValidateRemoteIpDescription">This policy configures if reverse DNS lookup is used to validate the remote machine IP Address.
|
||||
|
||||
If you enable this policy, the setting is enabled and the IP Address is validated.
|
||||
|
||||
If you disable this policy, the setting is disabled and the IP Address is not validated.
|
||||
|
||||
If you don't configure this policy, the user takes control over the setting and can enable or disable it.
|
||||
</string>
|
||||
<string id="MwbDisableUserDefinedIpMappingRulesDescription">This policy configures if the user can define IP Address mapping rules.
|
||||
|
||||
If you enable this policy, the setting is disabled and the user can't define rules or use existing ones.
|
||||
|
||||
If you disable or don't configure this policy, the user takes control over the setting.
|
||||
|
||||
Note: Enabling this policy does not prevent policy defined mapping rules from working.
|
||||
</string>
|
||||
<string id="MwbPolicyDefinedIpMappingRulesDescription">This policy allows you to define IP Address mapping rules.
|
||||
|
||||
If you enable this policy, you can define IP Address mapping rules that the user can't change or disable.
|
||||
Please enter one mapping per line in the format: "hostname IP"
|
||||
|
||||
If you disable or don't configure this policy, no predefined rules are applied.
|
||||
</string>
|
||||
|
||||
<string id="ConfigureAllUtilityGlobalEnabledState">Configure global utility enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAdvancedPaste">Advanced Paste: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAlwaysOnTop">Always On Top: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityAwake">Awake: Configure enabled state</string>
|
||||
@@ -173,13 +235,24 @@ If you disable this policy, the user won't be able to enable Enable paste with A
|
||||
<string id="PowerToysRunIndividualPluginEnabledState">Configure enabled state for individual plugins</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIPreview">QOI file preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIThumbnails">QOI file thumbnail: Configure enabled state</string>
|
||||
<string id="AllowPowerToysAdvancedPasteOnlineAIModels">Advanced Paste: Allow using online AI models</string>
|
||||
<string id="AllowPowerToysAdvancedPasteOnlineAIModels">Allow using online AI models</string>
|
||||
<string id="MwbClipboardSharingEnabled">Clipboard sharing enabled</string>
|
||||
<string id="MwbFileTransferEnabled">File transfer enabled</string>
|
||||
<string id="MwbUseOriginalUserInterface">Original user interface is available</string>
|
||||
<string id="MwbDisallowBlockingScreensaver">Disallow blocking screensaver on other machines</string>
|
||||
<string id="MwbSameSubnetOnly">Connect only in same subnet</string>
|
||||
<string id="MwbValidateRemoteIp">Validate remote machine IP Address</string>
|
||||
<string id="MwbDisableUserDefinedIpMappingRules">Disable user defined IP Address mapping rules</string>
|
||||
<string id="MwbPolicyDefinedIpMappingRules">Predefined IP Address mapping rules</string>
|
||||
</stringTable>
|
||||
|
||||
<presentationTable>
|
||||
<presentation id="PowerToysRunIndividualPluginEnabledState">
|
||||
<listBox refId="PowerToysRunIndividualPluginEnabledList">List of managed plugins:</listBox>
|
||||
</presentation>
|
||||
<presentation id="MwbPolicyDefinedIpMappingRules">
|
||||
<multiTextBox refId="MwbPolicyDefinedIpMappingsList">List of IP Address mappings:</multiTextBox>
|
||||
</presentation>
|
||||
</presentationTable>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
@@ -74,7 +74,8 @@
|
||||
<!-- HACK: To align Microsoft.Bcl.AsyncInterfaces.dll version with PowerToys.Settings.csproj. -->
|
||||
<PackageReference Include="StreamJsonRpc" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -24,6 +24,14 @@ namespace AdvancedPaste.Helpers
|
||||
private static readonly char[] CsvDelimArry = [',', ';', '\t'];
|
||||
private static readonly Regex CsvSepIdentifierRegex = new Regex(@"^sep=(.)$", RegexOptions.IgnoreCase);
|
||||
|
||||
// CSV: Split on every occurrence of the delimiter except if it is enclosed by " and ignore two " as escaped "
|
||||
private static readonly string CsvDelimSepRegexStr = @"(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
|
||||
|
||||
// CSV: Regex to remove/replace quotation marks
|
||||
private static readonly Regex CsvRemoveSingleQuotationMarksRegex = new Regex(@"^""(?!"")|(?<!"")""$|^""""$");
|
||||
private static readonly Regex CsvRemoveStartAndEndQuotationMarksRegex = new Regex(@"^""(?=(""{2})+)|(?<=(""{2})+)""$");
|
||||
private static readonly Regex CsvReplaceDoubleQuotationMarksRegex = new Regex(@"""{2}");
|
||||
|
||||
internal static string ToJsonFromXmlOrCsv(DataPackageView clipboardData)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
@@ -131,7 +139,7 @@ namespace AdvancedPaste.Helpers
|
||||
{
|
||||
if (string.IsNullOrEmpty(jsonText))
|
||||
{
|
||||
var csv = new List<string[]>();
|
||||
var csv = new List<IEnumerable<string>>();
|
||||
|
||||
string[] lines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
@@ -146,10 +154,12 @@ namespace AdvancedPaste.Helpers
|
||||
continue;
|
||||
}
|
||||
|
||||
// A CSV line is valid, if the delimiter occurs more or equal times in every line compared to the first data line. (More because sometimes the delimiter occurs in a data string.)
|
||||
if (line.Count(x => x == delim) >= delimCount)
|
||||
// A CSV line is valid, if the delimiter occurs equal times in every line compared to the first data line
|
||||
// and if every line contains no or an even count of quotation marks.
|
||||
if (Regex.Count(line, delim + CsvDelimSepRegexStr) == delimCount && int.IsEvenInteger(line.Count(x => x == '"')))
|
||||
{
|
||||
csv.Add(line.Split(delim));
|
||||
string[] dataCells = Regex.Split(line, delim + CsvDelimSepRegexStr, RegexOptions.IgnoreCase);
|
||||
csv.Add(dataCells.Select(x => ReplaceQuotationMarksInCsvData(x)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -205,7 +215,7 @@ namespace AdvancedPaste.Helpers
|
||||
// We get the count from the second line, as the first one only contains the character definition and not a CSV data line.
|
||||
char delimChar = matchChar.Groups[1].Value.Trim()[0];
|
||||
delimiter = delimChar;
|
||||
delimiterCount = csvLines[1].Count(x => x == delimChar);
|
||||
delimiterCount = Regex.Count(csvLines[1], delimChar + CsvDelimSepRegexStr, RegexOptions.IgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,19 +224,19 @@ namespace AdvancedPaste.Helpers
|
||||
// Try to select the correct delimiter based on the first two CSV lines from a list of predefined delimiters.
|
||||
foreach (char c in CsvDelimArry)
|
||||
{
|
||||
int cntFirstLine = csvLines[0].Count(x => x == c);
|
||||
int cntFirstLine = Regex.Count(csvLines[0], c + CsvDelimSepRegexStr, RegexOptions.IgnoreCase);
|
||||
int cntNextLine = 0; // Default to 0 that the 'second line' check is always true.
|
||||
|
||||
// Additional count if we have more than one line
|
||||
if (csvLines.Length >= 2)
|
||||
{
|
||||
cntNextLine = csvLines[1].Count(x => x == c);
|
||||
cntNextLine = Regex.Count(csvLines[1], c + CsvDelimSepRegexStr, RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
// The delimiter is found if the count is bigger as from the last selected delimiter
|
||||
// and if the next csv line does not exist or has the same number or more occurrences of the delimiter.
|
||||
// and if the next csv line does not exist or has the same number of occurrences of the delimiter.
|
||||
// (We check the next line to prevent false positives.)
|
||||
if (cntFirstLine > delimiterCount && (cntNextLine == 0 || cntNextLine >= cntFirstLine))
|
||||
if (cntFirstLine > delimiterCount && (cntNextLine == 0 || cntNextLine == cntFirstLine))
|
||||
{
|
||||
delimiter = c;
|
||||
delimiterCount = cntFirstLine;
|
||||
@@ -240,5 +250,26 @@ namespace AdvancedPaste.Helpers
|
||||
throw new FormatException("Invalid CSV format: Failed to detect the delimiter.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove and replace quotation marks used as control sequences. (Enclosing quotation marks and escaping quotation marks.)
|
||||
/// </summary>
|
||||
/// <param name="str">CSV cell data to manipulate.</param>
|
||||
/// <returns>Manipulated string.</returns>
|
||||
private static string ReplaceQuotationMarksInCsvData(string str)
|
||||
{
|
||||
// Remove first and last single quotation mark (enclosing quotation marks) and remove quotation marks of an empty data set ("").
|
||||
str = CsvRemoveSingleQuotationMarksRegex.Replace(str, string.Empty);
|
||||
|
||||
// Remove first quotation mark if followed by pairs of quotation marks
|
||||
// and remove last quotation mark if precede by pairs of quotation marks.
|
||||
// (Removes enclosing quotation marks around the cell data for data like /"""abc"""/.)
|
||||
str = CsvRemoveStartAndEndQuotationMarksRegex.Replace(str, string.Empty);
|
||||
|
||||
// Replace pairs of two quotation marks with a single quotation mark. (Escaped quotation marks.)
|
||||
str = CsvReplaceDoubleQuotationMarksRegex.Replace(str, "\"");
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,8 @@
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?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 FileLocksmithContextMenu.base.rc FileLocksmithContextMenu.rc" />
|
||||
</Target>
|
||||
@@ -98,7 +99,30 @@ MakeAppx.exe pack /d . /p $(OutDir)FileLocksmithContextMenuPackage.msix /nv</Com
|
||||
<None Include="Resources.resx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Assets\FileLocksmith\**" CopyToOutputDirectory="PreserveNewest" />
|
||||
<None Include="Assets\FileLocksmith\FileLocksmith.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\LargeTile.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\SmallTile.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\SplashScreen.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\Square150x150Logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\Square44x44Logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\storelogo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\Wide310x150Logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
@@ -118,11 +142,14 @@ MakeAppx.exe pack /d . /p $(OutDir)FileLocksmithContextMenuPackage.msix /nv</Com
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<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.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.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'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -37,10 +37,38 @@
|
||||
<None Include="Resources.resx">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\FileLocksmith.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\LargeTile.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\SmallTile.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\SplashScreen.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\Square44x44Logo.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\Square150x150Logo.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\storelogo.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Assets\FileLocksmith\Wide310x150Logo.png">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="FileLocksmithContextMenu.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,4 +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>
|
||||
@@ -1,5 +1,6 @@
|
||||
<?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')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
@@ -78,7 +79,18 @@
|
||||
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -51,4 +51,7 @@
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -25,6 +25,8 @@ namespace FileLocksmithUI
|
||||
Logger.InitializeLogger("\\File Locksmith\\FileLocksmithUI\\Logs");
|
||||
|
||||
this.InitializeComponent();
|
||||
|
||||
UnhandledException += App_UnhandledException;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -55,6 +57,11 @@ namespace FileLocksmithUI
|
||||
_window.Activate();
|
||||
}
|
||||
|
||||
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Logger.LogError("Unhandled exception", e.Exception);
|
||||
}
|
||||
|
||||
private Window _window;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,27 +141,16 @@
|
||||
IsTextSelectionEnabled="True"
|
||||
Text="{x:Bind user}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard ContentAlignment="Vertical">
|
||||
<tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard.Header>
|
||||
<TextBlock>
|
||||
<Run x:Uid="Files" />
|
||||
<Run Text="(" /><Run Text="{x:Bind files, Converter={StaticResource fileCountConverter}}" /><Run Text=")" />
|
||||
</TextBlock>
|
||||
</tkcontrols:SettingsCard.Header>
|
||||
<ItemsRepeater ItemsSource="{x:Bind files}">
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate x:DataType="x:String">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
IsTextSelectionEnabled="True"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{Binding}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap"
|
||||
ToolTipService.ToolTip="{Binding}" />
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
<Button Click="ShowProcessFiles_Click">
|
||||
<TextBlock x:Uid="ShowProcessFiles" />
|
||||
</Button>
|
||||
</tkcontrols:SettingsCard>
|
||||
</tkcontrols:SettingsExpander.Items>
|
||||
</tkcontrols:SettingsExpander>
|
||||
@@ -200,5 +189,13 @@
|
||||
Text="{x:Bind ViewModel.PathsToString, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
</ContentDialog>
|
||||
<ContentDialog x:Name="ProcessFilesListDialog" x:Uid="ProcessFilesListDialog">
|
||||
<ScrollViewer Padding="15" HorizontalScrollBarVisibility="Auto">
|
||||
<TextBlock
|
||||
x:Name="ProcessFilesListDialogTextBlock"
|
||||
x:Uid="ProcessFilesListDialogTextBlock"
|
||||
IsTextSelectionEnabled="True" />
|
||||
</ScrollViewer>
|
||||
</ContentDialog>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using FileLocksmith.Interop;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using PowerToys.FileLocksmithUI.ViewModels;
|
||||
|
||||
@@ -19,9 +21,17 @@ namespace PowerToys.FileLocksmithUI.Views
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private async void ShowSelectedPathsButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
private async void ShowSelectedPathsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await SelectedFilesListDialog.ShowAsync();
|
||||
}
|
||||
|
||||
private async void ShowProcessFiles_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var processResult = (ProcessResult)((FrameworkElement)sender).DataContext;
|
||||
ProcessFilesListDialogTextBlock.Text = string.Join(Environment.NewLine, processResult.files);
|
||||
|
||||
await ProcessFilesListDialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,13 @@
|
||||
<data name="Files.Text" xml:space="preserve">
|
||||
<value>Files</value>
|
||||
</data>
|
||||
<data name="ProcessFilesListDialog.Title" xml:space="preserve">
|
||||
<value>Files</value>
|
||||
</data>
|
||||
<data name="ProcessFilesListDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
<comment>As in, close a dialog prompt.</comment>
|
||||
</data>
|
||||
<data name="PathsTooltipDescription.Text" xml:space="preserve">
|
||||
<value>Click to see the entire list of paths.</value>
|
||||
<comment>Paths as in file paths that were selected for the utility to check.</comment>
|
||||
@@ -164,4 +171,8 @@
|
||||
<value>Administrator: File Locksmith</value>
|
||||
<comment>Title of the window when running as administrator.</comment>
|
||||
</data>
|
||||
<data name="ShowProcessFiles.Text" xml:space="preserve">
|
||||
<value>Show files</value>
|
||||
<comment>Show files for the selected process</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="System.IO.Abstractions.TestingHelpers" />
|
||||
<PackageReference Include="System.Diagnostics.EventLog">
|
||||
|
||||
@@ -76,6 +76,8 @@
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.CodeDom">
|
||||
<!-- This package is a dependency of System.Management, but we need to set it here so we can exclude the assets, so it doesn't conflict with the 8.0.1 dll coming from .NET SDK. -->
|
||||
<ExcludeAssets>runtime</ExcludeAssets> <!-- Should already be present on .net sdk runtime, so we avoid the conflicting runtime version from nuget -->
|
||||
|
||||
@@ -12,8 +12,10 @@ using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
|
||||
@@ -259,6 +261,11 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbClipboardSharingEnabledValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.ShareClipboard;
|
||||
@@ -267,6 +274,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (ShareClipboardIsGpoConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.ShareClipboard = value;
|
||||
@@ -274,10 +286,19 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool ShareClipboardIsGpoConfigured => GPOWrapper.GetConfiguredMwbClipboardSharingEnabledValue() == GpoRuleConfigured.Disabled;
|
||||
|
||||
internal bool TransferFile
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbFileTransferEnabledValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.TransferFile;
|
||||
@@ -286,10 +307,19 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (TransferFileIsGpoConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_properties.TransferFile = value;
|
||||
}
|
||||
}
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool TransferFileIsGpoConfigured => GPOWrapper.GetConfiguredMwbFileTransferEnabledValue() == GpoRuleConfigured.Disabled;
|
||||
|
||||
internal bool MatrixOneRow
|
||||
{
|
||||
get
|
||||
@@ -448,6 +478,8 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
// Note(@htcfreek): Settings UI CheckBox is disabled in frmMatrix.cs > FrmMatrix_Load()
|
||||
// Note(@htcfreek): If this settings gets implemented in the future we need a Group Policy for it!
|
||||
internal bool DisableCAD
|
||||
{
|
||||
get
|
||||
@@ -456,6 +488,8 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
// Note(@htcfreek): Settings UI CheckBox is disabled in frmMatrix.cs > FrmMatrix_Load()
|
||||
// Note(@htcfreek): If this settings gets implemented in the future we need a Group Policy for it!
|
||||
internal bool HideLogonLogo
|
||||
{
|
||||
get
|
||||
@@ -487,6 +521,11 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbDisallowBlockingScreensaverValue() == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.BlockScreenSaverOnOtherMachines;
|
||||
@@ -495,6 +534,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (BlockScreenSaverIsGpoConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.BlockScreenSaverOnOtherMachines = value;
|
||||
@@ -502,6 +546,10 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool BlockScreenSaverIsGpoConfigured => GPOWrapper.GetConfiguredMwbDisallowBlockingScreensaverValue() == GpoRuleConfigured.Enabled;
|
||||
|
||||
internal bool MoveMouseRelatively
|
||||
{
|
||||
get
|
||||
@@ -791,6 +839,15 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.ValidateRemoteMachineIP;
|
||||
@@ -799,6 +856,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (ReverseLookupIsGpoConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.ValidateRemoteMachineIP = value;
|
||||
@@ -806,10 +868,23 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool ReverseLookupIsGpoConfigured => GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Enabled || GPOWrapper.GetConfiguredMwbValidateRemoteIpValue() == GpoRuleConfigured.Disabled;
|
||||
|
||||
internal bool SameSubNetOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.SameSubnetOnly;
|
||||
@@ -818,6 +893,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (SameSubNetOnlyIsGpoConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.SameSubnetOnly = value;
|
||||
@@ -825,10 +905,19 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool SameSubNetOnlyIsGpoConfigured => GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Enabled || GPOWrapper.GetConfiguredMwbSameSubnetOnlyValue() == GpoRuleConfigured.Disabled;
|
||||
|
||||
internal string Name2IP
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbDisableUserDefinedIpMappingRulesValue() == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.Name2IP.Value;
|
||||
@@ -837,6 +926,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (Name2IpIsGpoConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.Name2IP.Value = value;
|
||||
@@ -844,6 +938,18 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool Name2IpIsGpoConfigured => GPOWrapper.GetConfiguredMwbDisableUserDefinedIpMappingRulesValue() == GpoRuleConfigured.Enabled;
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal string Name2IpPolicyList => GPOWrapper.GetConfiguredMwbPolicyDefinedIpMappingRules();
|
||||
|
||||
[CmdConfigureIgnore]
|
||||
[JsonIgnore]
|
||||
internal bool Name2IpPolicyListIsGpoConfigured => !string.IsNullOrWhiteSpace(Name2IpPolicyList);
|
||||
|
||||
internal bool FirstCtrlShiftS
|
||||
{
|
||||
get
|
||||
@@ -950,6 +1056,11 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbUseOriginalUserInterfaceValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.ShowOriginalUI;
|
||||
@@ -958,6 +1069,11 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
set
|
||||
{
|
||||
if (GPOWrapper.GetConfiguredMwbUseOriginalUserInterfaceValue() == GpoRuleConfigured.Disabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.ShowOriginalUI = value;
|
||||
@@ -989,6 +1105,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
// Note(@htcfreek): Settings UI CheckBox is disabled in frmMatrix.cs > FrmMatrix_Load()
|
||||
internal bool SendErrorLogV2
|
||||
{
|
||||
get
|
||||
|
||||
@@ -887,7 +887,8 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (!string.IsNullOrEmpty(Setting.Values.Name2IP))
|
||||
{
|
||||
string[] name2ip = Setting.Values.Name2IP.Split(Separator, StringSplitOptions.RemoveEmptyEntries);
|
||||
string combinedName2ipList = Setting.Values.Name2IpPolicyList + Separator + Setting.Values.Name2IP;
|
||||
string[] name2ip = combinedName2ipList.Split(Separator, StringSplitOptions.RemoveEmptyEntries);
|
||||
string[] nameNip;
|
||||
|
||||
if (name2ip != null)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using Windows.UI.Notifications;
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
@@ -88,6 +89,8 @@ namespace MouseWithoutBorders
|
||||
this.linkLabelReConfigure = new System.Windows.Forms.LinkLabel();
|
||||
this.tabControlSetting = new System.Windows.Forms.TabControl();
|
||||
this.tabPageAdvancedSettings = new System.Windows.Forms.TabPage();
|
||||
this.groupBoxName2IPPolicyList = new System.Windows.Forms.GroupBox();
|
||||
this.textBoxMachineName2IPPolicyList = new System.Windows.Forms.TextBox();
|
||||
this.pictureBoxMouseWithoutBorders = new System.Windows.Forms.PictureBox();
|
||||
this.groupBoxDNS = new System.Windows.Forms.GroupBox();
|
||||
this.textBoxMachineName2IP = new System.Windows.Forms.TextBox();
|
||||
@@ -103,6 +106,7 @@ namespace MouseWithoutBorders
|
||||
this.groupBoxMachineMatrix.SuspendLayout();
|
||||
this.tabControlSetting.SuspendLayout();
|
||||
this.tabPageAdvancedSettings.SuspendLayout();
|
||||
this.groupBoxName2IPPolicyList.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxMouseWithoutBorders)).BeginInit();
|
||||
this.groupBoxDNS.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
@@ -977,6 +981,7 @@ namespace MouseWithoutBorders
|
||||
// tabPageAdvancedSettings
|
||||
//
|
||||
this.tabPageAdvancedSettings.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(246)))), ((int)(((byte)(245)))), ((int)(((byte)(242)))));
|
||||
this.tabPageAdvancedSettings.Controls.Add(this.groupBoxName2IPPolicyList);
|
||||
this.tabPageAdvancedSettings.Controls.Add(this.pictureBoxMouseWithoutBorders);
|
||||
this.tabPageAdvancedSettings.Controls.Add(this.groupBoxDNS);
|
||||
this.tabPageAdvancedSettings.Controls.Add(this.textBoxDNS);
|
||||
@@ -986,6 +991,33 @@ namespace MouseWithoutBorders
|
||||
this.tabPageAdvancedSettings.Size = new System.Drawing.Size(563, 362);
|
||||
this.tabPageAdvancedSettings.TabIndex = 2;
|
||||
this.tabPageAdvancedSettings.Text = "IP Mappings";
|
||||
//
|
||||
// groupBoxName2IPPolicyList
|
||||
//
|
||||
this.groupBoxName2IPPolicyList.Controls.Add(this.textBoxMachineName2IPPolicyList);
|
||||
this.groupBoxName2IPPolicyList.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.groupBoxName2IPPolicyList.Location = new System.Drawing.Point(3, 241);
|
||||
this.groupBoxName2IPPolicyList.Name = "groupBoxName2IPPolicyList";
|
||||
this.groupBoxName2IPPolicyList.Size = new System.Drawing.Size(357, 150);
|
||||
this.groupBoxName2IPPolicyList.TabIndex = 1;
|
||||
this.groupBoxName2IPPolicyList.TabStop = false;
|
||||
this.groupBoxName2IPPolicyList.Text = " Policy defined machine name to IP address mappings [Managed]";
|
||||
this.groupBoxName2IPPolicyList.ForeColor = Color.DimGray;
|
||||
this.groupBoxName2IPPolicyList.Visible = false;
|
||||
//
|
||||
// textBoxMachineName2IPPolicyList
|
||||
//
|
||||
this.textBoxMachineName2IPPolicyList.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.textBoxMachineName2IPPolicyList.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.textBoxMachineName2IPPolicyList.Location = new System.Drawing.Point(3, 172); // 3,172
|
||||
this.textBoxMachineName2IPPolicyList.MaxLength = 1024;
|
||||
this.textBoxMachineName2IPPolicyList.Multiline = true;
|
||||
this.textBoxMachineName2IPPolicyList.Name = "textBoxMachineName2IPPolicyList";
|
||||
this.textBoxMachineName2IPPolicyList.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.textBoxMachineName2IPPolicyList.Size = new System.Drawing.Size(351, 131);
|
||||
this.textBoxMachineName2IPPolicyList.TabIndex = 1;
|
||||
this.textBoxMachineName2IPPolicyList.ReadOnly = true;
|
||||
this.textBoxMachineName2IPPolicyList.Visible = false;
|
||||
//
|
||||
// pictureBoxMouseWithoutBorders
|
||||
//
|
||||
@@ -1098,12 +1130,13 @@ namespace MouseWithoutBorders
|
||||
this.tabControlSetting.ResumeLayout(false);
|
||||
this.tabPageAdvancedSettings.ResumeLayout(false);
|
||||
this.tabPageAdvancedSettings.PerformLayout();
|
||||
this.groupBoxName2IPPolicyList.ResumeLayout(false);
|
||||
this.groupBoxName2IPPolicyList.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBoxMouseWithoutBorders)).EndInit();
|
||||
this.groupBoxDNS.ResumeLayout(false);
|
||||
this.groupBoxDNS.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1140,6 +1173,8 @@ namespace MouseWithoutBorders
|
||||
private GroupBox groupBoxDNS;
|
||||
private TextBox textBoxDNS;
|
||||
private TextBox textBoxMachineName2IP;
|
||||
private GroupBox groupBoxName2IPPolicyList;
|
||||
private TextBox textBoxMachineName2IPPolicyList;
|
||||
private PictureBox pictureBoxMouseWithoutBorders;
|
||||
private GroupBox groupBoxOtherOptions;
|
||||
private CheckBox checkBoxDrawMouse;
|
||||
|
||||
@@ -797,6 +797,14 @@ namespace MouseWithoutBorders
|
||||
checkBoxHideLogo.Enabled = false;
|
||||
}
|
||||
|
||||
// Note(@htcfreek): Disable checkboxes of settings that we don't support in the PowerToys implementation
|
||||
checkBoxDisableCAD.Enabled = false;
|
||||
checkBoxDisableCAD.Text = checkBoxDisableCAD.Text + " [Unsupported!]";
|
||||
checkBoxHideLogo.Enabled = false;
|
||||
checkBoxHideLogo.Text = checkBoxHideLogo.Text + " [Unsupported!]";
|
||||
checkBoxSendLog.Enabled = false;
|
||||
checkBoxSendLog.Text = checkBoxSendLog.Text + " [Unsupported!]";
|
||||
|
||||
checkBoxShareClipboard.Checked = Setting.Values.ShareClipboard;
|
||||
|
||||
if (!Setting.Values.ShareClipboard)
|
||||
@@ -845,6 +853,56 @@ namespace MouseWithoutBorders
|
||||
|
||||
comboBoxEasyMouse.Text = Setting.Values.HotKeyToggleEasyMouse == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyToggleEasyMouse });
|
||||
#endif
|
||||
|
||||
// Apply policy configuration on UI elements
|
||||
// Has to be the last action
|
||||
if (Setting.Values.ShareClipboardIsGpoConfigured)
|
||||
{
|
||||
checkBoxShareClipboard.Enabled = false;
|
||||
checkBoxShareClipboard.Text += " [Managed]";
|
||||
|
||||
// transfer file setting depends on clipboard sharing
|
||||
checkBoxTransferFile.Enabled = false;
|
||||
}
|
||||
|
||||
if (Setting.Values.TransferFileIsGpoConfigured)
|
||||
{
|
||||
checkBoxTransferFile.Enabled = false;
|
||||
checkBoxTransferFile.Text += " [Managed]";
|
||||
}
|
||||
|
||||
if (Setting.Values.BlockScreenSaverIsGpoConfigured)
|
||||
{
|
||||
checkBoxBlockScreenSaver.Enabled = false;
|
||||
checkBoxBlockScreenSaver.Text += " [Managed]";
|
||||
}
|
||||
|
||||
if (Setting.Values.SameSubNetOnlyIsGpoConfigured)
|
||||
{
|
||||
checkBoxSameSubNet.Enabled = false;
|
||||
checkBoxSameSubNet.Text += " [Managed]";
|
||||
}
|
||||
|
||||
if (Setting.Values.ReverseLookupIsGpoConfigured)
|
||||
{
|
||||
checkBoxReverseLookup.Enabled = false;
|
||||
checkBoxReverseLookup.Text += " [Managed]";
|
||||
}
|
||||
|
||||
if (Setting.Values.Name2IpIsGpoConfigured)
|
||||
{
|
||||
textBoxMachineName2IP.Enabled = false;
|
||||
groupBoxDNS.ForeColor = Color.DimGray;
|
||||
groupBoxDNS.Text += " [Managed]";
|
||||
}
|
||||
|
||||
if (Setting.Values.Name2IpPolicyListIsGpoConfigured)
|
||||
{
|
||||
pictureBoxMouseWithoutBorders.Visible = false;
|
||||
groupBoxName2IPPolicyList.Visible = true;
|
||||
textBoxMachineName2IPPolicyList.Visible = true;
|
||||
textBoxMachineName2IPPolicyList.Text = Setting.Values.Name2IpPolicyList;
|
||||
}
|
||||
}
|
||||
|
||||
private void RadioButton_CheckedChanged(object sender, EventArgs e)
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" />
|
||||
<PackageReference Include="StreamJsonRpc" />
|
||||
<PackageReference Include="System.Data.SqlClient" /> <!-- It's a dependency of Microsoft.Windows.Compatibility. We're adding it here to force it to the version specified in Directory.Packages.props -->
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<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">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{2833C9C6-AB32-4048-A5C7-A70898337B57}</ProjectGuid>
|
||||
@@ -67,11 +67,14 @@
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<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.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.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'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -95,7 +95,55 @@
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="PropertySheet.props" />
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\**">
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\0.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\1.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\2.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\3.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\4.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\5.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\6.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\7.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\8.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\9.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\no_active_window.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay_portrait.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
|
||||
BIN
src/modules/awake/Awake/Assets/Awake/disabled.ico
Normal file
BIN
src/modules/awake/Awake/Assets/Awake/disabled.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
src/modules/awake/Awake/Assets/Awake/expirable.ico
Normal file
BIN
src/modules/awake/Awake/Assets/Awake/expirable.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
src/modules/awake/Awake/Assets/Awake/indefinite.ico
Normal file
BIN
src/modules/awake/Awake/Assets/Awake/indefinite.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
src/modules/awake/Awake/Assets/Awake/normal.ico
Normal file
BIN
src/modules/awake/Awake/Assets/Awake/normal.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
src/modules/awake/Awake/Assets/Awake/scheduled.ico
Normal file
BIN
src/modules/awake/Awake/Assets/Awake/scheduled.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
src/modules/awake/Awake/Assets/Awake/timed.ico
Normal file
BIN
src/modules/awake/Awake/Assets/Awake/timed.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
@@ -10,7 +10,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWindowsForms>False</UseWindowsForms>
|
||||
<!--Per documentation: https://learn.microsoft.com/dotnet/core/compatibility/windows-forms/5.0/automatically-infer-winexe-output-type#outputtype-set-to-winexe-for-wpf-and-winforms-apps -->
|
||||
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
|
||||
<AssemblyName>PowerToys.Awake</AssemblyName>
|
||||
@@ -35,6 +35,7 @@
|
||||
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
@@ -59,6 +60,12 @@
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Assets\Awake\Awake.ico" />
|
||||
<None Remove="Assets\Awake\disabled.ico" />
|
||||
<None Remove="Assets\Awake\expirable.ico" />
|
||||
<None Remove="Assets\Awake\indefinite.ico" />
|
||||
<None Remove="Assets\Awake\normal.ico" />
|
||||
<None Remove="Assets\Awake\scheduled.ico" />
|
||||
<None Remove="Assets\Awake\timed.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -90,6 +97,24 @@
|
||||
<Content Include="Assets\Awake\Awake.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Awake\disabled.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Awake\expirable.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Awake\indefinite.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Awake\normal.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Awake\scheduled.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Assets\Awake\timed.ico">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -8,7 +8,15 @@ namespace Awake.Core
|
||||
{
|
||||
internal const string AppName = "Awake";
|
||||
internal const string FullAppName = "PowerToys " + AppName;
|
||||
internal const string TrayWindowId = "WindowsForms10.Window.0.app.0.";
|
||||
internal const string TrayWindowId = "Awake.MessageWindow";
|
||||
internal const string BuildRegistryLocation = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
|
||||
|
||||
// PowerToys Awake build code name. Used for exact logging
|
||||
// that does not map to PowerToys broad version schema to pinpoint
|
||||
// internal issues easier.
|
||||
// Format of the build ID is: CODENAME_MMDDYYYY, where MMDDYYYY
|
||||
// is representative of the date when the last change was made before
|
||||
// the pull request is issued.
|
||||
internal const string BuildId = "DAISY023_04102024";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Awake.Core
|
||||
public static void AddRange<T>(this ICollection<T> target, IEnumerable<T> source)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(target);
|
||||
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
foreach (var element in source)
|
||||
@@ -20,5 +19,17 @@ namespace Awake.Core
|
||||
target.Add(element);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToHumanReadableString(this TimeSpan timeSpan)
|
||||
{
|
||||
// Get days, hours, minutes, and seconds from the TimeSpan
|
||||
int days = timeSpan.Days;
|
||||
int hours = timeSpan.Hours;
|
||||
int minutes = timeSpan.Minutes;
|
||||
int seconds = timeSpan.Seconds;
|
||||
|
||||
// Format the string based on the presence of days, hours, minutes, and seconds
|
||||
return $"{days:D2}{Properties.Resources.AWAKE_LABEL_DAYS} {hours:D2}{Properties.Resources.AWAKE_LABEL_HOURS} {minutes:D2}{Properties.Resources.AWAKE_LABEL_MINUTES} {seconds:D2}{Properties.Resources.AWAKE_LABEL_SECONDS}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reactive.Linq;
|
||||
@@ -30,25 +30,35 @@ namespace Awake.Core
|
||||
/// </summary>
|
||||
public class Manager
|
||||
{
|
||||
private static readonly CompositeFormat AwakeMinutes = System.Text.CompositeFormat.Parse(Properties.Resources.AWAKE_MINUTES);
|
||||
private static readonly CompositeFormat AwakeHours = System.Text.CompositeFormat.Parse(Properties.Resources.AWAKE_HOURS);
|
||||
private static bool _isUsingPowerToysConfig;
|
||||
|
||||
private static BlockingCollection<ExecutionState> _stateQueue;
|
||||
internal static bool IsUsingPowerToysConfig { get => _isUsingPowerToysConfig; set => _isUsingPowerToysConfig = value; }
|
||||
|
||||
private static readonly CompositeFormat AwakeMinutes = CompositeFormat.Parse(Resources.AWAKE_MINUTES);
|
||||
private static readonly CompositeFormat AwakeHours = CompositeFormat.Parse(Resources.AWAKE_HOURS);
|
||||
|
||||
private static readonly BlockingCollection<ExecutionState> _stateQueue;
|
||||
|
||||
// Core icons used for the tray
|
||||
private static readonly Icon _timedIcon = new(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets/Awake/timed.ico"));
|
||||
private static readonly Icon _expirableIcon = new(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets/Awake/expirable.ico"));
|
||||
private static readonly Icon _indefiniteIcon = new(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets/Awake/indefinite.ico"));
|
||||
private static readonly Icon _disabledIcon = new(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets/Awake/disabled.ico"));
|
||||
|
||||
private static CancellationTokenSource _tokenSource;
|
||||
|
||||
private static SettingsUtils? _moduleSettings;
|
||||
|
||||
private static SettingsUtils? ModuleSettings { get => _moduleSettings; set => _moduleSettings = value; }
|
||||
internal static SettingsUtils? ModuleSettings { get => _moduleSettings; set => _moduleSettings = value; }
|
||||
|
||||
static Manager()
|
||||
{
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
_stateQueue = new BlockingCollection<ExecutionState>();
|
||||
_stateQueue = [];
|
||||
ModuleSettings = new SettingsUtils();
|
||||
}
|
||||
|
||||
public static void StartMonitor()
|
||||
internal static void StartMonitor()
|
||||
{
|
||||
Thread monitorThread = new(() =>
|
||||
{
|
||||
@@ -70,7 +80,7 @@ namespace Awake.Core
|
||||
Bridge.SetConsoleCtrlHandler(handler, addHandler);
|
||||
}
|
||||
|
||||
public static void AllocateConsole()
|
||||
internal static void AllocateConsole()
|
||||
{
|
||||
Bridge.AllocConsole();
|
||||
|
||||
@@ -103,17 +113,12 @@ namespace Awake.Core
|
||||
|
||||
private static ExecutionState ComputeAwakeState(bool keepDisplayOn)
|
||||
{
|
||||
if (keepDisplayOn)
|
||||
{
|
||||
return ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_CONTINUOUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_CONTINUOUS;
|
||||
}
|
||||
return keepDisplayOn
|
||||
? ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_CONTINUOUS
|
||||
: ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_CONTINUOUS;
|
||||
}
|
||||
|
||||
public static void CancelExistingThread()
|
||||
internal static void CancelExistingThread()
|
||||
{
|
||||
Logger.LogInfo($"Attempting to ensure that the thread is properly cleaned up...");
|
||||
|
||||
@@ -128,100 +133,200 @@ namespace Awake.Core
|
||||
Logger.LogInfo("Instantiating of new token source and thread token completed.");
|
||||
}
|
||||
|
||||
public static void SetIndefiniteKeepAwake(bool keepDisplayOn = false)
|
||||
internal static void SetIndefiniteKeepAwake(bool keepDisplayOn = false)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AwakeIndefinitelyKeepAwakeEvent());
|
||||
|
||||
CancelExistingThread();
|
||||
|
||||
_stateQueue.Add(ComputeAwakeState(keepDisplayOn));
|
||||
|
||||
TrayHelper.SetShellIcon(TrayHelper.HiddenWindowHandle, $"{Constants.FullAppName} [{Resources.AWAKE_TRAY_TEXT_INDEFINITE}]", _indefiniteIcon, TrayIconAction.Update);
|
||||
|
||||
if (IsUsingPowerToysConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName) ?? new AwakeSettings();
|
||||
var settingsChanged = currentSettings.Properties.Mode != AwakeMode.INDEFINITE ||
|
||||
currentSettings.Properties.KeepDisplayOn != keepDisplayOn;
|
||||
|
||||
if (settingsChanged)
|
||||
{
|
||||
currentSettings.Properties.Mode = AwakeMode.INDEFINITE;
|
||||
currentSettings.Properties.KeepDisplayOn = keepDisplayOn;
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), Constants.AppName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to handle indefinite keep awake command: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetNoKeepAwake()
|
||||
internal static void SetExpirableKeepAwake(DateTimeOffset expireAt, bool keepDisplayOn = true)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AwakeNoKeepAwakeEvent());
|
||||
Logger.LogInfo($"Expirable keep-awake. Expected expiration date/time: {expireAt} with display on setting set to {keepDisplayOn}.");
|
||||
|
||||
CancelExistingThread();
|
||||
}
|
||||
|
||||
public static void SetExpirableKeepAwake(DateTimeOffset expireAt, bool keepDisplayOn = true)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AwakeExpirableKeepAwakeEvent());
|
||||
|
||||
CancelExistingThread();
|
||||
|
||||
if (expireAt > DateTime.Now && expireAt != null)
|
||||
if (expireAt > DateTimeOffset.Now)
|
||||
{
|
||||
Logger.LogInfo($"Starting expirable log for {expireAt}");
|
||||
_stateQueue.Add(ComputeAwakeState(keepDisplayOn));
|
||||
|
||||
Observable.Timer(expireAt).Subscribe(
|
||||
TrayHelper.SetShellIcon(TrayHelper.HiddenWindowHandle, $"{Constants.FullAppName} [{Resources.AWAKE_TRAY_TEXT_EXPIRATION} - {expireAt}]", _expirableIcon, TrayIconAction.Update);
|
||||
|
||||
Observable.Timer(expireAt - DateTimeOffset.Now).Subscribe(
|
||||
_ =>
|
||||
{
|
||||
Logger.LogInfo($"Completed expirable keep-awake.");
|
||||
CancelExistingThread();
|
||||
|
||||
SetPassiveKeepAwakeMode(Constants.AppName);
|
||||
if (IsUsingPowerToysConfig)
|
||||
{
|
||||
SetPassiveKeepAwake();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInfo("Exiting after expirable keep awake.");
|
||||
CompleteExit(Environment.ExitCode);
|
||||
}
|
||||
},
|
||||
_tokenSource.Token);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The target date is not in the future.
|
||||
Logger.LogError("The specified target date and time is not in the future.");
|
||||
Logger.LogError($"Current time: {DateTime.Now}\tTarget time: {expireAt}");
|
||||
Logger.LogError($"Current time: {DateTimeOffset.Now}\tTarget time: {expireAt}");
|
||||
}
|
||||
|
||||
if (IsUsingPowerToysConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName) ?? new AwakeSettings();
|
||||
var settingsChanged = currentSettings.Properties.Mode != AwakeMode.EXPIRABLE ||
|
||||
currentSettings.Properties.ExpirationDateTime != expireAt ||
|
||||
currentSettings.Properties.KeepDisplayOn != keepDisplayOn;
|
||||
|
||||
if (settingsChanged)
|
||||
{
|
||||
currentSettings.Properties.Mode = AwakeMode.EXPIRABLE;
|
||||
currentSettings.Properties.KeepDisplayOn = keepDisplayOn;
|
||||
currentSettings.Properties.ExpirationDateTime = expireAt;
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), Constants.AppName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to handle indefinite keep awake command: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetTimedKeepAwake(uint seconds, bool keepDisplayOn = true)
|
||||
internal static void SetTimedKeepAwake(uint seconds, bool keepDisplayOn = true)
|
||||
{
|
||||
Logger.LogInfo($"Timed keep-awake. Expected runtime: {seconds} seconds with display on setting set to {keepDisplayOn}.");
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AwakeTimedKeepAwakeEvent());
|
||||
|
||||
CancelExistingThread();
|
||||
|
||||
Logger.LogInfo($"Timed keep awake started for {seconds} seconds.");
|
||||
|
||||
_stateQueue.Add(ComputeAwakeState(keepDisplayOn));
|
||||
|
||||
Observable.Timer(TimeSpan.FromSeconds(seconds)).Subscribe(
|
||||
_ =>
|
||||
{
|
||||
Logger.LogInfo($"Completed timed thread.");
|
||||
CancelExistingThread();
|
||||
TrayHelper.SetShellIcon(TrayHelper.HiddenWindowHandle, $"{Constants.FullAppName} [{Resources.AWAKE_TRAY_TEXT_TIMED}]", _timedIcon, TrayIconAction.Update);
|
||||
|
||||
SetPassiveKeepAwakeMode(Constants.AppName);
|
||||
},
|
||||
_tokenSource.Token);
|
||||
var timerObservable = Observable.Timer(TimeSpan.FromSeconds(seconds));
|
||||
var intervalObservable = Observable.Interval(TimeSpan.FromSeconds(1)).TakeUntil(timerObservable);
|
||||
|
||||
var combinedObservable = Observable.CombineLatest(intervalObservable, timerObservable.StartWith(0), (elapsedSeconds, _) => elapsedSeconds + 1);
|
||||
|
||||
combinedObservable.Subscribe(
|
||||
elapsedSeconds =>
|
||||
{
|
||||
var timeRemaining = seconds - (uint)elapsedSeconds;
|
||||
if (timeRemaining >= 0)
|
||||
{
|
||||
TrayHelper.SetShellIcon(TrayHelper.HiddenWindowHandle, $"{Constants.FullAppName} [{Resources.AWAKE_TRAY_TEXT_TIMED}]\n{TimeSpan.FromSeconds(timeRemaining).ToHumanReadableString()}", _timedIcon, TrayIconAction.Update);
|
||||
}
|
||||
},
|
||||
() =>
|
||||
{
|
||||
Console.WriteLine("Completed timed thread.");
|
||||
CancelExistingThread();
|
||||
|
||||
if (IsUsingPowerToysConfig)
|
||||
{
|
||||
// If we're using PowerToys settings, we need to make sure that
|
||||
// we just switch over the Passive Keep-Awake.
|
||||
SetPassiveKeepAwake();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInfo("Exiting after timed keep-awake.");
|
||||
CompleteExit(Environment.ExitCode);
|
||||
}
|
||||
},
|
||||
_tokenSource.Token);
|
||||
|
||||
if (IsUsingPowerToysConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName) ?? new AwakeSettings();
|
||||
var timeSpan = TimeSpan.FromSeconds(seconds);
|
||||
var settingsChanged = currentSettings.Properties.Mode != AwakeMode.TIMED ||
|
||||
currentSettings.Properties.IntervalHours != (uint)timeSpan.Hours ||
|
||||
currentSettings.Properties.IntervalMinutes != (uint)timeSpan.Minutes;
|
||||
|
||||
if (settingsChanged)
|
||||
{
|
||||
currentSettings.Properties.Mode = AwakeMode.TIMED;
|
||||
currentSettings.Properties.IntervalHours = (uint)timeSpan.Hours;
|
||||
currentSettings.Properties.IntervalMinutes = (uint)timeSpan.Minutes;
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), Constants.AppName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to handle timed keep awake command: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void CompleteExit(int exitCode, ManualResetEvent? exitSignal, bool force = false)
|
||||
/// <summary>
|
||||
/// Performs a clean exit from Awake.
|
||||
/// </summary>
|
||||
/// <param name="exitCode">Exit code to exit with.</param>
|
||||
internal static void CompleteExit(int exitCode)
|
||||
{
|
||||
SetNoKeepAwake();
|
||||
SetPassiveKeepAwake(updateSettings: false);
|
||||
|
||||
IntPtr windowHandle = GetHiddenWindow();
|
||||
|
||||
if (windowHandle != IntPtr.Zero)
|
||||
if (TrayHelper.HiddenWindowHandle != IntPtr.Zero)
|
||||
{
|
||||
Bridge.SendMessage(windowHandle, Native.Constants.WM_CLOSE, 0, 0);
|
||||
// Delete the icon.
|
||||
TrayHelper.SetShellIcon(TrayHelper.HiddenWindowHandle, string.Empty, null, TrayIconAction.Delete);
|
||||
|
||||
// Close the message window that we used for the tray.
|
||||
Bridge.SendMessage(TrayHelper.HiddenWindowHandle, Native.Constants.WM_CLOSE, 0, 0);
|
||||
|
||||
Bridge.DestroyWindow(TrayHelper.HiddenWindowHandle);
|
||||
}
|
||||
|
||||
if (force)
|
||||
{
|
||||
Bridge.PostQuitMessage(exitCode);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
exitSignal?.Set();
|
||||
Bridge.DestroyWindow(windowHandle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Exit signal error ${ex}");
|
||||
}
|
||||
Bridge.PostQuitMessage(exitCode);
|
||||
Environment.Exit(exitCode);
|
||||
}
|
||||
|
||||
public static string GetOperatingSystemBuild()
|
||||
/// <summary>
|
||||
/// Gets the operating system for logging purposes.
|
||||
/// </summary>
|
||||
/// <returns>Returns the string representing the current OS build.</returns>
|
||||
internal static string GetOperatingSystemBuild()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -245,83 +350,71 @@ namespace Awake.Core
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Performance", "CA1806:Do not ignore method results", Justification = "Function returns DWORD value that identifies the current thread, but we do not need it.")]
|
||||
internal static IEnumerable<IntPtr> EnumerateWindowsForProcess(int processId)
|
||||
/// <summary>
|
||||
/// Generates the default system tray options in situations where no custom options are provided.
|
||||
/// </summary>
|
||||
/// <returns>Returns a dictionary of default Awake timed interval options.</returns>
|
||||
internal static Dictionary<string, int> GetDefaultTrayOptions()
|
||||
{
|
||||
var handles = new List<IntPtr>();
|
||||
var hCurrentWnd = IntPtr.Zero;
|
||||
|
||||
do
|
||||
{
|
||||
hCurrentWnd = Bridge.FindWindowEx(IntPtr.Zero, hCurrentWnd, null as string, null);
|
||||
Bridge.GetWindowThreadProcessId(hCurrentWnd, out uint targetProcessId);
|
||||
|
||||
if (targetProcessId == processId)
|
||||
{
|
||||
handles.Add(hCurrentWnd);
|
||||
}
|
||||
}
|
||||
while (hCurrentWnd != IntPtr.Zero);
|
||||
|
||||
return handles;
|
||||
}
|
||||
|
||||
[SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "In this context, the string is only converted to a hex value.")]
|
||||
internal static IntPtr GetHiddenWindow()
|
||||
{
|
||||
IEnumerable<IntPtr> windowHandles = EnumerateWindowsForProcess(Environment.ProcessId);
|
||||
var domain = AppDomain.CurrentDomain.GetHashCode().ToString("x");
|
||||
string targetClass = $"{Constants.TrayWindowId}{domain}";
|
||||
|
||||
foreach (var handle in windowHandles)
|
||||
{
|
||||
StringBuilder className = new(256);
|
||||
int classQueryResult = Bridge.GetClassName(handle, className, className.Capacity);
|
||||
if (classQueryResult != 0 && className.ToString().StartsWith(targetClass, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public static Dictionary<string, int> GetDefaultTrayOptions()
|
||||
{
|
||||
Dictionary<string, int> optionsList = new Dictionary<string, int>
|
||||
Dictionary<string, int> optionsList = new()
|
||||
{
|
||||
{ string.Format(CultureInfo.InvariantCulture, AwakeMinutes, 30), 1800 },
|
||||
{ Resources.AWAKE_1_HOUR, 3600 },
|
||||
{ string.Format(CultureInfo.InvariantCulture, AwakeHours, 1), 3600 },
|
||||
{ string.Format(CultureInfo.InvariantCulture, AwakeHours, 2), 7200 },
|
||||
};
|
||||
return optionsList;
|
||||
}
|
||||
|
||||
public static void SetPassiveKeepAwakeMode(string moduleName)
|
||||
/// <summary>
|
||||
/// Resets the computer to standard power settings.
|
||||
/// </summary>
|
||||
/// <param name="updateSettings">In certain cases, such as exits, we want to make sure that settings are not reset for the passive mode but rather retained based on previous execution. Default is to save settings, but otherwise it can be overridden.</param>
|
||||
internal static void SetPassiveKeepAwake(bool updateSettings = true)
|
||||
{
|
||||
AwakeSettings currentSettings;
|
||||
Logger.LogInfo($"Operating in passive mode (computer's standard power plan). No custom keep awake settings enabled.");
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(moduleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"Failed to reset Awake mode GetSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
currentSettings = new AwakeSettings();
|
||||
}
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.AwakeNoKeepAwakeEvent());
|
||||
|
||||
currentSettings.Properties.Mode = AwakeMode.PASSIVE;
|
||||
CancelExistingThread();
|
||||
|
||||
try
|
||||
TrayHelper.SetShellIcon(TrayHelper.HiddenWindowHandle, $"{Constants.FullAppName} [{Resources.AWAKE_TRAY_TEXT_OFF}]", _disabledIcon, TrayIconAction.Update);
|
||||
|
||||
if (IsUsingPowerToysConfig && updateSettings)
|
||||
{
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
try
|
||||
{
|
||||
var currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName) ?? new AwakeSettings();
|
||||
|
||||
if (currentSettings.Properties.Mode != AwakeMode.PASSIVE)
|
||||
{
|
||||
currentSettings.Properties.Mode = AwakeMode.PASSIVE;
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), Constants.AppName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to reset Awake mode: {ex.Message}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the display settings.
|
||||
/// </summary>
|
||||
internal static void SetDisplay()
|
||||
{
|
||||
if (IsUsingPowerToysConfig)
|
||||
{
|
||||
string? errorString = $"Failed to reset Awake mode SaveSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
try
|
||||
{
|
||||
var currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName) ?? new AwakeSettings();
|
||||
currentSettings.Properties.KeepDisplayOn = !currentSettings.Properties.KeepDisplayOn;
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), Constants.AppName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to handle display setting command: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
src/modules/awake/Awake/Core/Models/MSG.cs
Normal file
18
src/modules/awake/Awake/Core/Models/MSG.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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;
|
||||
|
||||
namespace Awake.Core.Models
|
||||
{
|
||||
internal struct Msg
|
||||
{
|
||||
public IntPtr HWnd;
|
||||
public uint Message;
|
||||
public IntPtr WParam;
|
||||
public IntPtr LParam;
|
||||
public uint Time;
|
||||
public Point Pt;
|
||||
}
|
||||
}
|
||||
21
src/modules/awake/Awake/Core/Models/MenuInfo.cs
Normal file
21
src/modules/awake/Awake/Core/Models/MenuInfo.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Awake.Core.Models
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MenuInfo
|
||||
{
|
||||
public uint CbSize; // Size of the structure, in bytes
|
||||
public uint FMask; // Specifies which members of the structure are valid
|
||||
public uint DwStyle; // Style of the menu
|
||||
public uint CyMax; // Maximum height of the menu, in pixels
|
||||
public IntPtr HbrBack; // Handle to the brush used for the menu's background
|
||||
public uint DwContextHelpID; // Context help ID
|
||||
public IntPtr DwMenuData; // Pointer to the menu's user data
|
||||
}
|
||||
}
|
||||
22
src/modules/awake/Awake/Core/Models/NOTIFYICONDATA.cs
Normal file
22
src/modules/awake/Awake/Core/Models/NOTIFYICONDATA.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Awake.Core.Models
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct NotifyIconData
|
||||
{
|
||||
public int CbSize;
|
||||
public IntPtr HWnd;
|
||||
public int UId;
|
||||
public int UFlags;
|
||||
public int UCallbackMessage;
|
||||
public IntPtr HIcon;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string SzTip;
|
||||
}
|
||||
}
|
||||
15
src/modules/awake/Awake/Core/Models/POINT.cs
Normal file
15
src/modules/awake/Awake/Core/Models/POINT.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
|
||||
namespace Awake.Core.Models
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Point
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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.Threading;
|
||||
|
||||
namespace Awake.Core.Models
|
||||
{
|
||||
internal sealed class SingleThreadSynchronizationContext : SynchronizationContext
|
||||
{
|
||||
private readonly Queue<Tuple<SendOrPostCallback, object>> queue =
|
||||
new();
|
||||
|
||||
#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
|
||||
public override void Post(SendOrPostCallback d, object state)
|
||||
#pragma warning restore CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
|
||||
{
|
||||
lock (queue)
|
||||
{
|
||||
queue.Enqueue(Tuple.Create(d, state));
|
||||
Monitor.Pulse(queue);
|
||||
}
|
||||
}
|
||||
|
||||
public void BeginMessageLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Tuple<SendOrPostCallback, object> work;
|
||||
lock (queue)
|
||||
{
|
||||
while (queue.Count == 0)
|
||||
{
|
||||
Monitor.Wait(queue);
|
||||
}
|
||||
|
||||
work = queue.Dequeue();
|
||||
}
|
||||
|
||||
if (work == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
work.Item1(work.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
public void EndMessageLoop()
|
||||
{
|
||||
lock (queue)
|
||||
{
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
queue.Enqueue(null); // Signal the end of the message loop
|
||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
Monitor.Pulse(queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@ namespace Awake.Core.Models
|
||||
{
|
||||
internal enum TrayCommands : uint
|
||||
{
|
||||
TC_DISPLAY_SETTING = Native.Constants.WM_USER + 1,
|
||||
TC_MODE_PASSIVE = Native.Constants.WM_USER + 2,
|
||||
TC_MODE_INDEFINITE = Native.Constants.WM_USER + 3,
|
||||
TC_MODE_EXPIRABLE = Native.Constants.WM_USER + 4,
|
||||
TC_EXIT = Native.Constants.WM_USER + 100,
|
||||
TC_TIME = Native.Constants.WM_USER + 101,
|
||||
TC_DISPLAY_SETTING = Native.Constants.WM_USER + 0x2,
|
||||
TC_MODE_PASSIVE = Native.Constants.WM_USER + 0x3,
|
||||
TC_MODE_INDEFINITE = Native.Constants.WM_USER + 0x4,
|
||||
TC_MODE_EXPIRABLE = Native.Constants.WM_USER + 0x5,
|
||||
TC_EXIT = Native.Constants.WM_USER + 0x64,
|
||||
TC_TIME = Native.Constants.WM_USER + 0x65,
|
||||
}
|
||||
}
|
||||
|
||||
13
src/modules/awake/Awake/Core/Models/TrayIconAction.cs
Normal file
13
src/modules/awake/Awake/Core/Models/TrayIconAction.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
// 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 Awake.Core.Models
|
||||
{
|
||||
internal enum TrayIconAction
|
||||
{
|
||||
Add,
|
||||
Update,
|
||||
Delete,
|
||||
}
|
||||
}
|
||||
26
src/modules/awake/Awake/Core/Models/WNDCLASSEX.cs
Normal file
26
src/modules/awake/Awake/Core/Models/WNDCLASSEX.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Awake.Core.Models
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
internal struct WndClassEx
|
||||
{
|
||||
public uint CbSize;
|
||||
public uint Style;
|
||||
public IntPtr LpfnWndProc;
|
||||
public int CbClsExtra;
|
||||
public int CbWndExtra;
|
||||
public IntPtr HInstance;
|
||||
public IntPtr HIcon;
|
||||
public IntPtr HCursor;
|
||||
public IntPtr HbrBackground;
|
||||
public string LpszMenuName;
|
||||
public string LpszClassName;
|
||||
public IntPtr HIconSm;
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,14 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Awake.Core.Models;
|
||||
|
||||
namespace Awake.Core.Native
|
||||
{
|
||||
internal sealed class Bridge
|
||||
{
|
||||
internal delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true)]
|
||||
internal delegate int WndProcDelegate(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("Powrprof.dll", SetLastError = true)]
|
||||
internal static extern bool GetPwrCapabilities(out SystemPowerCapabilities lpSystemPowerCapabilities);
|
||||
@@ -30,9 +30,6 @@ namespace Awake.Core.Native
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern uint GetCurrentThreadId();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
internal static extern IntPtr CreateFile(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string filename,
|
||||
@@ -50,25 +47,13 @@ namespace Awake.Core.Native
|
||||
internal static extern bool InsertMenu(IntPtr hMenu, uint uPosition, uint uFlags, uint uIDNewItem, string lpNewItem);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr hWndChildAfter, string? className, string? windowTitle);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
public static extern bool TrackPopupMenuEx(IntPtr hMenu, uint uFlags, int x, int y, IntPtr hWnd, IntPtr lptpm);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, nuint wParam, nint lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool DestroyMenu(IntPtr hMenu);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
@@ -76,5 +61,46 @@ namespace Awake.Core.Native
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern void PostQuitMessage(int nExitCode);
|
||||
|
||||
[DllImport("shell32.dll")]
|
||||
internal static extern bool Shell_NotifyIcon(int dwMessage, ref NotifyIconData pnid);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool TranslateMessage(ref Msg lpMsg);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern IntPtr DispatchMessage(ref Msg lpMsg);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr RegisterClassEx(ref WndClassEx lpwcx);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr CreateWindowEx(uint dwExStyle, string lpClassName, string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern int DefWindowProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool GetCursorPos(out Point lpPoint);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern bool ScreenToClient(IntPtr hWnd, ref Point lpPoint);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern bool GetMessage(out Msg lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool UpdateWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool SetMenuInfo(IntPtr hMenu, ref MenuInfo lpcmi);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
internal static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,26 +7,46 @@ namespace Awake.Core.Native
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Win32 API convention.")]
|
||||
internal sealed class Constants
|
||||
{
|
||||
internal const uint WM_COMMAND = 0x111;
|
||||
internal const uint WM_USER = 0x400;
|
||||
internal const uint WM_GETTEXT = 0x000D;
|
||||
// Window Messages
|
||||
internal const uint WM_COMMAND = 0x0111;
|
||||
internal const uint WM_USER = 0x0400U;
|
||||
internal const uint WM_CLOSE = 0x0010;
|
||||
internal const int WM_DESTROY = 0x0002;
|
||||
internal const int WM_LBUTTONDOWN = 0x0201;
|
||||
internal const int WM_RBUTTONDOWN = 0x0204;
|
||||
|
||||
// Popup menu constants.
|
||||
// Menu Flags
|
||||
internal const uint MF_BYPOSITION = 1024;
|
||||
internal const uint MF_STRING = 0;
|
||||
internal const uint MF_MENUBREAK = 0x00000040;
|
||||
internal const uint MF_SEPARATOR = 0x00000800;
|
||||
internal const uint MF_POPUP = 0x00000010;
|
||||
internal const uint MF_UNCHECKED = 0x00000000;
|
||||
internal const uint MF_CHECKED = 0x00000008;
|
||||
internal const uint MF_OWNERDRAW = 0x00000100;
|
||||
|
||||
internal const uint MF_ENABLED = 0x00000000;
|
||||
internal const uint MF_DISABLED = 0x00000002;
|
||||
|
||||
// Standard Handles
|
||||
internal const int STD_OUTPUT_HANDLE = -11;
|
||||
|
||||
// Generic Access Rights
|
||||
internal const uint GENERIC_WRITE = 0x40000000;
|
||||
internal const uint GENERIC_READ = 0x80000000;
|
||||
|
||||
// Notification Icons
|
||||
internal const int NIF_ICON = 0x00000002;
|
||||
internal const int NIF_MESSAGE = 0x00000001;
|
||||
internal const int NIF_TIP = 0x00000004;
|
||||
internal const int NIM_ADD = 0x00000000;
|
||||
internal const int NIM_DELETE = 0x00000002;
|
||||
internal const int NIM_MODIFY = 0x00000001;
|
||||
|
||||
// Track Popup Menu Flags
|
||||
internal const uint TPM_LEFT_ALIGN = 0x0000;
|
||||
internal const uint TPM_BOTTOMALIGN = 0x0020;
|
||||
internal const uint TPM_LEFT_BUTTON = 0x0000;
|
||||
|
||||
// Menu Item Info Flags
|
||||
internal const uint MNS_AUTO_DISMISS = 0x10000000;
|
||||
internal const uint MIM_STYLE = 0x00000010;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Awake.Core.Models;
|
||||
using Awake.Core.Native;
|
||||
using Awake.Properties;
|
||||
@@ -27,147 +27,384 @@ namespace Awake.Core
|
||||
/// </remarks>
|
||||
internal static class TrayHelper
|
||||
{
|
||||
private static NotifyIconData _notifyIconData;
|
||||
|
||||
private static IntPtr _trayMenu;
|
||||
|
||||
private static IntPtr TrayMenu { get => _trayMenu; set => _trayMenu = value; }
|
||||
|
||||
private static NotifyIcon TrayIcon { get; set; }
|
||||
private static IntPtr _hiddenWindowHandle;
|
||||
|
||||
internal static IntPtr HiddenWindowHandle { get => _hiddenWindowHandle; private set => _hiddenWindowHandle = value; }
|
||||
|
||||
static TrayHelper()
|
||||
{
|
||||
TrayIcon = new NotifyIcon();
|
||||
TrayMenu = IntPtr.Zero;
|
||||
HiddenWindowHandle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public static void InitializeTray(string text, Icon icon, ManualResetEvent? exitSignal, ContextMenuStrip? contextMenu = null)
|
||||
public static void InitializeTray(string text, Icon icon)
|
||||
{
|
||||
Task.Factory.StartNew(
|
||||
(tray) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInfo("Setting up the tray.");
|
||||
if (tray != null)
|
||||
{
|
||||
((NotifyIcon)tray).Text = text;
|
||||
((NotifyIcon)tray).Icon = icon;
|
||||
((NotifyIcon)tray).ContextMenuStrip = contextMenu;
|
||||
((NotifyIcon)tray).Visible = true;
|
||||
((NotifyIcon)tray).MouseClick += TrayClickHandler;
|
||||
Application.AddMessageFilter(new TrayMessageFilter(exitSignal));
|
||||
Application.Run();
|
||||
Logger.LogInfo("Tray setup complete.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"An error occurred initializing the tray. {ex.Message}");
|
||||
Logger.LogError($"{ex.StackTrace}");
|
||||
}
|
||||
},
|
||||
TrayIcon);
|
||||
CreateHiddenWindow(icon, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function used to construct the context menu in the tray natively.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We need to use the Windows API here instead of the common control exposed
|
||||
/// by NotifyIcon because the one that is built into the Windows Forms stack
|
||||
/// hasn't been updated in a while and is looking like Office XP. That introduces
|
||||
/// scalability and coloring changes on any OS past Windows XP.
|
||||
/// </remarks>
|
||||
/// <param name="sender">The sender that triggers the handler.</param>
|
||||
/// <param name="e">MouseEventArgs instance containing mouse click event information.</param>
|
||||
private static void TrayClickHandler(object? sender, MouseEventArgs e)
|
||||
private static void ShowContextMenu(IntPtr hWnd)
|
||||
{
|
||||
IntPtr windowHandle = Manager.GetHiddenWindow();
|
||||
|
||||
if (windowHandle != IntPtr.Zero)
|
||||
if (TrayMenu != IntPtr.Zero)
|
||||
{
|
||||
Bridge.SetForegroundWindow(windowHandle);
|
||||
Bridge.TrackPopupMenuEx(TrayMenu, 0, Cursor.Position.X, Cursor.Position.Y, windowHandle, IntPtr.Zero);
|
||||
Bridge.SetForegroundWindow(hWnd);
|
||||
|
||||
// Get the handle to the context menu associated with the tray icon
|
||||
IntPtr hMenu = TrayMenu;
|
||||
|
||||
// Get the current cursor position
|
||||
Bridge.GetCursorPos(out Models.Point cursorPos);
|
||||
|
||||
Bridge.ScreenToClient(hWnd, ref cursorPos);
|
||||
|
||||
MenuInfo menuInfo = new()
|
||||
{
|
||||
CbSize = (uint)Marshal.SizeOf(typeof(MenuInfo)),
|
||||
FMask = Native.Constants.MIM_STYLE,
|
||||
DwStyle = Native.Constants.MNS_AUTO_DISMISS,
|
||||
};
|
||||
Bridge.SetMenuInfo(hMenu, ref menuInfo);
|
||||
|
||||
// Display the context menu at the cursor position
|
||||
Bridge.TrackPopupMenuEx(
|
||||
hMenu,
|
||||
Native.Constants.TPM_LEFT_ALIGN | Native.Constants.TPM_BOTTOMALIGN | Native.Constants.TPM_LEFT_BUTTON,
|
||||
cursorPos.X,
|
||||
cursorPos.Y,
|
||||
hWnd,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tray menu was not initialized. Log the issue.
|
||||
// This is normal when operating in "standalone mode" - that is, detached
|
||||
// from the PowerToys configuration file.
|
||||
Logger.LogError("Tried to create a context menu while the TrayMenu object is a null pointer. Normal when used in standalone mode.");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetTray(string text, AwakeSettings settings, bool startedFromPowerToys)
|
||||
private static void CreateHiddenWindow(Icon icon, string text)
|
||||
{
|
||||
IntPtr hWnd = IntPtr.Zero;
|
||||
|
||||
// Start the message loop asynchronously
|
||||
Task.Run(() =>
|
||||
{
|
||||
RunOnMainThread(() =>
|
||||
{
|
||||
WndClassEx wcex = new()
|
||||
{
|
||||
CbSize = (uint)Marshal.SizeOf(typeof(WndClassEx)),
|
||||
Style = 0,
|
||||
LpfnWndProc = Marshal.GetFunctionPointerForDelegate<Bridge.WndProcDelegate>(WndProc),
|
||||
CbClsExtra = 0,
|
||||
CbWndExtra = 0,
|
||||
HInstance = Marshal.GetHINSTANCE(typeof(Program).Module),
|
||||
HIcon = IntPtr.Zero,
|
||||
HCursor = IntPtr.Zero,
|
||||
HbrBackground = IntPtr.Zero,
|
||||
LpszMenuName = string.Empty,
|
||||
LpszClassName = Constants.TrayWindowId,
|
||||
HIconSm = IntPtr.Zero,
|
||||
};
|
||||
|
||||
Bridge.RegisterClassEx(ref wcex);
|
||||
|
||||
hWnd = Bridge.CreateWindowEx(
|
||||
0,
|
||||
Constants.TrayWindowId,
|
||||
text,
|
||||
0x00CF0000 | 0x00000001 | 0x00000008, // WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MINIMIZEBOX
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
unchecked(-3),
|
||||
IntPtr.Zero,
|
||||
Marshal.GetHINSTANCE(typeof(Program).Module),
|
||||
IntPtr.Zero);
|
||||
|
||||
if (hWnd == IntPtr.Zero)
|
||||
{
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
throw new Win32Exception(errorCode, "Failed to add tray icon. Error code: " + errorCode);
|
||||
}
|
||||
|
||||
// Keep this as a reference because we will need it when we update
|
||||
// the tray icon in the future.
|
||||
HiddenWindowHandle = hWnd;
|
||||
|
||||
Bridge.ShowWindow(hWnd, 0); // SW_HIDE
|
||||
Bridge.UpdateWindow(hWnd);
|
||||
|
||||
SetShellIcon(hWnd, text, icon);
|
||||
|
||||
RunMessageLoop();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
internal static void SetShellIcon(IntPtr hWnd, string text, Icon? icon, TrayIconAction action = TrayIconAction.Add)
|
||||
{
|
||||
int message = Native.Constants.NIM_ADD;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case TrayIconAction.Update:
|
||||
message = Native.Constants.NIM_MODIFY;
|
||||
break;
|
||||
case TrayIconAction.Delete:
|
||||
message = Native.Constants.NIM_DELETE;
|
||||
break;
|
||||
case TrayIconAction.Add:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (action == TrayIconAction.Add || action == TrayIconAction.Update)
|
||||
{
|
||||
_notifyIconData = new NotifyIconData
|
||||
{
|
||||
CbSize = Marshal.SizeOf(typeof(NotifyIconData)),
|
||||
HWnd = hWnd,
|
||||
UId = 1000,
|
||||
UFlags = Native.Constants.NIF_ICON | Native.Constants.NIF_TIP | Native.Constants.NIF_MESSAGE,
|
||||
UCallbackMessage = (int)Native.Constants.WM_USER,
|
||||
HIcon = icon?.Handle ?? IntPtr.Zero,
|
||||
SzTip = text,
|
||||
};
|
||||
}
|
||||
else if (action == TrayIconAction.Delete)
|
||||
{
|
||||
_notifyIconData = new NotifyIconData
|
||||
{
|
||||
CbSize = Marshal.SizeOf(typeof(NotifyIconData)),
|
||||
HWnd = hWnd,
|
||||
UId = 1000,
|
||||
UFlags = 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (!Bridge.Shell_NotifyIcon(message, ref _notifyIconData))
|
||||
{
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
throw new Win32Exception(errorCode, $"Failed to change tray icon. Action: {action} and error code: {errorCode}");
|
||||
}
|
||||
|
||||
if (action == TrayIconAction.Delete)
|
||||
{
|
||||
_notifyIconData = default;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunMessageLoop()
|
||||
{
|
||||
while (Bridge.GetMessage(out Msg msg, IntPtr.Zero, 0, 0))
|
||||
{
|
||||
Bridge.TranslateMessage(ref msg);
|
||||
Bridge.DispatchMessage(ref msg);
|
||||
}
|
||||
}
|
||||
|
||||
private static int WndProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case Native.Constants.WM_USER:
|
||||
if (lParam == (IntPtr)Native.Constants.WM_LBUTTONDOWN || lParam == (IntPtr)Native.Constants.WM_RBUTTONDOWN)
|
||||
{
|
||||
// Show the context menu associated with the tray icon
|
||||
ShowContextMenu(hWnd);
|
||||
}
|
||||
|
||||
break;
|
||||
case Native.Constants.WM_DESTROY:
|
||||
// Clean up resources when the window is destroyed
|
||||
Bridge.PostQuitMessage(0);
|
||||
break;
|
||||
case Native.Constants.WM_COMMAND:
|
||||
int trayCommandsSize = Enum.GetNames(typeof(TrayCommands)).Length;
|
||||
|
||||
long targetCommandIndex = wParam.ToInt64() & 0xFFFF;
|
||||
|
||||
switch (targetCommandIndex)
|
||||
{
|
||||
case (uint)TrayCommands.TC_EXIT:
|
||||
{
|
||||
Manager.CompleteExit(Environment.ExitCode);
|
||||
break;
|
||||
}
|
||||
|
||||
case (uint)TrayCommands.TC_DISPLAY_SETTING:
|
||||
{
|
||||
Manager.SetDisplay();
|
||||
break;
|
||||
}
|
||||
|
||||
case (uint)TrayCommands.TC_MODE_INDEFINITE:
|
||||
{
|
||||
AwakeSettings settings = Manager.ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName);
|
||||
Manager.SetIndefiniteKeepAwake(keepDisplayOn: settings.Properties.KeepDisplayOn);
|
||||
break;
|
||||
}
|
||||
|
||||
case (uint)TrayCommands.TC_MODE_PASSIVE:
|
||||
{
|
||||
Manager.SetPassiveKeepAwake();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (targetCommandIndex >= trayCommandsSize)
|
||||
{
|
||||
AwakeSettings settings = Manager.ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName);
|
||||
if (settings.Properties.CustomTrayTimes.Count == 0)
|
||||
{
|
||||
settings.Properties.CustomTrayTimes.AddRange(Manager.GetDefaultTrayOptions());
|
||||
}
|
||||
|
||||
int index = (int)targetCommandIndex - (int)TrayCommands.TC_TIME;
|
||||
uint targetTime = (uint)settings.Properties.CustomTrayTimes.ElementAt(index).Value;
|
||||
Manager.SetTimedKeepAwake(targetTime, keepDisplayOn: settings.Properties.KeepDisplayOn);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// Let the default window procedure handle other messages
|
||||
return Bridge.DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return Bridge.DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
internal static void RunOnMainThread(Action action)
|
||||
{
|
||||
var syncContext = new SingleThreadSynchronizationContext();
|
||||
SynchronizationContext.SetSynchronizationContext(syncContext);
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
syncContext.Post(
|
||||
_ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Error: " + e.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
syncContext.EndMessageLoop();
|
||||
}
|
||||
},
|
||||
null);
|
||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
|
||||
syncContext.BeginMessageLoop();
|
||||
}
|
||||
|
||||
internal static void SetTray(AwakeSettings settings, bool startedFromPowerToys)
|
||||
{
|
||||
SetTray(
|
||||
text,
|
||||
settings.Properties.KeepDisplayOn,
|
||||
settings.Properties.Mode,
|
||||
settings.Properties.CustomTrayTimes,
|
||||
startedFromPowerToys);
|
||||
}
|
||||
|
||||
public static void SetTray(string text, bool keepDisplayOn, AwakeMode mode, Dictionary<string, int> trayTimeShortcuts, bool startedFromPowerToys)
|
||||
public static void SetTray(bool keepDisplayOn, AwakeMode mode, Dictionary<string, int> trayTimeShortcuts, bool startedFromPowerToys)
|
||||
{
|
||||
if (TrayMenu != IntPtr.Zero)
|
||||
{
|
||||
var destructionStatus = Bridge.DestroyMenu(TrayMenu);
|
||||
if (destructionStatus != true)
|
||||
{
|
||||
Logger.LogError("Failed to destroy menu.");
|
||||
}
|
||||
}
|
||||
ClearExistingTrayMenu();
|
||||
CreateNewTrayMenu(startedFromPowerToys, keepDisplayOn, mode);
|
||||
|
||||
InsertAwakeModeMenuItems(mode);
|
||||
|
||||
EnsureDefaultTrayTimeShortcuts(trayTimeShortcuts);
|
||||
CreateAwakeTimeSubMenu(trayTimeShortcuts, mode == AwakeMode.TIMED);
|
||||
}
|
||||
|
||||
private static void ClearExistingTrayMenu()
|
||||
{
|
||||
if (TrayMenu != IntPtr.Zero && !Bridge.DestroyMenu(TrayMenu))
|
||||
{
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
Logger.LogError($"Failed to destroy menu: {errorCode}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateNewTrayMenu(bool startedFromPowerToys, bool keepDisplayOn, AwakeMode mode)
|
||||
{
|
||||
TrayMenu = Bridge.CreatePopupMenu();
|
||||
|
||||
if (TrayMenu != IntPtr.Zero)
|
||||
if (TrayMenu == IntPtr.Zero)
|
||||
{
|
||||
if (!startedFromPowerToys)
|
||||
{
|
||||
// If Awake is started from PowerToys, the correct way to exit it is disabling it from Settings.
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING, (uint)TrayCommands.TC_EXIT, Resources.AWAKE_EXIT);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_SEPARATOR, 0, string.Empty);
|
||||
}
|
||||
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (keepDisplayOn ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED) | (mode == AwakeMode.PASSIVE ? Native.Constants.MF_DISABLED : Native.Constants.MF_ENABLED), (uint)TrayCommands.TC_DISPLAY_SETTING, Resources.AWAKE_KEEP_SCREEN_ON);
|
||||
return;
|
||||
}
|
||||
|
||||
// In case there are no tray shortcuts defined for the application default to a
|
||||
// reasonable initial set.
|
||||
if (!startedFromPowerToys)
|
||||
{
|
||||
InsertMenuItem(0, TrayCommands.TC_EXIT, Resources.AWAKE_EXIT);
|
||||
}
|
||||
|
||||
InsertMenuItem(0, TrayCommands.TC_DISPLAY_SETTING, Resources.AWAKE_KEEP_SCREEN_ON, keepDisplayOn, mode == AwakeMode.PASSIVE);
|
||||
|
||||
if (!startedFromPowerToys)
|
||||
{
|
||||
InsertSeparator(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InsertMenuItem(int position, TrayCommands command, string text, bool checkedState = false, bool disabled = false)
|
||||
{
|
||||
uint state = Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING;
|
||||
state |= checkedState ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED;
|
||||
state |= disabled ? Native.Constants.MF_DISABLED : Native.Constants.MF_ENABLED;
|
||||
|
||||
Bridge.InsertMenu(TrayMenu, (uint)position, state, (uint)command, text);
|
||||
}
|
||||
|
||||
private static void InsertSeparator(int position)
|
||||
{
|
||||
Bridge.InsertMenu(TrayMenu, (uint)position, Native.Constants.MF_BYPOSITION | Native.Constants.MF_SEPARATOR, 0, string.Empty);
|
||||
}
|
||||
|
||||
private static void EnsureDefaultTrayTimeShortcuts(Dictionary<string, int> trayTimeShortcuts)
|
||||
{
|
||||
if (trayTimeShortcuts.Count == 0)
|
||||
{
|
||||
trayTimeShortcuts.AddRange(Manager.GetDefaultTrayOptions());
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateAwakeTimeSubMenu(Dictionary<string, int> trayTimeShortcuts, bool isChecked = false)
|
||||
{
|
||||
var awakeTimeMenu = Bridge.CreatePopupMenu();
|
||||
for (int i = 0; i < trayTimeShortcuts.Count; i++)
|
||||
{
|
||||
Bridge.InsertMenu(awakeTimeMenu, (uint)i, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING, (uint)TrayCommands.TC_TIME + (uint)i, trayTimeShortcuts.ElementAt(i).Key);
|
||||
}
|
||||
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_SEPARATOR, 0, string.Empty);
|
||||
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (mode == AwakeMode.PASSIVE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_PASSIVE, Resources.AWAKE_OFF);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (mode == AwakeMode.INDEFINITE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_INDEFINITE, Resources.AWAKE_KEEP_INDEFINITELY);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_POPUP | (mode == AwakeMode.TIMED ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)awakeTimeMenu, Resources.AWAKE_KEEP_ON_INTERVAL);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | Native.Constants.MF_DISABLED | (mode == AwakeMode.EXPIRABLE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_EXPIRABLE, Resources.AWAKE_KEEP_UNTIL_EXPIRATION);
|
||||
|
||||
TrayIcon.Text = text;
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_POPUP | (isChecked == true ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)awakeTimeMenu, Resources.AWAKE_KEEP_ON_INTERVAL);
|
||||
}
|
||||
|
||||
private sealed class CheckButtonToolStripMenuItemAccessibleObject : ToolStripItem.ToolStripItemAccessibleObject
|
||||
private static void InsertAwakeModeMenuItems(AwakeMode mode)
|
||||
{
|
||||
private readonly CheckButtonToolStripMenuItem _menuItem;
|
||||
InsertSeparator(0);
|
||||
|
||||
public CheckButtonToolStripMenuItemAccessibleObject(CheckButtonToolStripMenuItem menuItem)
|
||||
: base(menuItem)
|
||||
{
|
||||
_menuItem = menuItem;
|
||||
}
|
||||
|
||||
public override AccessibleRole Role => AccessibleRole.CheckButton;
|
||||
|
||||
public override string Name => _menuItem.Text + ", " + Role + ", " + (_menuItem.Checked ? Resources.AWAKE_CHECKED : Resources.AWAKE_UNCHECKED);
|
||||
}
|
||||
|
||||
private sealed class CheckButtonToolStripMenuItem : ToolStripMenuItem
|
||||
{
|
||||
protected override AccessibleObject CreateAccessibilityInstance()
|
||||
{
|
||||
return new CheckButtonToolStripMenuItemAccessibleObject(this);
|
||||
}
|
||||
InsertMenuItem(0, TrayCommands.TC_MODE_PASSIVE, Resources.AWAKE_OFF, mode == AwakeMode.PASSIVE);
|
||||
InsertMenuItem(0, TrayCommands.TC_MODE_INDEFINITE, Resources.AWAKE_KEEP_INDEFINITELY, mode == AwakeMode.INDEFINITE);
|
||||
InsertMenuItem(0, TrayCommands.TC_MODE_EXPIRABLE, Resources.AWAKE_KEEP_UNTIL_EXPIRATION, mode == AwakeMode.EXPIRABLE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,172 +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.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Awake.Core.Models;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace Awake.Core
|
||||
{
|
||||
public class TrayMessageFilter : IMessageFilter
|
||||
{
|
||||
private static SettingsUtils? _moduleSettings;
|
||||
|
||||
private static SettingsUtils? ModuleSettings { get => _moduleSettings; set => _moduleSettings = value; }
|
||||
|
||||
private static ManualResetEvent? _exitSignal;
|
||||
|
||||
public TrayMessageFilter(ManualResetEvent? exitSignal)
|
||||
{
|
||||
_exitSignal = exitSignal;
|
||||
ModuleSettings = new SettingsUtils();
|
||||
}
|
||||
|
||||
public bool PreFilterMessage(ref Message m)
|
||||
{
|
||||
var trayCommandsSize = Enum.GetNames(typeof(TrayCommands)).Length;
|
||||
|
||||
switch (m.Msg)
|
||||
{
|
||||
case (int)Native.Constants.WM_COMMAND:
|
||||
var targetCommandIndex = m.WParam.ToInt64() & 0xFFFF;
|
||||
switch (targetCommandIndex)
|
||||
{
|
||||
case (long)TrayCommands.TC_EXIT:
|
||||
ExitCommandHandler(_exitSignal);
|
||||
break;
|
||||
case (long)TrayCommands.TC_DISPLAY_SETTING:
|
||||
DisplaySettingCommandHandler(Constants.AppName);
|
||||
break;
|
||||
case (long)TrayCommands.TC_MODE_INDEFINITE:
|
||||
IndefiniteKeepAwakeCommandHandler(Constants.AppName);
|
||||
break;
|
||||
case (long)TrayCommands.TC_MODE_PASSIVE:
|
||||
PassiveKeepAwakeCommandHandler(Constants.AppName);
|
||||
break;
|
||||
case var _ when targetCommandIndex >= trayCommandsSize:
|
||||
// Format for the timer block:
|
||||
// TrayCommands.TC_TIME + ZERO_BASED_INDEX_IN_SETTINGS
|
||||
AwakeSettings settings = ModuleSettings!.GetSettings<AwakeSettings>(Constants.AppName);
|
||||
if (settings.Properties.CustomTrayTimes.Count == 0)
|
||||
{
|
||||
settings.Properties.CustomTrayTimes.AddRange(Manager.GetDefaultTrayOptions());
|
||||
}
|
||||
|
||||
int index = (int)targetCommandIndex - (int)TrayCommands.TC_TIME;
|
||||
var targetTime = settings.Properties.CustomTrayTimes.ElementAt(index).Value;
|
||||
TimedKeepAwakeCommandHandler(Constants.AppName, targetTime);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ExitCommandHandler(ManualResetEvent? exitSignal)
|
||||
{
|
||||
Manager.CompleteExit(0, exitSignal, true);
|
||||
}
|
||||
|
||||
private static void DisplaySettingCommandHandler(string moduleName)
|
||||
{
|
||||
AwakeSettings currentSettings;
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(moduleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"Failed GetSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
currentSettings = new AwakeSettings();
|
||||
}
|
||||
|
||||
currentSettings.Properties.KeepDisplayOn = !currentSettings.Properties.KeepDisplayOn;
|
||||
|
||||
try
|
||||
{
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"Failed SaveSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TimedKeepAwakeCommandHandler(string moduleName, int seconds)
|
||||
{
|
||||
TimeSpan timeSpan = TimeSpan.FromSeconds(seconds);
|
||||
|
||||
AwakeSettings currentSettings;
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(moduleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"Failed GetSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
currentSettings = new AwakeSettings();
|
||||
}
|
||||
|
||||
currentSettings.Properties.Mode = AwakeMode.TIMED;
|
||||
currentSettings.Properties.IntervalHours = (uint)timeSpan.Hours;
|
||||
currentSettings.Properties.IntervalMinutes = (uint)timeSpan.Minutes;
|
||||
|
||||
try
|
||||
{
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"Failed SaveSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
}
|
||||
}
|
||||
|
||||
private static void PassiveKeepAwakeCommandHandler(string moduleName)
|
||||
{
|
||||
Manager.SetPassiveKeepAwakeMode(moduleName);
|
||||
}
|
||||
|
||||
private static void IndefiniteKeepAwakeCommandHandler(string moduleName)
|
||||
{
|
||||
AwakeSettings currentSettings;
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings!.GetSettings<AwakeSettings>(moduleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"Failed GetSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
currentSettings = new AwakeSettings();
|
||||
}
|
||||
|
||||
currentSettings.Properties.Mode = AwakeMode.INDEFINITE;
|
||||
|
||||
try
|
||||
{
|
||||
ModuleSettings!.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"Failed SaveSettings: {ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ using System.Threading.Tasks;
|
||||
using Awake.Core;
|
||||
using Awake.Core.Models;
|
||||
using Awake.Core.Native;
|
||||
using Awake.Properties;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
@@ -25,14 +26,6 @@ namespace Awake
|
||||
{
|
||||
internal sealed class Program
|
||||
{
|
||||
// PowerToys Awake build code name. Used for exact logging
|
||||
// that does not map to PowerToys broad version schema to pinpoint
|
||||
// internal issues easier.
|
||||
// Format of the build ID is: CODENAME_MMDDYYYY, where MMDDYYYY
|
||||
// is representative of the date when the last change was made before
|
||||
// the pull request is issued.
|
||||
private static readonly string BuildId = "ATRIOX_04132023";
|
||||
|
||||
private static Mutex? _mutex;
|
||||
private static FileSystemWatcher? _watcher;
|
||||
private static SettingsUtils? _settingsUtils;
|
||||
@@ -46,12 +39,13 @@ namespace Awake
|
||||
private static SystemPowerCapabilities _powerCapabilities;
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
|
||||
private static ManualResetEvent _exitSignal = new ManualResetEvent(false);
|
||||
internal static readonly string[] AliasesConfigOption = new[] { "--use-pt-config", "-c" };
|
||||
internal static readonly string[] AliasesDisplayOption = new[] { "--display-on", "-d" };
|
||||
internal static readonly string[] AliasesTimeOption = new[] { "--time-limit", "-t" };
|
||||
internal static readonly string[] AliasesPidOption = new[] { "--pid", "-p" };
|
||||
internal static readonly string[] AliasesExpireAtOption = new[] { "--expire-at", "-e" };
|
||||
internal static readonly string[] AliasesConfigOption = ["--use-pt-config", "-c"];
|
||||
internal static readonly string[] AliasesDisplayOption = ["--display-on", "-d"];
|
||||
internal static readonly string[] AliasesTimeOption = ["--time-limit", "-t"];
|
||||
internal static readonly string[] AliasesPidOption = ["--pid", "-p"];
|
||||
internal static readonly string[] AliasesExpireAtOption = ["--expire-at", "-e"];
|
||||
|
||||
private static readonly Icon _defaultAwakeIcon = new(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets/Awake/awake.ico"));
|
||||
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
@@ -60,20 +54,22 @@ namespace Awake
|
||||
|
||||
Logger.InitializeLogger(Path.Combine("\\", Core.Constants.AppName, "Logs"));
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += AwakeUnhandledExceptionCatcher;
|
||||
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredAwakeEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||
{
|
||||
Exit("PowerToys.Awake tried to start with a group policy setting that disables the tool. Please contact your system administrator.", 1, _exitSignal, true);
|
||||
Exit("PowerToys.Awake tried to start with a group policy setting that disables the tool. Please contact your system administrator.", 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!instantiated)
|
||||
{
|
||||
Exit(Core.Constants.AppName + " is already running! Exiting the application.", 1, _exitSignal, true);
|
||||
Exit(Core.Constants.AppName + " is already running! Exiting the application.", 1);
|
||||
}
|
||||
|
||||
Logger.LogInfo($"Launching {Core.Constants.AppName}...");
|
||||
Logger.LogInfo(FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion);
|
||||
Logger.LogInfo($"Build: {BuildId}");
|
||||
Logger.LogInfo($"Build: {Core.Constants.BuildId}");
|
||||
Logger.LogInfo($"OS: {Environment.OSVersion}");
|
||||
Logger.LogInfo($"OS Build: {Manager.GetOperatingSystemBuild()}");
|
||||
|
||||
@@ -90,85 +86,71 @@ namespace Awake
|
||||
|
||||
Logger.LogInfo("Parsing parameters...");
|
||||
|
||||
Option<bool> configOption = new(
|
||||
aliases: AliasesConfigOption,
|
||||
getDefaultValue: () => false,
|
||||
description: $"Specifies whether {Core.Constants.AppName} will be using the PowerToys configuration file for managing the state.")
|
||||
var configOption = new Option<bool>(AliasesConfigOption, () => false, Resources.AWAKE_CMD_HELP_CONFIG_OPTION)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
IsRequired = false,
|
||||
};
|
||||
|
||||
Option<bool> displayOption = new(
|
||||
aliases: AliasesDisplayOption,
|
||||
getDefaultValue: () => true,
|
||||
description: "Determines whether the display should be kept awake.")
|
||||
var displayOption = new Option<bool>(AliasesDisplayOption, () => true, Resources.AWAKE_CMD_HELP_DISPLAY_OPTION)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
IsRequired = false,
|
||||
};
|
||||
|
||||
Option<uint> timeOption = new(
|
||||
aliases: AliasesTimeOption,
|
||||
getDefaultValue: () => 0,
|
||||
description: "Determines the interval, in seconds, during which the computer is kept awake.")
|
||||
var timeOption = new Option<uint>(AliasesTimeOption, () => 0, Resources.AWAKE_CMD_HELP_TIME_OPTION)
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
IsRequired = false,
|
||||
};
|
||||
|
||||
Option<int> pidOption = new(
|
||||
aliases: AliasesPidOption,
|
||||
getDefaultValue: () => 0,
|
||||
description: $"Bind the execution of {Core.Constants.AppName} to another process. When the process ends, the system will resume managing the current sleep and display state.")
|
||||
var pidOption = new Option<int>(AliasesPidOption, () => 0, Resources.AWAKE_CMD_HELP_PID_OPTION)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
IsRequired = false,
|
||||
};
|
||||
|
||||
Option<string> expireAtOption = new(
|
||||
aliases: AliasesExpireAtOption,
|
||||
getDefaultValue: () => string.Empty,
|
||||
description: $"Determines the end date/time when {Core.Constants.AppName} will back off and let the system manage the current sleep and display state.")
|
||||
var expireAtOption = new Option<string>(AliasesExpireAtOption, () => string.Empty, Resources.AWAKE_CMD_HELP_EXPIRE_AT_OPTION)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
IsRequired = false,
|
||||
};
|
||||
|
||||
RootCommand? rootCommand = new()
|
||||
{
|
||||
RootCommand? rootCommand =
|
||||
[
|
||||
configOption,
|
||||
displayOption,
|
||||
timeOption,
|
||||
pidOption,
|
||||
expireAtOption,
|
||||
};
|
||||
];
|
||||
|
||||
rootCommand.Description = Core.Constants.AppName;
|
||||
|
||||
rootCommand.SetHandler(
|
||||
HandleCommandLineArguments,
|
||||
configOption,
|
||||
displayOption,
|
||||
timeOption,
|
||||
pidOption,
|
||||
expireAtOption);
|
||||
rootCommand.SetHandler(HandleCommandLineArguments, configOption, displayOption, timeOption, pidOption, expireAtOption);
|
||||
|
||||
return rootCommand.InvokeAsync(args).Result;
|
||||
}
|
||||
|
||||
private static void AwakeUnhandledExceptionCatcher(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
if (e.ExceptionObject is Exception exception)
|
||||
{
|
||||
Logger.LogError(exception.ToString());
|
||||
Logger.LogError(exception.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ExitHandler(ControlType ctrlType)
|
||||
{
|
||||
Logger.LogInfo($"Exited through handler with control type: {ctrlType}");
|
||||
Exit("Exiting from the internal termination handler.", Environment.ExitCode, _exitSignal);
|
||||
Exit(Resources.AWAKE_EXIT_MESSAGE, Environment.ExitCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void Exit(string message, int exitCode, ManualResetEvent exitSignal, bool force = false)
|
||||
private static void Exit(string message, int exitCode)
|
||||
{
|
||||
Logger.LogInfo(message);
|
||||
|
||||
Manager.CompleteExit(exitCode, exitSignal, force);
|
||||
Manager.CompleteExit(exitCode);
|
||||
}
|
||||
|
||||
private static void HandleCommandLineArguments(bool usePtConfig, bool displayOn, uint timeLimit, int pid, string expireAt)
|
||||
@@ -197,31 +179,32 @@ namespace Awake
|
||||
// Start the monitor thread that will be used to track the current state.
|
||||
Manager.StartMonitor();
|
||||
|
||||
TrayHelper.InitializeTray(Core.Constants.FullAppName, _defaultAwakeIcon);
|
||||
|
||||
var eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, interop.Constants.AwakeExitEvent());
|
||||
new Thread(() =>
|
||||
{
|
||||
WaitHandle.WaitAny([eventHandle]);
|
||||
Exit(Resources.AWAKE_EXIT_SIGNAL_MESSAGE, 0);
|
||||
}).Start();
|
||||
|
||||
if (usePtConfig)
|
||||
{
|
||||
// Configuration file is used, therefore we disregard any other command-line parameter
|
||||
// and instead watch for changes in the file.
|
||||
Manager.IsUsingPowerToysConfig = true;
|
||||
|
||||
try
|
||||
{
|
||||
var eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, interop.Constants.AwakeExitEvent());
|
||||
new Thread(() =>
|
||||
{
|
||||
if (WaitHandle.WaitAny(new WaitHandle[] { _exitSignal, eventHandle }) == 1)
|
||||
{
|
||||
Exit("Received a signal to end the process. Making sure we quit...", 0, _exitSignal, true);
|
||||
}
|
||||
}).Start();
|
||||
|
||||
TrayHelper.InitializeTray(Core.Constants.FullAppName, new Icon(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets/Awake/awake.ico")), _exitSignal);
|
||||
|
||||
string? settingsPath = _settingsUtils!.GetSettingsFilePath(Core.Constants.AppName);
|
||||
|
||||
Logger.LogInfo($"Reading configuration file: {settingsPath}");
|
||||
|
||||
if (!File.Exists(settingsPath))
|
||||
{
|
||||
string? errorString = $"The settings file does not exist. Scaffolding default configuration...";
|
||||
Logger.LogError("The settings file does not exist. Scaffolding default configuration...");
|
||||
|
||||
AwakeSettings scaffoldSettings = new AwakeSettings();
|
||||
AwakeSettings scaffoldSettings = new();
|
||||
_settingsUtils.SaveSettings(JsonSerializer.Serialize(scaffoldSettings), Core.Constants.AppName);
|
||||
}
|
||||
|
||||
@@ -229,8 +212,7 @@ namespace Awake
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorString = $"There was a problem with the configuration file. Make sure it exists.\n{ex.Message}";
|
||||
Logger.LogError(errorString);
|
||||
Logger.LogError($"There was a problem with the configuration file. Make sure it exists.\n{ex.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -241,24 +223,13 @@ namespace Awake
|
||||
{
|
||||
try
|
||||
{
|
||||
DateTime expirationDateTime = DateTime.Parse(expireAt, CultureInfo.CurrentCulture);
|
||||
if (expirationDateTime > DateTime.Now)
|
||||
{
|
||||
// We want to have a dedicated expirable keep-awake logic instead of
|
||||
// converting the target date to seconds and then passing to SetupTimedKeepAwake
|
||||
// because that way we're accounting for the user potentially changing their clock
|
||||
// while Awake is running.
|
||||
Logger.LogInfo($"Operating in thread ID {Environment.CurrentManagedThreadId}.");
|
||||
SetupExpirableKeepAwake(expirationDateTime, displayOn);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInfo($"Target date is not in the future, therefore there is nothing to wait for.");
|
||||
}
|
||||
DateTimeOffset expirationDateTime = DateTimeOffset.Parse(expireAt, CultureInfo.CurrentCulture);
|
||||
Logger.LogInfo($"Operating in thread ID {Environment.CurrentManagedThreadId}.");
|
||||
Manager.SetExpirableKeepAwake(expirationDateTime, displayOn);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Could not parse date string {expireAt} into a viable date.");
|
||||
Logger.LogError($"Could not parse date string {expireAt} into a DateTimeOffset object.");
|
||||
Logger.LogError(ex.Message);
|
||||
}
|
||||
}
|
||||
@@ -268,11 +239,11 @@ namespace Awake
|
||||
|
||||
if (mode == AwakeMode.INDEFINITE)
|
||||
{
|
||||
SetupIndefiniteKeepAwake(displayOn);
|
||||
Manager.SetIndefiniteKeepAwake(displayOn);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupTimedKeepAwake(timeLimit, displayOn);
|
||||
Manager.SetTimedKeepAwake(timeLimit, displayOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,44 +253,43 @@ namespace Awake
|
||||
RunnerHelper.WaitForPowerToysRunner(pid, () =>
|
||||
{
|
||||
Logger.LogInfo($"Triggered PID-based exit handler for PID {pid}.");
|
||||
Exit("Terminating from process binding hook.", 0, _exitSignal, true);
|
||||
Exit(Resources.AWAKE_EXIT_BINDING_HOOK_MESSAGE, 0);
|
||||
});
|
||||
}
|
||||
|
||||
_exitSignal.WaitOne();
|
||||
}
|
||||
|
||||
private static void ScaffoldConfiguration(string settingsPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var directory = Path.GetDirectoryName(settingsPath)!;
|
||||
var fileName = Path.GetFileName(settingsPath);
|
||||
|
||||
_watcher = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(settingsPath)!,
|
||||
Path = directory,
|
||||
EnableRaisingEvents = true,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime,
|
||||
Filter = Path.GetFileName(settingsPath),
|
||||
Filter = fileName,
|
||||
};
|
||||
|
||||
IObservable<System.Reactive.EventPattern<FileSystemEventArgs>>? changedObservable = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||
var mergedObservable = Observable.Merge(
|
||||
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||
h => _watcher.Changed += h,
|
||||
h => _watcher.Changed -= h);
|
||||
h => _watcher.Changed -= h),
|
||||
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||
h => _watcher.Created += h,
|
||||
h => _watcher.Created -= h));
|
||||
|
||||
IObservable<System.Reactive.EventPattern<FileSystemEventArgs>>? createdObservable = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||
cre => _watcher.Created += cre,
|
||||
cre => _watcher.Created -= cre);
|
||||
|
||||
IObservable<System.Reactive.EventPattern<FileSystemEventArgs>>? mergedObservable = Observable.Merge(changedObservable, createdObservable);
|
||||
|
||||
mergedObservable.Throttle(TimeSpan.FromMilliseconds(25))
|
||||
mergedObservable
|
||||
.Throttle(TimeSpan.FromMilliseconds(25))
|
||||
.SubscribeOn(TaskPoolScheduler.Default)
|
||||
.Select(e => e.EventArgs)
|
||||
.Subscribe(HandleAwakeConfigChange);
|
||||
|
||||
TrayHelper.SetTray(Core.Constants.FullAppName, new AwakeSettings(), _startedFromPowerToys);
|
||||
var settings = Manager.ModuleSettings!.GetSettings<AwakeSettings>(Core.Constants.AppName) ?? new AwakeSettings();
|
||||
TrayHelper.SetTray(settings, _startedFromPowerToys);
|
||||
|
||||
// Initially the file might not be updated, so we need to start processing
|
||||
// settings right away.
|
||||
ProcessSettings();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -328,99 +298,64 @@ namespace Awake
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetupIndefiniteKeepAwake(bool displayOn)
|
||||
{
|
||||
Manager.SetIndefiniteKeepAwake(displayOn);
|
||||
}
|
||||
|
||||
private static void HandleAwakeConfigChange(FileSystemEventArgs fileEvent)
|
||||
{
|
||||
Logger.LogInfo("Detected a settings file change. Updating configuration...");
|
||||
Logger.LogInfo("Resetting keep-awake to normal state due to settings change.");
|
||||
ProcessSettings();
|
||||
try
|
||||
{
|
||||
Logger.LogInfo("Detected a settings file change. Updating configuration...");
|
||||
ProcessSettings();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Could not handle Awake configuration change. Error: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
AwakeSettings settings = _settingsUtils!.GetSettings<AwakeSettings>(Core.Constants.AppName);
|
||||
var settings = _settingsUtils!.GetSettings<AwakeSettings>(Core.Constants.AppName) ?? throw new InvalidOperationException("Settings are null.");
|
||||
Logger.LogInfo($"Identified custom time shortcuts for the tray: {settings.Properties.CustomTrayTimes.Count}");
|
||||
|
||||
if (settings != null)
|
||||
switch (settings.Properties.Mode)
|
||||
{
|
||||
Logger.LogInfo($"Identified custom time shortcuts for the tray: {settings.Properties.CustomTrayTimes.Count}");
|
||||
case AwakeMode.PASSIVE:
|
||||
Manager.SetPassiveKeepAwake();
|
||||
break;
|
||||
|
||||
switch (settings.Properties.Mode)
|
||||
{
|
||||
case AwakeMode.PASSIVE:
|
||||
{
|
||||
SetupNoKeepAwake();
|
||||
break;
|
||||
}
|
||||
case AwakeMode.INDEFINITE:
|
||||
Manager.SetIndefiniteKeepAwake(settings.Properties.KeepDisplayOn);
|
||||
break;
|
||||
|
||||
case AwakeMode.INDEFINITE:
|
||||
{
|
||||
SetupIndefiniteKeepAwake(settings.Properties.KeepDisplayOn);
|
||||
break;
|
||||
}
|
||||
case AwakeMode.TIMED:
|
||||
uint computedTime = (settings.Properties.IntervalHours * 60 * 60) + (settings.Properties.IntervalMinutes * 60);
|
||||
Manager.SetTimedKeepAwake(computedTime, settings.Properties.KeepDisplayOn);
|
||||
break;
|
||||
|
||||
case AwakeMode.TIMED:
|
||||
{
|
||||
uint computedTime = (settings.Properties.IntervalHours * 60 * 60) + (settings.Properties.IntervalMinutes * 60);
|
||||
SetupTimedKeepAwake(computedTime, settings.Properties.KeepDisplayOn);
|
||||
case AwakeMode.EXPIRABLE:
|
||||
// When we are loading from the settings file, let's make sure that we never
|
||||
// get users in a state where the expirable keep-awake is in the past.
|
||||
if (settings.Properties.ExpirationDateTime <= DateTimeOffset.Now)
|
||||
{
|
||||
settings.Properties.ExpirationDateTime = DateTimeOffset.Now.AddMinutes(5);
|
||||
_settingsUtils.SaveSettings(JsonSerializer.Serialize(settings), Core.Constants.AppName);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
Manager.SetExpirableKeepAwake(settings.Properties.ExpirationDateTime, settings.Properties.KeepDisplayOn);
|
||||
break;
|
||||
|
||||
case AwakeMode.EXPIRABLE:
|
||||
{
|
||||
SetupExpirableKeepAwake(settings.Properties.ExpirationDateTime, settings.Properties.KeepDisplayOn);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
string? errorMessage = "Unknown mode of operation. Check config file.";
|
||||
Logger.LogError(errorMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TrayHelper.SetTray(Core.Constants.FullAppName, settings, _startedFromPowerToys);
|
||||
}
|
||||
else
|
||||
{
|
||||
string? errorMessage = "Settings are null.";
|
||||
Logger.LogError(errorMessage);
|
||||
default:
|
||||
Logger.LogError("Unknown mode of operation. Check config file.");
|
||||
break;
|
||||
}
|
||||
|
||||
TrayHelper.SetTray(settings, _startedFromPowerToys);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string? errorMessage = $"There was a problem reading the configuration file. Error: {ex.GetType()} {ex.Message}";
|
||||
Logger.LogError(errorMessage);
|
||||
Logger.LogError($"There was a problem reading the configuration file. Error: {ex.GetType()} {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetupNoKeepAwake()
|
||||
{
|
||||
Logger.LogInfo($"Operating in passive mode (computer's standard power plan). No custom keep awake settings enabled.");
|
||||
|
||||
Manager.SetNoKeepAwake();
|
||||
}
|
||||
|
||||
private static void SetupExpirableKeepAwake(DateTimeOffset expireAt, bool displayOn)
|
||||
{
|
||||
Logger.LogInfo($"Expirable keep-awake. Expected expiration date/time: {expireAt} with display on setting set to {displayOn}.");
|
||||
|
||||
Manager.SetExpirableKeepAwake(expireAt, displayOn);
|
||||
}
|
||||
|
||||
private static void SetupTimedKeepAwake(uint time, bool displayOn)
|
||||
{
|
||||
Logger.LogInfo($"Timed keep-awake. Expected runtime: {time} seconds with display on setting set to {displayOn}.");
|
||||
|
||||
Manager.SetTimedKeepAwake(time, displayOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
162
src/modules/awake/Awake/Properties/Resources.Designer.cs
generated
162
src/modules/awake/Awake/Properties/Resources.Designer.cs
generated
@@ -60,24 +60,6 @@ namespace Awake.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1 hour.
|
||||
/// </summary>
|
||||
internal static string AWAKE_1_HOUR {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_1_HOUR", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1 minute.
|
||||
/// </summary>
|
||||
internal static string AWAKE_1_MINUTE {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_1_MINUTE", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Checked.
|
||||
/// </summary>
|
||||
@@ -87,6 +69,51 @@ namespace Awake.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Specifies whether Awake will be using the PowerToys configuration file for managing the state..
|
||||
/// </summary>
|
||||
internal static string AWAKE_CMD_HELP_CONFIG_OPTION {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_CMD_HELP_CONFIG_OPTION", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Determines whether the display should be kept awake..
|
||||
/// </summary>
|
||||
internal static string AWAKE_CMD_HELP_DISPLAY_OPTION {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_CMD_HELP_DISPLAY_OPTION", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Determines the end date and time when Awake will back off and let the system manage the current sleep and display state..
|
||||
/// </summary>
|
||||
internal static string AWAKE_CMD_HELP_EXPIRE_AT_OPTION {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_CMD_HELP_EXPIRE_AT_OPTION", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bind the execution of Awake to another process. When the process ends, the system will resume managing the current sleep and display state..
|
||||
/// </summary>
|
||||
internal static string AWAKE_CMD_HELP_PID_OPTION {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_CMD_HELP_PID_OPTION", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Determines the interval (in seconds) during which the computer is kept awake..
|
||||
/// </summary>
|
||||
internal static string AWAKE_CMD_HELP_TIME_OPTION {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_CMD_HELP_TIME_OPTION", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Exit.
|
||||
/// </summary>
|
||||
@@ -96,6 +123,33 @@ namespace Awake.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Terminating from process binding hook..
|
||||
/// </summary>
|
||||
internal static string AWAKE_EXIT_BINDING_HOOK_MESSAGE {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_EXIT_BINDING_HOOK_MESSAGE", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Exiting from the internal termination handler..
|
||||
/// </summary>
|
||||
internal static string AWAKE_EXIT_MESSAGE {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_EXIT_MESSAGE", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Received a signal to end the process. Making sure we quit....
|
||||
/// </summary>
|
||||
internal static string AWAKE_EXIT_SIGNAL_MESSAGE {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_EXIT_SIGNAL_MESSAGE", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} hours.
|
||||
/// </summary>
|
||||
@@ -141,6 +195,42 @@ namespace Awake.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to d.
|
||||
/// </summary>
|
||||
internal static string AWAKE_LABEL_DAYS {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_LABEL_DAYS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to h.
|
||||
/// </summary>
|
||||
internal static string AWAKE_LABEL_HOURS {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_LABEL_HOURS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to m.
|
||||
/// </summary>
|
||||
internal static string AWAKE_LABEL_MINUTES {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_LABEL_MINUTES", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to s.
|
||||
/// </summary>
|
||||
internal static string AWAKE_LABEL_SECONDS {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_LABEL_SECONDS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} minutes.
|
||||
/// </summary>
|
||||
@@ -159,6 +249,42 @@ namespace Awake.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Expiring.
|
||||
/// </summary>
|
||||
internal static string AWAKE_TRAY_TEXT_EXPIRATION {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_TRAY_TEXT_EXPIRATION", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Indefinite.
|
||||
/// </summary>
|
||||
internal static string AWAKE_TRAY_TEXT_INDEFINITE {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_TRAY_TEXT_INDEFINITE", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Passive.
|
||||
/// </summary>
|
||||
internal static string AWAKE_TRAY_TEXT_OFF {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_TRAY_TEXT_OFF", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Interval.
|
||||
/// </summary>
|
||||
internal static string AWAKE_TRAY_TEXT_TIMED {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_TRAY_TEXT_TIMED", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unchecked.
|
||||
/// </summary>
|
||||
|
||||
@@ -123,9 +123,6 @@
|
||||
<data name="AWAKE_EXIT" xml:space="preserve">
|
||||
<value>Exit</value>
|
||||
</data>
|
||||
<data name="AWAKE_1_HOUR" xml:space="preserve">
|
||||
<value>1 hour</value>
|
||||
</data>
|
||||
<data name="AWAKE_HOURS" xml:space="preserve">
|
||||
<value>{0} hours</value>
|
||||
<comment>{0} shouldn't be removed. It will be replaced by a number greater than 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>
|
||||
@@ -145,9 +142,6 @@
|
||||
<value>Keep awake until expiration date and time</value>
|
||||
<comment>Keep the system awake until expiration date and time</comment>
|
||||
</data>
|
||||
<data name="AWAKE_1_MINUTE" xml:space="preserve">
|
||||
<value>1 minute</value>
|
||||
</data>
|
||||
<data name="AWAKE_MINUTES" xml:space="preserve">
|
||||
<value>{0} minutes</value>
|
||||
<comment>{0} shouldn't be removed. It will be replaced by a number greater than 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>
|
||||
@@ -159,4 +153,56 @@
|
||||
<data name="AWAKE_UNCHECKED" xml:space="preserve">
|
||||
<value>Unchecked</value>
|
||||
</data>
|
||||
<data name="AWAKE_CMD_HELP_CONFIG_OPTION" xml:space="preserve">
|
||||
<value>Specifies whether Awake will be using the PowerToys configuration file for managing the state.</value>
|
||||
</data>
|
||||
<data name="AWAKE_CMD_HELP_DISPLAY_OPTION" xml:space="preserve">
|
||||
<value>Determines whether the display should be kept awake.</value>
|
||||
</data>
|
||||
<data name="AWAKE_CMD_HELP_EXPIRE_AT_OPTION" xml:space="preserve">
|
||||
<value>Determines the end date and time when Awake will back off and let the system manage the current sleep and display state.</value>
|
||||
</data>
|
||||
<data name="AWAKE_CMD_HELP_PID_OPTION" xml:space="preserve">
|
||||
<value>Bind the execution of Awake to another process. When the process ends, the system will resume managing the current sleep and display state.</value>
|
||||
</data>
|
||||
<data name="AWAKE_CMD_HELP_TIME_OPTION" xml:space="preserve">
|
||||
<value>Determines the interval (in seconds) during which the computer is kept awake.</value>
|
||||
</data>
|
||||
<data name="AWAKE_EXIT_BINDING_HOOK_MESSAGE" xml:space="preserve">
|
||||
<value>Terminating from process binding hook.</value>
|
||||
</data>
|
||||
<data name="AWAKE_EXIT_MESSAGE" xml:space="preserve">
|
||||
<value>Exiting from the internal termination handler.</value>
|
||||
</data>
|
||||
<data name="AWAKE_EXIT_SIGNAL_MESSAGE" xml:space="preserve">
|
||||
<value>Received a signal to end the process. Making sure we quit...</value>
|
||||
</data>
|
||||
<data name="AWAKE_TRAY_TEXT_EXPIRATION" xml:space="preserve">
|
||||
<value>Expiring</value>
|
||||
</data>
|
||||
<data name="AWAKE_TRAY_TEXT_INDEFINITE" xml:space="preserve">
|
||||
<value>Indefinite</value>
|
||||
</data>
|
||||
<data name="AWAKE_TRAY_TEXT_OFF" xml:space="preserve">
|
||||
<value>Passive</value>
|
||||
</data>
|
||||
<data name="AWAKE_TRAY_TEXT_TIMED" xml:space="preserve">
|
||||
<value>Interval</value>
|
||||
</data>
|
||||
<data name="AWAKE_LABEL_DAYS" xml:space="preserve">
|
||||
<value>d</value>
|
||||
<comment>Used to display number of days in the system tray tooltip.</comment>
|
||||
</data>
|
||||
<data name="AWAKE_LABEL_HOURS" xml:space="preserve">
|
||||
<value>h</value>
|
||||
<comment>Used to display number of hours in the system tray tooltip.</comment>
|
||||
</data>
|
||||
<data name="AWAKE_LABEL_MINUTES" xml:space="preserve">
|
||||
<value>m</value>
|
||||
<comment>Used to display number of minutes in the system tray tooltip.</comment>
|
||||
</data>
|
||||
<data name="AWAKE_LABEL_SECONDS" xml:space="preserve">
|
||||
<value>s</value>
|
||||
<comment>Used to display number of seconds in the system tray tooltip.</comment>
|
||||
</data>
|
||||
</root>
|
||||
8
src/modules/awake/Awake/app.manifest
Normal file
8
src/modules/awake/Awake/app.manifest
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<asmv3:application>
|
||||
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
|
||||
<dpiAware>true</dpiAware>
|
||||
</asmv3:windowsSettings>
|
||||
</asmv3:application>
|
||||
</assembly>
|
||||
@@ -48,6 +48,7 @@
|
||||
AutomationProperties.Name="{x:Static p:Resources.Color_History}"
|
||||
ItemsSource="{Binding ColorsHistory}"
|
||||
KeyboardNavigation.DirectionalNavigation="Contained"
|
||||
MouseWheel="HistoryColors_OnMouseWheelScroll"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
SelectedIndex="{Binding SelectedColorIndex}"
|
||||
SelectionMode="Extended"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using ColorPicker.Helpers;
|
||||
using ColorPicker.ViewModels;
|
||||
|
||||
@@ -42,6 +43,60 @@ namespace ColorPicker.Views
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse wheel scroll event on the HistoryColors ListView.
|
||||
/// Scrolls the ListView horizontally based on the direction of the mouse wheel scroll.
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the event.</param>
|
||||
/// <param name="e">The mouse wheel event data.</param>
|
||||
private void HistoryColors_OnMouseWheelScroll(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
||||
{
|
||||
var scrollViewer = FindVisualChild<ScrollViewer>(HistoryColors);
|
||||
|
||||
if (scrollViewer != null)
|
||||
{
|
||||
if (e.Delta > 0)
|
||||
{
|
||||
scrollViewer.LineLeft();
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollViewer.LineRight();
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a visual child of a specified type within a given dependency object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the child element to find.</typeparam>
|
||||
/// <param name="obj">The parent dependency object.</param>
|
||||
/// <returns>The first child element of the specified type, or null if no such element is found.</returns>
|
||||
private static T FindVisualChild<T>(DependencyObject obj)
|
||||
where T : DependencyObject
|
||||
{
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||||
if (child != null && child is T tChild)
|
||||
{
|
||||
return tChild;
|
||||
}
|
||||
else
|
||||
{
|
||||
T childOfChild = FindVisualChild<T>(child);
|
||||
if (childOfChild != null)
|
||||
{
|
||||
return childOfChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
private void HistoryColors_ItemClick(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="Microsoft.Win32.SystemEvents">
|
||||
<!-- This package is a dependency of System.Drawing.Common, but we need to set it here so we can exclude the assets, so it doesn't conflict with the 8.0.1 dll coming from .NET SDK. -->
|
||||
<ExcludeAssets>runtime</ExcludeAssets> <!-- Should already be present on .net sdk runtime, so we avoid the conflicting runtime version from nuget -->
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Appium.WebDriver" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Appium.WebDriver" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="System.IO.Abstractions.TestingHelpers" />
|
||||
<PackageReference Include="System.CodeDom">
|
||||
|
||||
@@ -99,7 +99,30 @@ MakeAppx.exe pack /d . /p $(OutDir)ImageResizerContextMenuPackage.msix /nv</Comm
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Assets\ImageResizer\**" CopyToOutputDirectory="PreserveNewest" />
|
||||
<None Include="Assets\ImageResizer\ImageResizer.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\ImageResizer\LargeTile.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\ImageResizer\SmallTile.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\ImageResizer\SplashScreen.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\ImageResizer\Square150x150Logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\ImageResizer\Square44x44Logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\ImageResizer\storelogo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Assets\ImageResizer\Wide310x150Logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{18b3db45-4ffe-4d01-97d6-5223feee1853}</ProjectGuid>
|
||||
@@ -30,7 +31,7 @@
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup >
|
||||
<PropertyGroup>
|
||||
<TargetName>PowerToys.$(ProjectName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
@@ -75,6 +76,18 @@
|
||||
<ClCompile Include="Settings.cpp" />
|
||||
<ClCompile Include="trace.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -42,4 +42,7 @@
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
4
src/modules/imageresizer/ImageResizerLib/packages.config
Normal file
4
src/modules/imageresizer/ImageResizerLib/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -51,10 +51,8 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="System.CodeDom">
|
||||
<!-- This package is a dependency of System.Management, but we need to set it here so we can exclude the assets, so it doesn't conflict with the 8.0.1 dll coming from .NET SDK. -->
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\;..\..\..\;..\..\..\common\telemetry;..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>%(AdditionalOptions) /Zm200</AdditionalOptions>
|
||||
<AdditionalOptions>%(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -179,6 +179,22 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts spelling "kph" to "km/h"
|
||||
/// </summary>
|
||||
public static void KPHHandler(ref string[] split)
|
||||
{
|
||||
split[1] = split[1].Replace("cph", "cm/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
split[1] = split[1].Replace("kph", "km/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
split[1] = split[1].Replace("kmph", "km/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
split[1] = split[1].Replace("cmph", "cm/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
|
||||
split[3] = split[3].Replace("cph", "cm/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
split[3] = split[3].Replace("kph", "km/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
split[3] = split[3].Replace("kmph", "km/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
split[3] = split[3].Replace("cmph", "cm/h", System.StringComparison.CurrentCultureIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts spelling "metre" to "meter", also for centimetre and other variants
|
||||
/// </summary>
|
||||
@@ -239,6 +255,7 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter
|
||||
InputInterpreter.DegreePrefixer(ref split);
|
||||
InputInterpreter.MetreToMeter(ref split);
|
||||
InputInterpreter.FeetToFt(ref split);
|
||||
InputInterpreter.KPHHandler(ref split);
|
||||
InputInterpreter.GallonHandler(ref split, CultureInfo.CurrentCulture);
|
||||
if (!double.TryParse(split[0], out double value))
|
||||
{
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// 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 Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
{
|
||||
internal sealed class GeneratorData
|
||||
{
|
||||
public string Keyword { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public string Example { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Community.PowerToys.Run.Plugin.ValueGenerator.Properties;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.ValueGenerator.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to easier work with queries
|
||||
/// </summary>
|
||||
internal static class QueryHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// a list of all value generator descriptions
|
||||
/// </summary>
|
||||
private static readonly string GeneratorDescriptionUuid = Resources.generator_description_uuid;
|
||||
private static readonly string GeneratorDescriptionUuidv1 = Resources.generator_description_uuidv1;
|
||||
private static readonly string GeneratorDescriptionUuidv3 = Resources.generator_description_uuidv3;
|
||||
private static readonly string GeneratorDescriptionUuidv4 = Resources.generator_description_uuidv4;
|
||||
private static readonly string GeneratorDescriptionUuidv5 = Resources.generator_description_uuidv5;
|
||||
private static readonly string GeneratorDescriptionHash = Resources.generator_description_hash;
|
||||
private static readonly string GeneratorDescriptionBase64 = Resources.generator_description_base64;
|
||||
private static readonly string GeneratorDescriptionBase64d = Resources.generator_description_base64d;
|
||||
private static readonly string GeneratorDescriptionUrl = Resources.generator_description_url;
|
||||
private static readonly string GeneratorDescriptionUrld = Resources.generator_description_urld;
|
||||
private static readonly string GeneratorDescriptionEscData = Resources.generator_description_esc_data;
|
||||
private static readonly string GeneratorDescriptionUescData = Resources.generator_description_uesc_data;
|
||||
private static readonly string GeneratorDescriptionEscHex = Resources.generator_description_esc_hex;
|
||||
private static readonly string GeneratorDescriptionUescHex = Resources.generator_description_uesc_hex;
|
||||
private static readonly string GeneratorDescriptionYourInput = Resources.generator_description_your_input;
|
||||
private static readonly string GeneratorExample = Resources.generator_example;
|
||||
private static readonly string Or = Resources.or;
|
||||
|
||||
private static string GetStringFormat(string value, string arg)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, value, arg);
|
||||
}
|
||||
|
||||
private static string GetStringFormat(string value)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, value);
|
||||
}
|
||||
|
||||
internal static string GetResultTitle(GeneratorData generatorData)
|
||||
{
|
||||
return $"{generatorData.Keyword} - {generatorData.Description}";
|
||||
}
|
||||
|
||||
internal static string GetResultSubtitle(GeneratorData generatorData)
|
||||
{
|
||||
return GetStringFormat(GeneratorExample, generatorData.Example);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list that contain all of the value generators and its descriptions
|
||||
/// </summary>
|
||||
internal static readonly List<GeneratorData> GeneratorDataList =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Keyword = "uuid",
|
||||
Description = GetStringFormat(GeneratorDescriptionUuid),
|
||||
Example = $"uuid {GetStringFormat(Or)} guid",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "uuidv1",
|
||||
Description = GetStringFormat(GeneratorDescriptionUuidv1),
|
||||
Example = $"uuidv1 {GetStringFormat(Or)} uuid1",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "uuidv3",
|
||||
Description = GetStringFormat(GeneratorDescriptionUuidv3),
|
||||
Example = $"uuidv3 ns:<DNS, URL, OID, {GetStringFormat(Or)} X500> <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "uuidv4",
|
||||
Description = GetStringFormat(GeneratorDescriptionUuidv4),
|
||||
Example = $"uuidv4 {GetStringFormat(Or)} uuid4",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "uuidv5",
|
||||
Description = GetStringFormat(GeneratorDescriptionUuidv5),
|
||||
Example = $"uuidv5 ns:<DNS, URL, OID, {GetStringFormat(Or)} X500> <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "md5",
|
||||
Description = GetStringFormat(GeneratorDescriptionHash, "MD5"),
|
||||
Example = $"md5 <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "sha1",
|
||||
Description = GetStringFormat(GeneratorDescriptionHash, "SHA1"),
|
||||
Example = $"sha1 <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "sha256",
|
||||
Description = GetStringFormat(GeneratorDescriptionHash, "SHA256"),
|
||||
Example = $"sha256 <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "sha384",
|
||||
Description = GetStringFormat(GeneratorDescriptionHash, "SHA384"),
|
||||
Example = $"sha384 <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "sha512",
|
||||
Description = GetStringFormat(GeneratorDescriptionHash, "SHA512"),
|
||||
Example = $"sha512 <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "base64",
|
||||
Description = GetStringFormat(GeneratorDescriptionBase64),
|
||||
Example = $"base64 <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "base64d",
|
||||
Description = GetStringFormat(GeneratorDescriptionBase64d),
|
||||
Example = $"base64d <{GetStringFormat(GeneratorDescriptionYourInput)}>",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "url",
|
||||
Description = GetStringFormat(GeneratorDescriptionUrl),
|
||||
Example = "url https://bing.com/?q=My Test query",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "urld",
|
||||
Description = GetStringFormat(GeneratorDescriptionUrld),
|
||||
Example = "urld https://bing.com/?q=My+Test+query",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "esc:data",
|
||||
Description = GetStringFormat(GeneratorDescriptionEscData),
|
||||
Example = "esc:data C:\\Program Files\\PowerToys\\PowerToys.exe",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "uesc:data",
|
||||
Description = GetStringFormat(GeneratorDescriptionUescData),
|
||||
Example = "uesc:data C%3A%5CProgram%20Files%5CPowerToys%5CPowerToys.exe",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "esc:hex",
|
||||
Description = GetStringFormat(GeneratorDescriptionEscHex),
|
||||
Example = "esc:hex z",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Keyword = "uesc:hex",
|
||||
Description = GetStringFormat(GeneratorDescriptionUescHex),
|
||||
Example = "uesc:hex %7A",
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
algorithmName = HashAlgorithmName.SHA512;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unknown SHA variant. Supported variants: SHA1, SHA256, SHA384, SHA512");
|
||||
throw new FormatException("Unknown SHA variant. Supported variants: SHA1, SHA256, SHA384, SHA512");
|
||||
}
|
||||
|
||||
if (content == string.Empty)
|
||||
@@ -93,7 +93,7 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
|
||||
if (!int.TryParse(versionQuery, null, out version))
|
||||
{
|
||||
throw new ArgumentException("Could not determine requested GUID version");
|
||||
throw new FormatException("Could not determine requested GUID version. Supported versions are 1, 3, 4 and 5");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
|
||||
if (sParameters.Length != 2)
|
||||
{
|
||||
throw new ArgumentException("GUID versions 3 and 5 require 2 parameters - a namespace GUID and a name");
|
||||
throw new ArgumentException($"GUID version {version} require 2 parameters - a namespace GUID and a name.\nExample: uuidv{version} ns:<DNS, URL, OID, or X500> <your input>");
|
||||
}
|
||||
|
||||
string namespaceParameter = sParameters[0];
|
||||
|
||||
@@ -7,8 +7,10 @@ using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using Community.PowerToys.Run.Plugin.ValueGenerator.Helper;
|
||||
using Community.PowerToys.Run.Plugin.ValueGenerator.Properties;
|
||||
using ManagedCommon;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Plugin;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
@@ -59,6 +61,19 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetIcoPath(bool isWarning = false)
|
||||
{
|
||||
var imageName = isWarning ? "Warning" : "ValueGenerator";
|
||||
if (_isLightTheme)
|
||||
{
|
||||
return $"Images/{imageName}.light.png";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"Images/{imageName}.dark.png";
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
@@ -90,6 +105,11 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
ArgumentNullException.ThrowIfNull(query);
|
||||
|
||||
var results = new List<Result>();
|
||||
if (string.IsNullOrWhiteSpace(query?.Search) && !string.IsNullOrEmpty(query?.ActionKeyword))
|
||||
{
|
||||
return GetSuggestionResults(query, results);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IComputeRequest computeRequest = _inputParser.ParseInput(query);
|
||||
@@ -110,7 +130,33 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Log.Debug(GetTranslatedPluginTitle() + ": " + e.Message, GetType());
|
||||
Log.Debug(GetTranslatedPluginTitle() + ": " + e.Message, GetType());
|
||||
if (!string.IsNullOrEmpty(query.ActionKeyword))
|
||||
{
|
||||
return GetSuggestionFuzzyResults(query, results);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<Result> GetSuggestionResults(Query query, List<Result> results)
|
||||
{
|
||||
foreach (var generatorData in QueryHelper.GeneratorDataList)
|
||||
{
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = QueryHelper.GetResultTitle(generatorData),
|
||||
SubTitle = QueryHelper.GetResultSubtitle(generatorData),
|
||||
IcoPath = GetIcoPath(),
|
||||
ToolTipData = new ToolTipData(QueryHelper.GetResultTitle(generatorData), QueryHelper.GetResultSubtitle(generatorData)),
|
||||
QueryTextDisplay = generatorData.Keyword + " ",
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.ChangeQuery($"{query.ActionKeyword} {generatorData.Keyword} ", true);
|
||||
return false;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
@@ -124,7 +170,7 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
{
|
||||
ContextData = request.Result,
|
||||
Title = request.ResultToString(),
|
||||
IcoPath = _isLightTheme ? "Images/ValueGenerator.light.png" : "Images/ValueGenerator.dark.png",
|
||||
IcoPath = GetIcoPath(),
|
||||
Score = 300,
|
||||
SubTitle = request.Description,
|
||||
Action = c =>
|
||||
@@ -150,13 +196,42 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator
|
||||
};
|
||||
}
|
||||
|
||||
private List<Result> GetSuggestionFuzzyResults(Query query, List<Result> results)
|
||||
{
|
||||
foreach (var generatorData in QueryHelper.GeneratorDataList)
|
||||
{
|
||||
var matchScore = StringMatcher.FuzzySearch(query.Search.Trim(), generatorData.Keyword).Score;
|
||||
|
||||
if (matchScore > 0)
|
||||
{
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = QueryHelper.GetResultTitle(generatorData),
|
||||
SubTitle = QueryHelper.GetResultSubtitle(generatorData),
|
||||
IcoPath = GetIcoPath(),
|
||||
Score = matchScore,
|
||||
ToolTipData = new ToolTipData(QueryHelper.GetResultTitle(generatorData), QueryHelper.GetResultSubtitle(generatorData)),
|
||||
QueryTextDisplay = generatorData.Keyword + " ",
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.ChangeQuery($"{query.ActionKeyword} {generatorData.Keyword} ", true);
|
||||
return false;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private Result GetErrorResult(string errorMessage)
|
||||
{
|
||||
return new Result
|
||||
{
|
||||
Title = Resources.error_title,
|
||||
SubTitle = errorMessage,
|
||||
IcoPath = _isLightTheme ? "Images/Warning.light.png" : "Images/Warning.dark.png",
|
||||
ToolTipData = new ToolTipData(Resources.error_title, errorMessage),
|
||||
IcoPath = GetIcoPath(isWarning: true),
|
||||
Action = _ => { return true; },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,6 +87,159 @@ namespace Community.PowerToys.Run.Plugin.ValueGenerator.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Encode a string with Base64.
|
||||
/// </summary>
|
||||
public static string generator_description_base64 {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_base64", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Decode a string with Base64.
|
||||
/// </summary>
|
||||
public static string generator_description_base64d {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_base64d", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Escape a data string.
|
||||
/// </summary>
|
||||
public static string generator_description_esc_data {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_esc_data", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Escape a single hex character.
|
||||
/// </summary>
|
||||
public static string generator_description_esc_hex {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_esc_hex", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hash a string with {0}.
|
||||
/// </summary>
|
||||
public static string generator_description_hash {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_hash", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unescape a data string.
|
||||
/// </summary>
|
||||
public static string generator_description_uesc_data {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_uesc_data", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unescape a single hex character.
|
||||
/// </summary>
|
||||
public static string generator_description_uesc_hex {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_uesc_hex", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Encode a URL.
|
||||
/// </summary>
|
||||
public static string generator_description_url {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_url", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Decode a URL.
|
||||
/// </summary>
|
||||
public static string generator_description_urld {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_urld", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Generate a random UUID.
|
||||
/// </summary>
|
||||
public static string generator_description_uuid {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_uuid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Generate a version 1: Time based UUID.
|
||||
/// </summary>
|
||||
public static string generator_description_uuidv1 {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_uuidv1", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Generate a version 3 (MD5): Namespace and name based UUID.
|
||||
/// </summary>
|
||||
public static string generator_description_uuidv3 {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_uuidv3", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Generate a version 4: Randomly generated UUID.
|
||||
/// </summary>
|
||||
public static string generator_description_uuidv4 {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_uuidv4", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Generate a version 5 (SHA1): Namespace and name based UUID.
|
||||
/// </summary>
|
||||
public static string generator_description_uuidv5 {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_uuidv5", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to your input.
|
||||
/// </summary>
|
||||
public static string generator_description_your_input {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_description_your_input", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Example: {0}.
|
||||
/// </summary>
|
||||
public static string generator_example {
|
||||
get {
|
||||
return ResourceManager.GetString("generator_example", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to or.
|
||||
/// </summary>
|
||||
public static string or {
|
||||
get {
|
||||
return ResourceManager.GetString("or", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Calculates hashes and generate values.
|
||||
/// </summary>
|
||||
|
||||
@@ -126,6 +126,60 @@
|
||||
<data name="error_title" xml:space="preserve">
|
||||
<value>Value Generator Error</value>
|
||||
</data>
|
||||
<data name="generator_description_base64" xml:space="preserve">
|
||||
<value>Encode a string with Base64</value>
|
||||
</data>
|
||||
<data name="generator_description_base64d" xml:space="preserve">
|
||||
<value>Decode a string with Base64</value>
|
||||
</data>
|
||||
<data name="generator_description_esc_data" xml:space="preserve">
|
||||
<value>Escape a data string</value>
|
||||
</data>
|
||||
<data name="generator_description_esc_hex" xml:space="preserve">
|
||||
<value>Escape a single hex character</value>
|
||||
</data>
|
||||
<data name="generator_description_hash" xml:space="preserve">
|
||||
<value>Hash a string with {0}</value>
|
||||
</data>
|
||||
<data name="generator_description_uesc_data" xml:space="preserve">
|
||||
<value>Unescape a data string</value>
|
||||
</data>
|
||||
<data name="generator_description_uesc_hex" xml:space="preserve">
|
||||
<value>Unescape a single hex character</value>
|
||||
</data>
|
||||
<data name="generator_description_url" xml:space="preserve">
|
||||
<value>Encode a URL</value>
|
||||
</data>
|
||||
<data name="generator_description_urld" xml:space="preserve">
|
||||
<value>Decode a URL</value>
|
||||
</data>
|
||||
<data name="generator_description_uuid" xml:space="preserve">
|
||||
<value>Generate a random UUID</value>
|
||||
</data>
|
||||
<data name="generator_description_uuidv1" xml:space="preserve">
|
||||
<value>Generate a version 1: Time based UUID</value>
|
||||
</data>
|
||||
<data name="generator_description_uuidv3" xml:space="preserve">
|
||||
<value>Generate a version 3 (MD5): Namespace and name based UUID</value>
|
||||
</data>
|
||||
<data name="generator_description_uuidv4" xml:space="preserve">
|
||||
<value>Generate a version 4: Randomly generated UUID</value>
|
||||
</data>
|
||||
<data name="generator_description_uuidv5" xml:space="preserve">
|
||||
<value>Generate a version 5 (SHA1): Namespace and name based UUID</value>
|
||||
</data>
|
||||
<data name="generator_description_your_input" xml:space="preserve">
|
||||
<value>your input</value>
|
||||
<comment>Usage example: "md5 <your input>"</comment>
|
||||
</data>
|
||||
<data name="generator_example" xml:space="preserve">
|
||||
<value>Example: {0}</value>
|
||||
<comment>The arg following is the usage example</comment>
|
||||
</data>
|
||||
<data name="or" xml:space="preserve">
|
||||
<value>or</value>
|
||||
<comment>Used to indicate alternatives or options available</comment>
|
||||
</data>
|
||||
<data name="plugin_description" xml:space="preserve">
|
||||
<value>Calculates hashes and generate values</value>
|
||||
</data>
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest" />
|
||||
<PackageReference Include="System.IO.Abstractions.TestingHelpers" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user