mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-03 19:06:41 +01:00
Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ccbb694dd | ||
|
|
2dcaa526cb | ||
|
|
03a5a4200e | ||
|
|
148f1df56c | ||
|
|
cc83e2b3ee | ||
|
|
345486acda | ||
|
|
217f3f9ff3 | ||
|
|
cfc65e8c69 | ||
|
|
cb4ee89623 | ||
|
|
63c624b273 | ||
|
|
6ba8596d52 | ||
|
|
67ce81ded8 | ||
|
|
397178deec | ||
|
|
1b9094ae2b | ||
|
|
8dcdcbaa37 | ||
|
|
9511d17063 | ||
|
|
8cb632a0c2 | ||
|
|
b8a253fda6 | ||
|
|
a32d6a688c | ||
|
|
cfaa3670db | ||
|
|
08215a8a77 | ||
|
|
26bf4193f7 | ||
|
|
46ed52eab6 | ||
|
|
a883dcc283 | ||
|
|
c598d93ad3 | ||
|
|
bc8e821ab4 | ||
|
|
d190934d61 | ||
|
|
c7f8b696a6 | ||
|
|
9581cd7a27 | ||
|
|
6ece812103 | ||
|
|
2f130bcc62 | ||
|
|
293b06d083 | ||
|
|
a780e6ae72 | ||
|
|
40ef76a686 | ||
|
|
c69c74a8ad | ||
|
|
06e4518742 | ||
|
|
0adda35b4b | ||
|
|
97578a1b97 | ||
|
|
852778daa5 | ||
|
|
56cdd6dd40 | ||
|
|
284a5fb31f | ||
|
|
eddb617484 | ||
|
|
b6ff97f795 | ||
|
|
d1d7c74440 | ||
|
|
40335a6998 | ||
|
|
026db38457 | ||
|
|
13cc22336b | ||
|
|
994bb15876 | ||
|
|
7e65caa83b | ||
|
|
f6f31c8c32 | ||
|
|
9960d2d536 | ||
|
|
177c58f494 | ||
|
|
1e481b1162 | ||
|
|
ddaa348e5a | ||
|
|
0f6ac52f99 | ||
|
|
995a9ae7a8 | ||
|
|
d426d9afde | ||
|
|
4d5152f78a | ||
|
|
0f6305f5fa | ||
|
|
a012d591c2 | ||
|
|
792a77437e | ||
|
|
2981dc67c3 | ||
|
|
e378f0cebc | ||
|
|
88656a9fe0 | ||
|
|
0f04180912 | ||
|
|
f6a91dd073 | ||
|
|
4cc74da82f | ||
|
|
b50b587a63 | ||
|
|
ce87952058 | ||
|
|
88b1203cd6 | ||
|
|
1d23ed5811 | ||
|
|
b72af5e247 | ||
|
|
4905258c94 | ||
|
|
0c69e3422c | ||
|
|
9786d08695 | ||
|
|
202bb4caf5 | ||
|
|
951d449204 | ||
|
|
ecdf4217e4 | ||
|
|
61073158c2 | ||
|
|
d7ff0d06ec | ||
|
|
850b8c1fb8 | ||
|
|
95a9a8a2b0 | ||
|
|
6d676329ce | ||
|
|
d3b1c0a067 | ||
|
|
b56d22b9a2 | ||
|
|
5cff678322 | ||
|
|
42e707966d | ||
|
|
4560abe557 | ||
|
|
6f56b35a6c | ||
|
|
dbc11b8920 | ||
|
|
0bf4cfd8b5 | ||
|
|
6a4a5c59d7 | ||
|
|
22e4c4ce2a | ||
|
|
667aad247a | ||
|
|
675aac95d2 | ||
|
|
e87de7d9fc | ||
|
|
aea02117fd |
34
.configurations/configuration.dsc.yaml
Normal file
34
.configurations/configuration.dsc.yaml
Normal file
@@ -0,0 +1,34 @@
|
||||
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
|
||||
# Reference: https://github.com/microsoft/PowerToys/blob/main/doc/devdocs/readme.md#compiling-powertoys
|
||||
properties:
|
||||
resources:
|
||||
- resource: Microsoft.Windows.Developer/DeveloperMode
|
||||
directives:
|
||||
description: Enable Developer Mode
|
||||
allowPrerelease: true
|
||||
settings:
|
||||
Ensure: Present
|
||||
- resource: Microsoft.WinGet.DSC/WinGetPackage
|
||||
id: vsPackage
|
||||
directives:
|
||||
description: Install Visual Studio 2022 (any edition is OK)
|
||||
allowPrerelease: true
|
||||
settings:
|
||||
id: Microsoft.VisualStudio.2022.Community
|
||||
source: winget
|
||||
- resource: Microsoft.VisualStudio.DSC/VSComponents
|
||||
dependsOn:
|
||||
- vsPackage
|
||||
directives:
|
||||
description: Install required VS workloads
|
||||
allowPrerelease: true
|
||||
settings:
|
||||
productId: Microsoft.VisualStudio.Product.Community
|
||||
channelId: VisualStudio.17.Release
|
||||
vsConfigFile: '${WinGetConfigRoot}\..\.vsconfig'
|
||||
configurationVersion: 0.2.0
|
||||
|
||||
# Next steps:
|
||||
# Open a terminal
|
||||
# Navigate to the folder you cloned PowerToys to.
|
||||
# Run git submodule update --init --recursive
|
||||
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -10,7 +10,7 @@ body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Microsoft PowerToys version
|
||||
placeholder: 0.68.0
|
||||
placeholder: 0.70.0
|
||||
description: Hover over system tray icon or look at Settings
|
||||
validations:
|
||||
required: true
|
||||
@@ -60,7 +60,9 @@ body:
|
||||
- Installer
|
||||
- Keyboard Manager
|
||||
- Mouse Utilities
|
||||
- Mouse Without Borders
|
||||
- Paste as Plain Text
|
||||
- Peek
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
- Quick Accent
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
4
.github/ISSUE_TEMPLATE/translation_issue.yml
vendored
@@ -12,7 +12,7 @@ body:
|
||||
- type: input
|
||||
attributes:
|
||||
label: Microsoft PowerToys version
|
||||
placeholder: 0.68.0
|
||||
placeholder: 0.70.0
|
||||
description: Hover over system tray icon or look at Settings
|
||||
validations:
|
||||
required: true
|
||||
@@ -34,7 +34,9 @@ body:
|
||||
- Installer
|
||||
- Keyboard Manager
|
||||
- Mouse Utilities
|
||||
- Mouse Without Borders
|
||||
- Paste as Plain Text
|
||||
- Peek
|
||||
- PowerRename
|
||||
- PowerToys Run
|
||||
- Quick Accent
|
||||
|
||||
79
.github/actions/spell-check/expect.txt
vendored
79
.github/actions/spell-check/expect.txt
vendored
@@ -91,7 +91,6 @@ APPIDS
|
||||
appium
|
||||
Applets
|
||||
Applicationcan
|
||||
applicationconfiguration
|
||||
applicationframehost
|
||||
appmanifest
|
||||
APPNAME
|
||||
@@ -158,7 +157,6 @@ BCB
|
||||
BCCE
|
||||
BCCEA
|
||||
bck
|
||||
Bcl
|
||||
BDB
|
||||
BDBAD
|
||||
BDCC
|
||||
@@ -239,7 +237,6 @@ Cangjie
|
||||
CANRENAME
|
||||
CAPTUREBLT
|
||||
CAPTURECHANGED
|
||||
CARRAY
|
||||
CAtl
|
||||
CBA
|
||||
CBB
|
||||
@@ -281,7 +278,6 @@ chdir
|
||||
CHILDACTIVATE
|
||||
CHILDWINDOW
|
||||
chrdavis
|
||||
Chromakey
|
||||
Chrzan
|
||||
CHT
|
||||
cidl
|
||||
@@ -424,7 +420,6 @@ Dac
|
||||
dacl
|
||||
DAF
|
||||
damienleroy
|
||||
DANGEROUSLYCOMMITMERELYTODISKCACHE
|
||||
DARKPURPLE
|
||||
DARKTEAL
|
||||
DARKYELLOW
|
||||
@@ -456,13 +451,11 @@ dcompi
|
||||
DComposition
|
||||
dcr
|
||||
dcs
|
||||
Dct
|
||||
DDCDD
|
||||
DDCE
|
||||
DDEIf
|
||||
DDevice
|
||||
ddf
|
||||
Dds
|
||||
DDxgi
|
||||
Deact
|
||||
debian
|
||||
@@ -494,8 +487,6 @@ depersist
|
||||
deprioritized
|
||||
depsfileslistspath
|
||||
deref
|
||||
READOBJECTS
|
||||
WRITEOBJECTS
|
||||
DESKTOPABSOLUTEEDITING
|
||||
DESKTOPABSOLUTEPARSING
|
||||
desktopshorcutinstalled
|
||||
@@ -545,6 +536,7 @@ drawingcolor
|
||||
dreamsofameaningfullife
|
||||
drf
|
||||
drivedetectionwarning
|
||||
dsc
|
||||
dshow
|
||||
DSTINVERT
|
||||
DUMMYUNIONNAME
|
||||
@@ -622,6 +614,7 @@ Emoji
|
||||
ENABLEDELAYEDEXPANSION
|
||||
enabledisable
|
||||
ENABLEDPOPUP
|
||||
encodedlaunch
|
||||
encryptor
|
||||
endpointvolume
|
||||
endregion
|
||||
@@ -662,8 +655,6 @@ exabyte
|
||||
examplehandler
|
||||
examplepowertoy
|
||||
EXAND
|
||||
Excep
|
||||
EXCEPINFO
|
||||
EXCLUDEFROMCAPTURE
|
||||
exdisp
|
||||
executionpolicy
|
||||
@@ -788,7 +779,6 @@ GETSTATE
|
||||
GETTEXT
|
||||
GETTEXTLENGTH
|
||||
GHND
|
||||
Globbing
|
||||
GMEM
|
||||
GNumber
|
||||
google
|
||||
@@ -833,7 +823,6 @@ HCRYPTHASH
|
||||
HCRYPTPROV
|
||||
hcwhite
|
||||
hdc
|
||||
HDR
|
||||
hdrop
|
||||
hdwwiz
|
||||
HEB
|
||||
@@ -915,17 +904,12 @@ HWNDPREV
|
||||
hyjiacan
|
||||
IBase
|
||||
IBeam
|
||||
IBitmap
|
||||
IBlock
|
||||
ICapture
|
||||
ICEBLUE
|
||||
IClass
|
||||
IColor
|
||||
ICONERROR
|
||||
IContext
|
||||
IData
|
||||
IDD
|
||||
IDecoder
|
||||
IDesktop
|
||||
IDirect
|
||||
idl
|
||||
@@ -934,7 +918,6 @@ IDOn
|
||||
IDR
|
||||
idx
|
||||
IDXGI
|
||||
IEncoder
|
||||
IEnum
|
||||
IExec
|
||||
IEXPLORE
|
||||
@@ -959,7 +942,6 @@ imageresizerinput
|
||||
imageresizersettings
|
||||
imagingdevices
|
||||
ime
|
||||
IMetadata
|
||||
imeutil
|
||||
inetcpl
|
||||
Infobar
|
||||
@@ -997,8 +979,6 @@ Interlop
|
||||
INTRESOURCE
|
||||
INVALIDARG
|
||||
invalidoperatioexception
|
||||
invalidkey
|
||||
IPalette
|
||||
ipc
|
||||
ipcmanager
|
||||
IPlugin
|
||||
@@ -1007,8 +987,6 @@ IPREVIEW
|
||||
ipreviewhandlervisualssetfont
|
||||
IProperty
|
||||
IPublic
|
||||
IQuery
|
||||
IReader
|
||||
irprops
|
||||
isbi
|
||||
ISearch
|
||||
@@ -1016,15 +994,14 @@ ISettings
|
||||
isfinite
|
||||
IShell
|
||||
isocpp
|
||||
ISource
|
||||
iss
|
||||
ISurface
|
||||
ITask
|
||||
ith
|
||||
ITHUMBNAIL
|
||||
IUI
|
||||
IUnknown
|
||||
IWbem
|
||||
IWeb
|
||||
IWIC
|
||||
iwr
|
||||
IYUV
|
||||
@@ -1106,10 +1083,12 @@ lexon
|
||||
lhs
|
||||
lhwnd
|
||||
LIBID
|
||||
licate
|
||||
LIGHTORANGE
|
||||
LIGHTTURQUOISE
|
||||
lindex
|
||||
linkedin
|
||||
LINKOVERLAY
|
||||
linq
|
||||
LINQTo
|
||||
listview
|
||||
@@ -1128,8 +1107,6 @@ LOCALPACKAGE
|
||||
localport
|
||||
LOCALSYSTEM
|
||||
LOCATIONCHANGE
|
||||
LOCKBYTES
|
||||
LOCKTYPE
|
||||
LOGFONT
|
||||
LOGFONTW
|
||||
logon
|
||||
@@ -1151,12 +1128,12 @@ LPCWSTR
|
||||
lpdw
|
||||
lpfn
|
||||
LPINPUT
|
||||
LPQUERY
|
||||
lpmi
|
||||
LPMINMAXINFO
|
||||
LPMONITORINFO
|
||||
LPOSVERSIONINFOEXW
|
||||
LPPOINT
|
||||
LPQUERY
|
||||
lprc
|
||||
LPRECT
|
||||
LPSAFEARRAY
|
||||
@@ -1324,11 +1301,11 @@ Mul
|
||||
MULTIPLEUSE
|
||||
multizone
|
||||
mvvm
|
||||
mwb
|
||||
MWBEx
|
||||
myfile
|
||||
MYICON
|
||||
mysql
|
||||
mwb
|
||||
MWBEx
|
||||
NAMECHANGE
|
||||
nameof
|
||||
namespaceanddescendants
|
||||
@@ -1356,6 +1333,7 @@ NCRBUTTONUP
|
||||
NCRENDERING
|
||||
ndp
|
||||
NEEDDISPATCH
|
||||
needinfo
|
||||
Nemeth
|
||||
NESW
|
||||
netcore
|
||||
@@ -1401,7 +1379,6 @@ NONCONVERT
|
||||
NONELEVATED
|
||||
NONINFRINGEMENT
|
||||
nonstd
|
||||
NOOPEN
|
||||
NOOWNERZORDER
|
||||
NOPARENTNOTIFY
|
||||
NOREDIRECTIONBITMAP
|
||||
@@ -1441,6 +1418,7 @@ nullonfailure
|
||||
numberbox
|
||||
NUMLOCK
|
||||
numpad
|
||||
nupkg
|
||||
nwc
|
||||
Objbase
|
||||
OBJID
|
||||
@@ -1464,8 +1442,6 @@ OLEDB
|
||||
OLIVEGREEN
|
||||
onebranch
|
||||
onenote
|
||||
ONLYIFCURRENT
|
||||
ONLYONCE
|
||||
onstd
|
||||
oobe
|
||||
OOBEPT
|
||||
@@ -1528,6 +1504,7 @@ pcs
|
||||
PCWSTR
|
||||
pdb
|
||||
pdbonly
|
||||
pdisp
|
||||
pdo
|
||||
pdto
|
||||
pdtobj
|
||||
@@ -1565,7 +1542,6 @@ pinvoke
|
||||
pipename
|
||||
PKBDLLHOOKSTRUCT
|
||||
pkey
|
||||
PKEY
|
||||
plib
|
||||
PLK
|
||||
ploc
|
||||
@@ -1598,7 +1574,6 @@ ppidl
|
||||
ppmt
|
||||
pprm
|
||||
pproc
|
||||
pprop
|
||||
ppshv
|
||||
ppsi
|
||||
ppsid
|
||||
@@ -1619,7 +1594,6 @@ previouscamera
|
||||
PREVIOUSINSTALLFOLDER
|
||||
PREVIOUSVERSIONSINSTALLED
|
||||
prevpane
|
||||
PRGBA
|
||||
prgms
|
||||
pri
|
||||
PRINTCLIENT
|
||||
@@ -1636,20 +1610,17 @@ PROGRAMFILES
|
||||
projectname
|
||||
PROPBAG
|
||||
PROPERTYKEY
|
||||
PROPERTYNOTFOUND
|
||||
propkey
|
||||
PROPVARIANT
|
||||
propvarutil
|
||||
prvpane
|
||||
psapi
|
||||
pscid
|
||||
PSECURITY
|
||||
psfgao
|
||||
psfi
|
||||
Psr
|
||||
psrm
|
||||
psrree
|
||||
pstatstg
|
||||
pstm
|
||||
pstr
|
||||
pstream
|
||||
pstrm
|
||||
@@ -1663,7 +1634,6 @@ PToy
|
||||
ptstr
|
||||
pui
|
||||
PULONG
|
||||
pvar
|
||||
pwa
|
||||
pwcs
|
||||
pwsh
|
||||
@@ -1703,6 +1673,7 @@ rclsid
|
||||
RCONTROL
|
||||
RCtrl
|
||||
READMODE
|
||||
READOBJECTS
|
||||
READWRITE
|
||||
RECTDESTINATION
|
||||
RECTL
|
||||
@@ -1748,6 +1719,7 @@ renamable
|
||||
RENAMEONCOLLISION
|
||||
Renamer
|
||||
reparse
|
||||
reportbug
|
||||
requery
|
||||
requerying
|
||||
rescap
|
||||
@@ -1765,7 +1737,6 @@ resw
|
||||
resx
|
||||
retval
|
||||
rfc
|
||||
RGBE
|
||||
RGBQUAD
|
||||
rgbs
|
||||
rgelt
|
||||
@@ -1808,7 +1779,6 @@ rungameid
|
||||
RUNLEVEL
|
||||
runsettings
|
||||
runtimeclass
|
||||
runtimeconfig
|
||||
runtimedepsjsonpath
|
||||
runtimeobject
|
||||
runtimepack
|
||||
@@ -1824,7 +1794,6 @@ ryanbodrug
|
||||
saahmedm
|
||||
sachaple
|
||||
sacl
|
||||
SAFEARRAY
|
||||
safeprojectname
|
||||
SAMEKEYPREVIOUSLYMAPPED
|
||||
SAMESHORTCUTPREVIOUSLYMAPPED
|
||||
@@ -1855,7 +1824,6 @@ sendvirtualinput
|
||||
Seperate
|
||||
Seraphima
|
||||
serverside
|
||||
Ses
|
||||
SETCONTEXT
|
||||
setcursor
|
||||
setenv
|
||||
@@ -1873,6 +1841,7 @@ setzero
|
||||
sfgao
|
||||
SFGAOF
|
||||
SFP
|
||||
SHANDLE
|
||||
sharpkeys
|
||||
SHCNE
|
||||
SHCNF
|
||||
@@ -1888,6 +1857,7 @@ shellscalingapi
|
||||
SHFILEINFO
|
||||
SHGDNF
|
||||
SHGFI
|
||||
shinfo
|
||||
Shl
|
||||
shldisp
|
||||
shlobj
|
||||
@@ -1943,7 +1913,6 @@ SMALLICON
|
||||
smartphone
|
||||
SMTO
|
||||
snd
|
||||
sni
|
||||
snwprintf
|
||||
softline
|
||||
somil
|
||||
@@ -1971,7 +1940,6 @@ SRCPAINT
|
||||
sre
|
||||
SResize
|
||||
srf
|
||||
SRGB
|
||||
srme
|
||||
srre
|
||||
srw
|
||||
@@ -2000,10 +1968,8 @@ STDMETHODCALLTYPE
|
||||
STDMETHODIMP
|
||||
stefan
|
||||
Stereolithography
|
||||
STGC
|
||||
STGM
|
||||
STGMEDIUM
|
||||
STGTY
|
||||
sticpl
|
||||
stl
|
||||
storelogo
|
||||
@@ -2077,8 +2043,8 @@ taskschd
|
||||
tchar
|
||||
tcl
|
||||
Tcollab
|
||||
tcs
|
||||
tcp
|
||||
tcs
|
||||
tcscpy
|
||||
TCustom
|
||||
tdbuild
|
||||
@@ -2097,6 +2063,7 @@ TEXCOORD
|
||||
textblock
|
||||
TEXTEXTRACTOR
|
||||
TEXTINCLUDE
|
||||
tgz
|
||||
themeresources
|
||||
THH
|
||||
THICKFRAME
|
||||
@@ -2161,8 +2128,10 @@ uipi
|
||||
UIs
|
||||
ULARGE
|
||||
ULONGLONG
|
||||
unapply
|
||||
unassign
|
||||
uncompilable
|
||||
Uncompress
|
||||
UNCPRIORITY
|
||||
UNDNAME
|
||||
UNICODETEXT
|
||||
@@ -2192,7 +2161,6 @@ Usb
|
||||
USEDEFAULT
|
||||
USEFILEATTRIBUTES
|
||||
USERDATA
|
||||
USERDEFINED
|
||||
USERDOMAIN
|
||||
userprofile
|
||||
USESHOWWINDOW
|
||||
@@ -2209,7 +2177,6 @@ vabdq
|
||||
validmodulename
|
||||
Vanara
|
||||
variantassignment
|
||||
VARTYPE
|
||||
vcamp
|
||||
vccorlib
|
||||
vcdl
|
||||
@@ -2229,7 +2196,6 @@ VERBSONLY
|
||||
VERBW
|
||||
VERIFYCONTEXT
|
||||
verrsrc
|
||||
VERSIONED
|
||||
VERSIONINFO
|
||||
Versioning
|
||||
VFT
|
||||
@@ -2329,8 +2295,8 @@ winget
|
||||
wingetcreate
|
||||
Winhook
|
||||
winkey
|
||||
winlogon
|
||||
WINL
|
||||
winlogon
|
||||
winmd
|
||||
winmm
|
||||
WINNT
|
||||
@@ -2387,6 +2353,7 @@ wregex
|
||||
WReserved
|
||||
WResize
|
||||
writefile
|
||||
WRITEOBJECTS
|
||||
Wrk
|
||||
wrl
|
||||
WSAEADDRINUSE
|
||||
@@ -2398,7 +2365,6 @@ wsh
|
||||
wsl
|
||||
wss
|
||||
wstr
|
||||
wsystem
|
||||
wsz
|
||||
wtoi
|
||||
WTS
|
||||
@@ -2442,7 +2408,6 @@ yinyue
|
||||
YOffset
|
||||
YPels
|
||||
ypescript
|
||||
YQuantized
|
||||
YResolution
|
||||
YStr
|
||||
YUY
|
||||
|
||||
929
.github/fabricbot.json
vendored
929
.github/fabricbot.json
vendored
@@ -1,929 +0,0 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"tasks": [
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssuesOnlyResponder",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"taskName": "Add needs triage label to new issues",
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "isAction",
|
||||
"parameters": {
|
||||
"action": "opened"
|
||||
}
|
||||
},
|
||||
{
|
||||
"operator": "not",
|
||||
"operands": [
|
||||
{
|
||||
"name": "isPartOfProject",
|
||||
"parameters": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"operator": "not",
|
||||
"operands": [
|
||||
{
|
||||
"name": "isAssignedToSomeone",
|
||||
"parameters": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Triage"
|
||||
}
|
||||
}
|
||||
],
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issues",
|
||||
"project_card"
|
||||
]
|
||||
},
|
||||
"id": "eUOhvA_62"
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssueCommentResponder",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"taskName": "Replace needs author feedback label with needs attention label when the author comments on an issue",
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "isAction",
|
||||
"parameters": {
|
||||
"action": "created"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "isActivitySender",
|
||||
"parameters": {
|
||||
"user": {
|
||||
"type": "author"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "hasLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Author-Feedback"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "isOpen",
|
||||
"parameters": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Triage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Author-Feedback"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Team-Response"
|
||||
}
|
||||
}
|
||||
],
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issue_comment"
|
||||
]
|
||||
},
|
||||
"id": "kgfxdBIu_9"
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssuesOnlyResponder",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"taskName": "Remove no recent activity label from issues",
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"operator": "not",
|
||||
"operands": [
|
||||
{
|
||||
"name": "isAction",
|
||||
"parameters": {
|
||||
"action": "closed"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hasLabel",
|
||||
"parameters": {
|
||||
"label": "Status-No recent activity"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Status-No recent activity"
|
||||
}
|
||||
}
|
||||
],
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issues",
|
||||
"project_card"
|
||||
]
|
||||
},
|
||||
"id": "eR-TaGJJzW",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssueCommentResponder",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"taskName": "Remove no recent activity label when an issue is commented on",
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "hasLabel",
|
||||
"parameters": {
|
||||
"label": "Status-No recent activity"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Status-No recent activity"
|
||||
}
|
||||
}
|
||||
],
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issue_comment"
|
||||
]
|
||||
},
|
||||
"id": "tXKeoDht_g",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"taskType": "scheduled",
|
||||
"capabilityId": "ScheduledSearch",
|
||||
"subCapability": "ScheduledSearch",
|
||||
"version": "1.1",
|
||||
"config": {
|
||||
"taskName": "Close stale issues",
|
||||
"frequency": [
|
||||
{
|
||||
"weekDay": 0,
|
||||
"hours": [
|
||||
1,
|
||||
7,
|
||||
13,
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 1,
|
||||
"hours": [
|
||||
1,
|
||||
7,
|
||||
13,
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 2,
|
||||
"hours": [
|
||||
1,
|
||||
7,
|
||||
13,
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 3,
|
||||
"hours": [
|
||||
1,
|
||||
7,
|
||||
13,
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 4,
|
||||
"hours": [
|
||||
1,
|
||||
7,
|
||||
13,
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 5,
|
||||
"hours": [
|
||||
1,
|
||||
7,
|
||||
13,
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 6,
|
||||
"hours": [
|
||||
1,
|
||||
7,
|
||||
13,
|
||||
19
|
||||
]
|
||||
}
|
||||
],
|
||||
"searchTerms": [
|
||||
{
|
||||
"name": "isIssue",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "isOpen",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "hasLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Author-Feedback"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "hasLabel",
|
||||
"parameters": {
|
||||
"label": "Status-No recent activity"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "noActivitySince",
|
||||
"parameters": {
|
||||
"days": 5
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "closeIssue",
|
||||
"parameters": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "8yr-nVZj9k",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"taskType": "scheduled",
|
||||
"capabilityId": "ScheduledSearch",
|
||||
"subCapability": "ScheduledSearch",
|
||||
"version": "1.1",
|
||||
"config": {
|
||||
"taskName": "Add no recent activity label to issues",
|
||||
"frequency": [
|
||||
{
|
||||
"weekDay": 0,
|
||||
"hours": [
|
||||
2,
|
||||
8,
|
||||
14,
|
||||
20
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 1,
|
||||
"hours": [
|
||||
2,
|
||||
8,
|
||||
14,
|
||||
20
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 2,
|
||||
"hours": [
|
||||
2,
|
||||
8,
|
||||
14,
|
||||
20
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 3,
|
||||
"hours": [
|
||||
2,
|
||||
8,
|
||||
14,
|
||||
20
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 4,
|
||||
"hours": [
|
||||
2,
|
||||
8,
|
||||
14,
|
||||
20
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 5,
|
||||
"hours": [
|
||||
2,
|
||||
8,
|
||||
14,
|
||||
20
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 6,
|
||||
"hours": [
|
||||
2,
|
||||
8,
|
||||
14,
|
||||
20
|
||||
]
|
||||
}
|
||||
],
|
||||
"searchTerms": [
|
||||
{
|
||||
"name": "isIssue",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "isOpen",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "hasLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Author-Feedback"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "noActivitySince",
|
||||
"parameters": {
|
||||
"days": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "noLabel",
|
||||
"parameters": {
|
||||
"label": "Status-No recent activity"
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Status-No recent activity"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addReply",
|
||||
"parameters": {
|
||||
"comment": "This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **5 days**. It will be closed if no further activity occurs **within 5 days of this comment**."
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "DAhxoYjVcq",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"taskType": "scheduled",
|
||||
"capabilityId": "ScheduledSearch",
|
||||
"subCapability": "ScheduledSearch",
|
||||
"version": "1.1",
|
||||
"config": {
|
||||
"taskName": "Close duplicate issues",
|
||||
"frequency": [
|
||||
{
|
||||
"weekDay": 0,
|
||||
"hours": [
|
||||
3,
|
||||
9,
|
||||
15,
|
||||
21
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 1,
|
||||
"hours": [
|
||||
3,
|
||||
9,
|
||||
15,
|
||||
21
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 2,
|
||||
"hours": [
|
||||
3,
|
||||
9,
|
||||
15,
|
||||
21
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 3,
|
||||
"hours": [
|
||||
3,
|
||||
9,
|
||||
15,
|
||||
21
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 4,
|
||||
"hours": [
|
||||
3,
|
||||
9,
|
||||
15,
|
||||
21
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 5,
|
||||
"hours": [
|
||||
3,
|
||||
9,
|
||||
15,
|
||||
21
|
||||
]
|
||||
},
|
||||
{
|
||||
"weekDay": 6,
|
||||
"hours": [
|
||||
3,
|
||||
9,
|
||||
15,
|
||||
21
|
||||
]
|
||||
}
|
||||
],
|
||||
"searchTerms": [
|
||||
{
|
||||
"name": "isIssue",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "isOpen",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "hasLabel",
|
||||
"parameters": {
|
||||
"label": "Resolution-Duplicate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "noActivitySince",
|
||||
"parameters": {
|
||||
"days": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "addReply",
|
||||
"parameters": {
|
||||
"comment": "This issue has been marked as duplicate and has not had any activity for **1 day**. It will be closed for housekeeping purposes."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "closeIssue",
|
||||
"parameters": {}
|
||||
}
|
||||
]
|
||||
},
|
||||
"id": "xGhARy1H0w"
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "InPrLabel",
|
||||
"subCapability": "InPrLabel",
|
||||
"version": "1.0",
|
||||
"config": {
|
||||
"taskName": "Add 'In-PR' label on issue when an open pull request is targeting it",
|
||||
"inPrLabelText": "Status: In PR",
|
||||
"fixedLabelText": "Status: Fixed",
|
||||
"fixedLabelEnabled": true,
|
||||
"label_fixed": "Resolution-Fix-Committed",
|
||||
"label_inPr": "In progress"
|
||||
},
|
||||
"id": "Rn1tANe62T"
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "EmailCleanser",
|
||||
"subCapability": "EmailCleanser",
|
||||
"version": "1.0",
|
||||
"id": "X0O-6aZ1v3_DAmhUIcNb2",
|
||||
"config": {
|
||||
"taskName": "Clean the email stuff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssueCommentResponder",
|
||||
"version": "1.0",
|
||||
"id": "VyV9JJSA8SbOyeWEwjyfL",
|
||||
"config": {
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "commentContains",
|
||||
"parameters": {
|
||||
"commentPattern": "\\/(bugreport|reportbug)",
|
||||
"isRegex": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"operator": "or",
|
||||
"operands": [
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"permissions": "admin",
|
||||
"association": "MEMBER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "OWNER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "COLLABORATOR"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issue_comment"
|
||||
],
|
||||
"taskName": "Ask for bug report zip file",
|
||||
"actions": [
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Triage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Author-Feedback"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addReply",
|
||||
"parameters": {
|
||||
"comment": "Hi there!<br/><br/>We need a bit more information to really debug this issue. Can you add a \"Report Bug\" zip file here? You right click on our system tray icon and just go to report bug. Then drag the zipfile from your desktop onto the GitHub comment box in this issue. Thanks! <br/>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Team-Response"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssueCommentResponder",
|
||||
"version": "1.0",
|
||||
"id": "bvMkigH2HPgUniYFCNco9",
|
||||
"config": {
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "commentContains",
|
||||
"parameters": {
|
||||
"isRegex": true,
|
||||
"commentPattern": "\\/feedback[H|h]ub"
|
||||
}
|
||||
},
|
||||
{
|
||||
"operator": "or",
|
||||
"operands": [
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "OWNER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "MEMBER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "COLLABORATOR"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issue_comment"
|
||||
],
|
||||
"taskName": "Helper to mark as feedback hub",
|
||||
"actions": [
|
||||
{
|
||||
"name": "addReply",
|
||||
"parameters": {
|
||||
"comment": "Hi! We've identified this issue that best is suited for Windows Feedback Hub. To do this on Windows, WinKey+F will bring it up!"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "closeIssue",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Triage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Team-Response"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Resolution-Please File on Feedback Hub"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssueCommentResponder",
|
||||
"version": "1.0",
|
||||
"id": "bvMkigH2HPgUniYFCNco8",
|
||||
"config": {
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "commentContains",
|
||||
"parameters": {
|
||||
"isRegex": true,
|
||||
"commentPattern": "\\/dup(licate|e)?(\\s+of)?\\s+(#[\\d]+|https)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"operator": "or",
|
||||
"operands": [
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "OWNER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "MEMBER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "COLLABORATOR"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issue_comment"
|
||||
],
|
||||
"taskName": "Helper to mark as duplicate",
|
||||
"actions": [
|
||||
{
|
||||
"name": "addReply",
|
||||
"parameters": {
|
||||
"comment": "Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report!"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "closeIssue",
|
||||
"parameters": {}
|
||||
},
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Triage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Team-Response"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Resolution-Duplicate"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssueCommentResponder",
|
||||
"version": "1.0",
|
||||
"id": "mgZxIoqeF7GWUo7-tZF56",
|
||||
"config": {
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "commentContains",
|
||||
"parameters": {
|
||||
"commentPattern": "\\/needinfo",
|
||||
"isRegex": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"operator": "or",
|
||||
"operands": [
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "OWNER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "MEMBER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "COLLABORATOR"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issue_comment"
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Triage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Team-Response"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Author-Feedback"
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskName": "Author Response needed"
|
||||
}
|
||||
},
|
||||
{
|
||||
"taskType": "trigger",
|
||||
"capabilityId": "IssueResponder",
|
||||
"subCapability": "IssueCommentResponder",
|
||||
"version": "1.0",
|
||||
"id": "mgZxIoqeF7GWUo7-t3773",
|
||||
"config": {
|
||||
"conditions": {
|
||||
"operator": "and",
|
||||
"operands": [
|
||||
{
|
||||
"name": "commentContains",
|
||||
"parameters": {
|
||||
"commentPattern": "\\/loc\\b",
|
||||
"isRegex": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"operator": "or",
|
||||
"operands": [
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "OWNER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "activitySenderHasAssociation",
|
||||
"parameters": {
|
||||
"association": "MEMBER"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eventType": "issue",
|
||||
"eventNames": [
|
||||
"issue_comment"
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "removeLabel",
|
||||
"parameters": {
|
||||
"label": "Needs-Triage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addLabel",
|
||||
"parameters": {
|
||||
"label": "Loc-Sent To Team"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "addReply",
|
||||
"parameters": {
|
||||
"comment": "Hi! Thanks for making us aware of the problem. We raised the issue with our internal localization team. This issue should be fixed hopefully in the next version of PowerToys."
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskName": "Filed ADO item with Localization team"
|
||||
}
|
||||
}
|
||||
],
|
||||
"userGroups": []
|
||||
}
|
||||
214
.github/policies/resourceManagement.yml
vendored
Normal file
214
.github/policies/resourceManagement.yml
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
id:
|
||||
name: GitOps.PullRequestIssueManagement
|
||||
description: GitOps.PullRequestIssueManagement primitive
|
||||
owner:
|
||||
resource: repository
|
||||
disabled: false
|
||||
where:
|
||||
configuration:
|
||||
resourceManagementConfiguration:
|
||||
scheduledSearches:
|
||||
- description:
|
||||
frequencies:
|
||||
- hourly:
|
||||
hour: 6
|
||||
filters:
|
||||
- isIssue
|
||||
- isOpen
|
||||
- hasLabel:
|
||||
label: Needs-Author-Feedback
|
||||
- hasLabel:
|
||||
label: Status-No recent activity
|
||||
- noActivitySince:
|
||||
days: 5
|
||||
actions:
|
||||
- closeIssue
|
||||
- description:
|
||||
frequencies:
|
||||
- hourly:
|
||||
hour: 6
|
||||
filters:
|
||||
- isIssue
|
||||
- isOpen
|
||||
- hasLabel:
|
||||
label: Needs-Author-Feedback
|
||||
- noActivitySince:
|
||||
days: 5
|
||||
- isNotLabeledWith:
|
||||
label: Status-No recent activity
|
||||
actions:
|
||||
- addLabel:
|
||||
label: Status-No recent activity
|
||||
- addReply:
|
||||
reply: This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **5 days**. It will be closed if no further activity occurs **within 5 days of this comment**.
|
||||
- description:
|
||||
frequencies:
|
||||
- hourly:
|
||||
hour: 6
|
||||
filters:
|
||||
- isIssue
|
||||
- isOpen
|
||||
- hasLabel:
|
||||
label: Resolution-Duplicate
|
||||
- noActivitySince:
|
||||
days: 1
|
||||
actions:
|
||||
- addReply:
|
||||
reply: This issue has been marked as duplicate and has not had any activity for **1 day**. It will be closed for housekeeping purposes.
|
||||
- closeIssue
|
||||
eventResponderTasks:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- isAction:
|
||||
action: Created
|
||||
- isActivitySender:
|
||||
issueAuthor: True
|
||||
- hasLabel:
|
||||
label: Needs-Author-Feedback
|
||||
- isOpen
|
||||
then:
|
||||
- addLabel:
|
||||
label: Needs-Triage
|
||||
- removeLabel:
|
||||
label: Needs-Author-Feedback
|
||||
- addLabel:
|
||||
label: Needs-Team-Response
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issues
|
||||
- not:
|
||||
isAction:
|
||||
action: Closed
|
||||
- hasLabel:
|
||||
label: Status-No recent activity
|
||||
then:
|
||||
- removeLabel:
|
||||
label: Status-No recent activity
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- hasLabel:
|
||||
label: Status-No recent activity
|
||||
then:
|
||||
- removeLabel:
|
||||
label: Status-No recent activity
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Pull_Request
|
||||
then:
|
||||
- inPrLabel:
|
||||
label: Status-In progress
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
then:
|
||||
- cleanEmailReply
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- commentContains:
|
||||
pattern: '\/(bugreport|reportbug)'
|
||||
isRegex: True
|
||||
- or:
|
||||
- activitySenderHasAssociation:
|
||||
association: Member
|
||||
- activitySenderHasAssociation:
|
||||
association: Owner
|
||||
- activitySenderHasAssociation:
|
||||
association: Collaborator
|
||||
then:
|
||||
- removeLabel:
|
||||
label: Needs-Triage
|
||||
- addLabel:
|
||||
label: Needs-Author-Feedback
|
||||
- addReply:
|
||||
reply: Hi there!<br/><br/>We need a bit more information to really debug this issue. Can you add a "Report Bug" zip file here? You right click on our system tray icon and just go to report bug. Then drag the zipfile from your desktop onto the GitHub comment box in this issue. Thanks! <br/>
|
||||
- removeLabel:
|
||||
label: Needs-Team-Response
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- commentContains:
|
||||
pattern: '\/feedback[H|h]ub'
|
||||
isRegex: True
|
||||
- or:
|
||||
- activitySenderHasAssociation:
|
||||
association: Owner
|
||||
- activitySenderHasAssociation:
|
||||
association: Member
|
||||
- activitySenderHasAssociation:
|
||||
association: Collaborator
|
||||
then:
|
||||
- addReply:
|
||||
reply: Hi! We've identified this issue that best is suited for Windows Feedback Hub. To do this on Windows, WinKey+F will bring it up!
|
||||
- closeIssue
|
||||
- removeLabel:
|
||||
label: Needs-Triage
|
||||
- removeLabel:
|
||||
label: Needs-Team-Response
|
||||
- addLabel:
|
||||
label: Resolution-Please File on Feedback Hub
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- commentContains:
|
||||
pattern: '\/dup(licate|e)?(\s+of)?\s+(\#[\d]+|https)'
|
||||
isRegex: True
|
||||
- or:
|
||||
- activitySenderHasAssociation:
|
||||
association: Owner
|
||||
- activitySenderHasAssociation:
|
||||
association: Member
|
||||
- activitySenderHasAssociation:
|
||||
association: Collaborator
|
||||
then:
|
||||
- addReply:
|
||||
reply: Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report!
|
||||
- closeIssue
|
||||
- removeLabel:
|
||||
label: Needs-Triage
|
||||
- removeLabel:
|
||||
label: Needs-Team-Response
|
||||
- addLabel:
|
||||
label: Resolution-Duplicate
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- commentContains:
|
||||
pattern: '\/needinfo'
|
||||
isRegex: True
|
||||
- or:
|
||||
- activitySenderHasAssociation:
|
||||
association: Owner
|
||||
- activitySenderHasAssociation:
|
||||
association: Member
|
||||
- activitySenderHasAssociation:
|
||||
association: Collaborator
|
||||
then:
|
||||
- removeLabel:
|
||||
label: Needs-Triage
|
||||
- removeLabel:
|
||||
label: Needs-Team-Response
|
||||
- addLabel:
|
||||
label: Needs-Author-Feedback
|
||||
description:
|
||||
- if:
|
||||
- payloadType: Issue_Comment
|
||||
- commentContains:
|
||||
pattern: '\/loc\b'
|
||||
isRegex: True
|
||||
- or:
|
||||
- activitySenderHasAssociation:
|
||||
association: Owner
|
||||
- activitySenderHasAssociation:
|
||||
association: Member
|
||||
then:
|
||||
- removeLabel:
|
||||
label: Needs-Triage
|
||||
- addLabel:
|
||||
label: Loc-Sent To Team
|
||||
- addReply:
|
||||
reply: Hi! Thanks for making us aware of the problem. We raised the issue with our internal localization team. This issue should be fixed hopefully in the next version of PowerToys.
|
||||
description:
|
||||
onFailure:
|
||||
onSuccess:
|
||||
2
.github/workflows/package-submissions.yml
vendored
2
.github/workflows/package-submissions.yml
vendored
@@ -28,4 +28,4 @@ jobs:
|
||||
|
||||
# getting latest wingetcreate file
|
||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||
.\wingetcreate.exe update $wingetPackage -s -v $ver -u $installerUserX64Url $installerMachineX64Url $installerUserArmUrl $installerMachineArmUrl -t $gitToken
|
||||
.\wingetcreate.exe update $wingetPackage -s -v $ver -u "$installerUserX64Url|user" "$installerMachineX64Url|machine" "$installerUserArmUrl|user" "$installerMachineArmUrl|machine" -t $gitToken
|
||||
|
||||
@@ -279,6 +279,7 @@
|
||||
"modules\\MouseWithoutBorders\\MessagePack.Annotations.dll",
|
||||
"modules\\MouseWithoutBorders\\MessagePack.dll",
|
||||
"modules\\MouseWithoutBorders\\Nerdbank.Streams.dll",
|
||||
"modules\\Peek\\SharpCompress.dll",
|
||||
"Settings\\Microsoft.Graphics.Canvas.Interop.dll",
|
||||
"Settings\\clrcompression.dll",
|
||||
"Settings\\CommunityToolkit.Labs.WinUI.SettingsControls.dll",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"Microsoft.VisualStudio.Component.VC.Runtimes.x86.x64.Spectre",
|
||||
"Microsoft.VisualStudio.Component.VC.ATL.ARM64",
|
||||
"Microsoft.VisualStudio.Component.VC.ATL.ARM64.Spectre",
|
||||
"Microsoft.VisualStudio.Component.VC.ATL",
|
||||
"Microsoft.VisualStudio.Component.VC.ATL.Spectre",
|
||||
"Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs"
|
||||
]
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<PackageTags>PowerToys</PackageTags>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
<AnalysisMode>Recommended</AnalysisMode>
|
||||
<_SkipUpgradeNetAnalyzersNuGetWarning>true</_SkipUpgradeNetAnalyzersNuGetWarning>
|
||||
<PlatformTarget>$(Platform)</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Appium.WebDriver" Version="4.2.1" />
|
||||
<PackageVersion Include="CommunityToolkit.Labs.WinUI.SettingsControls" Version="0.0.18" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.0.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.0" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Animations" Version="7.1.2" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" />
|
||||
<PackageVersion Include="ControlzEx" Version="5.0.1" />
|
||||
<PackageVersion Include="coverlet.collector" Version="1.3.0" />
|
||||
@@ -18,7 +19,7 @@
|
||||
<PackageVersion Include="LazyCache" Version="2.4.0" />
|
||||
<PackageVersion Include="Mages" Version="2.0.1" />
|
||||
<PackageVersion Include="Markdig.Signed" Version="0.27.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="7.0.1" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="7.0.3" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="7.0.0" />
|
||||
<PackageVersion Include="Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers" Version="0.4.336902" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
@@ -28,7 +29,7 @@
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.1722.45" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="7.0.1" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="7.0.3" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.0.2" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
|
||||
@@ -44,6 +45,7 @@
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.0.4" />
|
||||
<PackageVersion Include="NLog.Schema" Version="5.0.4" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.33.0" />
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.14.24" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.435" />
|
||||
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
@@ -53,7 +55,7 @@
|
||||
<PackageVersion Include="System.Drawing.Common" Version="7.0.0" />
|
||||
<PackageVersion Include="System.IO.Abstractions" Version="17.2.3" />
|
||||
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="17.2.3" />
|
||||
<PackageVersion Include="System.Management" Version="7.0.0" />
|
||||
<PackageVersion Include="System.Management" Version="7.0.2" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.0-preview.9" />
|
||||
<PackageVersion Include="System.Runtime.Caching" Version="7.0.0" />
|
||||
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="7.0.0" />
|
||||
@@ -61,7 +63,7 @@
|
||||
<PackageVersion Include="UnitsNet" Version="4.145.0" />
|
||||
<PackageVersion Include="Vanara.PInvoke.User32" Version="3.4.11" />
|
||||
<PackageVersion Include="Vanara.PInvoke.Shell32" Version="3.4.11" />
|
||||
<PackageVersion Include="WinUIEx" Version="2.1.0" />
|
||||
<PackageVersion Include="WinUIEx" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsExperimentationLive)'!=''">
|
||||
<!-- Additional dependencies used by experimentation -->
|
||||
|
||||
12
NOTICE.md
12
NOTICE.md
@@ -282,8 +282,9 @@ SOFTWARE.
|
||||
## NuGet Packages used by PowerToys
|
||||
|
||||
- CommunityToolkit.Labs.WinUI.SettingsControls 0.0.18
|
||||
- CommunityToolkit.Mvvm 8.0.0
|
||||
- CommunityToolkit.Mvvm 8.2.0
|
||||
- CommunityToolkit.WinUI.UI 7.1.2
|
||||
- CommunityToolkit.WinUI.UI.Animations 7.1.2
|
||||
- CommunityToolkit.WinUI.UI.Controls 7.1.2
|
||||
- ControlzEx 5.0.1
|
||||
- HelixToolkit 2.20.2
|
||||
@@ -293,7 +294,7 @@ SOFTWARE.
|
||||
- LazyCache 2.4.0
|
||||
- Mages 2.0.1
|
||||
- Markdig.Signed 0.27.0
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 7.0.1
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 7.0.3
|
||||
- Microsoft.Data.Sqlite 7.0.0
|
||||
- Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzers 0.4.336902
|
||||
- Microsoft.Extensions.DependencyInjection 7.0.0
|
||||
@@ -303,7 +304,7 @@ SOFTWARE.
|
||||
- Microsoft.NET.Test.Sdk 17.4.1
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.1722.45
|
||||
- Microsoft.Windows.Compatibility 7.0.1
|
||||
- Microsoft.Windows.Compatibility 7.0.3
|
||||
- Microsoft.Windows.CsWin32 0.2.46-beta
|
||||
- Microsoft.Windows.CsWinRT 2.0.2
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.22621.755
|
||||
@@ -317,6 +318,7 @@ SOFTWARE.
|
||||
- NLog.Extensions.Logging 5.0.4
|
||||
- NLog.Schema 5.0.4
|
||||
- ScipBe.Common.Office.OneNote 3.0.1
|
||||
- SharpCompress 0.33.0
|
||||
- StreamJsonRpc 2.14.24
|
||||
- StyleCop.Analyzers 1.2.0-beta.435
|
||||
- System.CommandLine 2.0.0-beta4.22272.1
|
||||
@@ -326,7 +328,7 @@ SOFTWARE.
|
||||
- System.Drawing.Common 7.0.0
|
||||
- System.IO.Abstractions 17.2.3
|
||||
- System.IO.Abstractions.TestingHelpers 17.2.3
|
||||
- System.Management 7.0.0
|
||||
- System.Management 7.0.2
|
||||
- System.Reactive 6.0.0-preview.9
|
||||
- System.Runtime.Caching 7.0.0
|
||||
- System.ServiceProcess.ServiceController 7.0.0
|
||||
@@ -334,5 +336,5 @@ SOFTWARE.
|
||||
- UnitsNet 4.145.0
|
||||
- Vanara.PInvoke.Shell32 3.4.11
|
||||
- Vanara.PInvoke.User32 3.4.11
|
||||
- WinUIEx 2.1.0
|
||||
- WinUIEx 2.2.0
|
||||
|
||||
|
||||
158
README.md
158
README.md
@@ -13,7 +13,7 @@
|
||||
|
||||
## About
|
||||
|
||||
Microsoft PowerToys is a set of utilities for power users to tune and streamline their Windows experience for greater productivity. For more info on [PowerToys overviews and how to use the utilities][usingPowerToys-docs-link], or any other tools and resources for [Windows development environments](https://learn.microsoft.com/windows/dev-environment/overview), head over to [learn.microsoft.com][usingPowerToys-docs-link]!
|
||||
Microsoft PowerToys is a set of utilities for power users to tune and streamline their Windows experience for greater productivity. For more info on [PowerToys overviews and how to use the utilities][usingPowerToys-docs-link], or any other tools and resources for [Windows development environments](https://learn.microsoft.com/windows/dev-environment/overview), head over to [learn.microsoft.com][usingPowerToys-docs-link]!
|
||||
|
||||
| | Current utilities: | |
|
||||
|--------------|--------------------|--------------|
|
||||
@@ -36,11 +36,19 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
### Via GitHub with EXE [Recommended]
|
||||
|
||||
Go to [Microsoft PowerToys GitHub releases page][github-release-link], click on `Assets` at the bottom to show the files available in the release. Please use the appropriate PowerToys installer that matches your machine's architecture and install scope. For most, it is `x64` and per-user.
|
||||
|
||||
- **For x64 processors (most common) per-user installer:** [PowerToysUserSetup-0.69.1-x64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysUserSetup-0.69.1-x64.exe)
|
||||
- **For x64 processors per-machine installer:** [PowerToysSetup-0.69.1-x64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysSetup-0.69.1-x64.exe)
|
||||
- **For ARM64 processors per-user installer:** [PowerToysUserSetup-0.69.1-arm64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysUserSetup-0.69.1-arm64.exe)
|
||||
- **For ARM64 processors per-machine installer:** [PowerToysSetup-0.69.1-arm64.exe](https://github.com/microsoft/PowerToys/releases/download/v0.69.1/PowerToysSetup-0.69.1-arm64.exe)
|
||||
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=issue+project%3Amicrosoft%2FPowerToys%2F43
|
||||
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.70.1/PowerToysUserSetup-0.70.1-x64.exe
|
||||
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.70.1/PowerToysUserSetup-0.70.1-arm64.exe
|
||||
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.70.1/PowerToysSetup-0.70.1-x64.exe
|
||||
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.70.1/PowerToysSetup-0.70.1-arm64.exe
|
||||
|
||||
| Description | Filename | sha256 hash |
|
||||
|----------------|----------|-------------|
|
||||
| Per user - x64 | [PowerToysUserSetup-0.70.1-x64.exe][ptUserX64] | B8FD209310B9847DA3AC35C2C5A89F99CE5EA91F456D9D3595DD2840D62A1AC1 |
|
||||
| Per user - ARM64 | [PowerToysUserSetup-0.70.1-arm64.exe][ptUserArm64] | 5155EA186230876EF1DA6F49DC33E40D552B2BFFA0E03F66FBA71FBEB8713594 |
|
||||
| Machine wide - x64 | [PowerToysSetup-0.70.1-x64.exe][ptMachineX64] | 1BE4760558765EF363E12126282F1E3340A8ADFF657C5C51714F7E096F86EE50 |
|
||||
| Machine wide - ARM64 | [PowerToysSetup-0.70.1-arm64.exe][ptMachineArm64] | 9F267B7AD91E5FAE86ED5050A08A24756CE3EA9875FFCFDE195F1F4F299F0933 |
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
@@ -82,113 +90,117 @@ For guidance on developing for PowerToys, please read the [developer docs](/doc/
|
||||
|
||||
Our [prioritized roadmap][roadmap] of features and utilities that the core team is focusing on.
|
||||
|
||||
### 0.69 - March 2023 Update
|
||||
### 0.70 - May 2023 Update
|
||||
|
||||
In this release, we focused on releasing new features, stability and improvements. Early notice for v0.70, we will be releasing it later in May 2023.
|
||||
In this release, we focused on releasing new features, stability and improvements.
|
||||
|
||||
**Highlights**
|
||||
|
||||
- New utility: Registry Preview is a utility to visualize and edit Windows Registry files. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Support per-user scope installation.
|
||||
- Awake: Quality-of-life improvements and introduced keeping system awake until expiration time and date. Thanks [@dend](https://github.com/dend)!
|
||||
- PowerToys Run: Fix crashing issue caused by thumbnail image loading.
|
||||
- New utility: Mouse Without Borders enables you to interact with other computers from the same keyboard and mouse and share clipboard and files between the machines. We’ve upgraded it to .NET 7 and made a few small adjustments to fit inside the PowerToys model. Thanks [@truong2d](https://github.com/truong2d) and the rest of the contributors from the Microsoft Garage!
|
||||
- New utility: Peek is a utility that shows a quick preview of files selected in File Explorer when you press a shortcut (`Ctrl`+`Space` by default). Thanks [@SamChaps](https://github.com/SamChaps)!
|
||||
- Registry preview Quality of Life improvements. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Awake Quality of Life improvements. Thanks [@dend](https://github.com/dend)!
|
||||
- Mouse Jump Quality of Life improvements. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
|
||||
### General
|
||||
|
||||
- New utility: Registry Preview. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Fix issue causing folders to not be removed on uninstall.
|
||||
- Support per-user scope installation.
|
||||
- Companies can control this using the new GPO.
|
||||
- New utility: Mouse Without Borders. Thanks [@truong2d](https://github.com/truong2d) and [other original contributors](https://github.com/microsoft/PowerToys/blob/main/COMMUNITY.md#mouse-without-borders-original-contributors)!
|
||||
- New utility: Peek. Thanks [@SamChaps](https://github.com/SamChaps)!
|
||||
- Fixed a bug causing saved settings to clear sometimes when upgrading PowerToys.
|
||||
- Font, icon and corner radius adjustments in the UI across utilities. Thanks [@Jay-o-Way](https://github.com/Jay-o-Way)!
|
||||
|
||||
### Awake
|
||||
|
||||
- Quality-of-life improvements and introduced keeping system awake until expiration time and date. Thanks [@dend](https://github.com/dend)!
|
||||
|
||||
### Color Picker
|
||||
|
||||
- Fix issue sampling timing and grid issue causing Color Picker to sample the color of its own grid. Thanks [@IHorvalds](https://github.com/IHorvalds)!
|
||||
- Update to command line output to match the arguments. Thanks [@rpr69](https://github.com/rpr69) for creating a PR to help fix this.
|
||||
- Fix crash happening when setting an expiration date on time zones with a negative offset relative to UTC (This was a hotfix for 0.69).
|
||||
- Fix missing logging file when installing (This was a hotfix for 0.69).
|
||||
- Upgraded Awake to a new version, with Quality of Life improvements and fixing many issues regarding Awake not resetting or not keeping the computer awake when expected. Thanks [@dend](https://github.com/dend)!
|
||||
|
||||
### FancyZones
|
||||
|
||||
- Fix window cycling on multiple monitors issue.
|
||||
- Fixed accessibility issues on the Editor.
|
||||
|
||||
### File Locksmith
|
||||
|
||||
- Add context menu icon. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Fixed tooltips having a transparent background (This was a hotfix for 0.69).
|
||||
|
||||
### Mouse Utils
|
||||
### File Explorer add-ons
|
||||
|
||||
- Mouse Jump - Simulate mouse input event on mouse jump in addition to cursor move.
|
||||
- Mouse Jump - Improve performance of screenshot generation. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Add a Setting to select a background for the SVG Preview. Thanks [@zanseb](https://github.com/zanseb)!
|
||||
|
||||
### Paste as Plain Text
|
||||
### Installer
|
||||
|
||||
- Support Ctrl+V as activation shortcut. (This was a hotfix for 0.67)
|
||||
- Repress modifier keys after plain paste. (This was a hotfix for 0.67) Thanks [@UnderKoen](https://github.com/UnderKoen)!
|
||||
- Set default shortcut to Ctrl+Win+Alt+V. (This was a hotfix for 0.67)
|
||||
- Update icons. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
- Added more utilities to terminate when installing to help prevent files that sometimes are leftover from uninstall.
|
||||
|
||||
### PowerRename
|
||||
### Keyboard Manager
|
||||
|
||||
- Show PowerRename in directory background context menu.
|
||||
- Fix the crash on clicking Select/UnselectAll checkbox while showing only files to be renamed.
|
||||
- Improve performance on populating Renamed items when many items are being renamed.
|
||||
- Fixed an issue causing mapping to media keys to type additional characters.
|
||||
|
||||
### Measure Tool
|
||||
|
||||
- Created a setting to specify the default measure tool. Thanks [@zanseb](https://github.com/zanseb)!
|
||||
|
||||
### Mouse Jump
|
||||
|
||||
- Reduced dependency on WinForms utility classes. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Improved popup responsiveness. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Added a setting to set a custom sized window. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
- Added some shortcuts for screen navigation. Thanks [@mikeclayton](https://github.com/mikeclayton)!
|
||||
|
||||
### Peek
|
||||
- New utility: Peek. Thanks [@SamChaps](https://github.com/SamChaps), who drove the effort! Many thanks for all the contributors who made it possible: [@danielchau](https://github.com/danielchau), [@estebanm123](https://github.com/estebanm123), [@Joanna-Zhou](https://github.com/Joanna-Zhou), [@jth-ms](https://github.com/jth-ms), [@miksalmon](https://github.com/miksalmon), [@niels9001](https://github.com/niels9001), [@RobsonPontin](https://github.com/RobsonPontin), [@sujessie](https://github.com/sujessie), and [@Sytta](https://github.com/Sytta)!
|
||||
|
||||
### PowerToys Run
|
||||
|
||||
- Add setting to disable thumbnails generation for files. (This was a hotfix for 0.67)
|
||||
- Calculator plugin - handle implied multiplication expressions. Thanks [@jjavierdguezas](https://github.com/jjavierdguezas)!
|
||||
- Fix Calculator plugin unit tests to respect decimal separator locale. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Fix crashing caused by thumbnail image loading.
|
||||
- Date & Time plugin - Add filename-compatible date & time format. Thanks [@Picazsoo](https://github.com/Picazsoo)!
|
||||
- Improved the error message shown on plugin loading error. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Add a plugin to start other PowerToys. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Added code to the Shell plugin to use Windows Terminal. Currently accessible only through manipulating the settings file directly. Thanks [@phoenix172](https://github.com/phoenix172)!
|
||||
|
||||
### Quick Accent
|
||||
|
||||
- Fix existing and add missing Hebrew and Pinyin characters. Thanks [@stevenlele](https://github.com/stevenlele)!
|
||||
- Added a missing character to the Welsh language.
|
||||
|
||||
### Registry Preview
|
||||
|
||||
- Added a new utility: Registry Preview.
|
||||
- Thanks [@htcfreek](https://github.com/htcfreek)! for the help shipping this utility!
|
||||
- Thanks [@niels9001](https://github.com/niels9001) for the help on the UI!
|
||||
|
||||
### Video Conference Mute
|
||||
|
||||
- Add toolbar DPI scaling support.
|
||||
- Fix selecting overlay image when Settings app is running elevated.
|
||||
- Add push-to-talk (and push-to-reverse) feature. Thanks [@pajawojciech](https://github.com/pajawojciech)!
|
||||
- Specify minimum size / position values for the UI (This was a hotfix for 0.69). Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Fixes in the UI command bar (This was a hotfix for 0.69). Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Fix crash on opening a file picker when running elevated (This was a hotfix for 0.69). Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Fixed tooltips having a transparent background (This was a hotfix for 0.69).
|
||||
- Fixed a file size limit typo. Thanks [@idma88](https://github.com/idma88)!
|
||||
- Improve hexadecimal value parsing. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Added a button to open the Registry Editor at a selected key. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Improve key and value parsing. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Better theme support for caption bar. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
- Fix an issue handling empty DWORD and QWORD values. Thanks [@randyrants](https://github.com/randyrants)!
|
||||
|
||||
### Settings
|
||||
|
||||
- Fix Experiment bitmap icon rendering on theme change and bump CommunityToolkit.Labs.WinUI.SettingsControls package version. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
- Video Conference Mute page improvements. Thanks [@Jay-o-Way](https://github.com/Jay-o-Way)!
|
||||
- Add warning that PowerToys Run might get no focus if "Use centralized keyboard hook" settings is enabled. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Fix ShortcutControl issues related to keyboard input focus, theme change and missing error badge when invalid key is pressed. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Add warning when Ctrl+V and Ctrl+Shift+V is used as an activation shortcut for Paste as Plain Text. Thanks [@htcfreek](https://github.com/htcfreek)!
|
||||
- Update the What's New screen to hide the installer hashes in the new format (This was a hotfix for 0.69).
|
||||
- Fix crashes happening when using the Shortcut Control (This was a hotfix for 0.69).
|
||||
- The Settings window now has a minimum width. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
- Prevent a second Settings instance from being opened on upgrade.
|
||||
- Fix accessibility issues on many pages. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update CONTRIBUTING.md with information about localization issues. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Remove localization from URLs. Thanks [@Jay-o-Way](https://github.com/Jay-o-Way)!
|
||||
- Add dev docs for tools. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Fix a dead link in documentation that was pointing to the wrong settings specification. Thanks [@zanseb](https://github.com/zanseb)!
|
||||
- Added some missing contributors to COMMUNITY.md
|
||||
|
||||
### Development
|
||||
|
||||
- Ignore spellcheck for MouseJumpUI/MainForm.resx file. (This was a hotfix for 0.67)
|
||||
- Optimize versionAndSignCheck.ps1 script. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Upgraded NetAnalyzers to 7.0.1. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
|
||||
- Move all DLL imports in Settings project to NativeMethods.cs file.
|
||||
- Fix FancyZones tools build issues. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Centralize Logger used in C# projects. Thanks [@Aaron-Junker](https://github.com/Aaron-Junker)!
|
||||
- Add missing project references. Thanks [@ACGNnsj](https://github.com/ACGNnsj)!
|
||||
- Fixed the CI release pipelines hash generation (This was a hotfix for 0.69).
|
||||
- Added per-user installers to the winget package submission script.
|
||||
- Upgraded the Community Toolkit Labs dependency. Thanks [@niels9001](https://github.com/niels9001)!
|
||||
- Fixed building with Visual Studio 17.6. Thanks [@snickler](https://github.com/snickler)!
|
||||
- Upgraded the WebView 2 dependency.
|
||||
- Upgraded the WinAppSDK dependency to 1.3.1.
|
||||
- Fixed a typo preventing the clean up script to run. Thanks [@Sajad-Lx](https://github.com/Sajad-Lx)!
|
||||
- Fixed encoding on a test file to fix running tests in some configurations. Thanks [@VisualBasist](https://github.com/VisualBasist)!
|
||||
- Made the GPO release assets come named with a version in the build CI output.
|
||||
|
||||
#### What is being planned for version 0.70
|
||||
#### What is being planned for version 0.71
|
||||
|
||||
For [v0.70][github-next-release-work], we'll work on below:
|
||||
For [v0.71][github-next-release-work], we'll work on below:
|
||||
|
||||
- New utility: [PowerToys Peek](https://github.com/microsoft/PowerToys/issues/80)
|
||||
- Stability / bug fixes
|
||||
- Adjustments on feedback / stability / bug fixes
|
||||
|
||||
## PowerToys Community
|
||||
|
||||
@@ -215,5 +227,5 @@ The application logs basic telemetry. Our Telemetry Data page (Coming Soon) has
|
||||
[usingPowerToys-docs-link]: https://aka.ms/powertoys-docs
|
||||
|
||||
<!-- items that need to be updated release to release -->
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F43
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F42
|
||||
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F44
|
||||
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aopen+is%3Aissue+project%3Amicrosoft%2FPowerToys%2F43
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\Drive\ShellEx\ContextMenuHandlers\FileLocksmithExt">
|
||||
<RegistryValue Type="string" Value="{84D68575-E186-46AD-B0CB-BAEB45EE29C0}"/>
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="SOFTWARE\Classes\Directory\background\ShellEx\ContextMenuHandlers\FileLocksmithExt">
|
||||
<RegistryValue Type="string" Value="{84D68575-E186-46AD-B0CB-BAEB45EE29C0}"/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
</Custom>
|
||||
|
||||
<Custom Action="UninstallServicesTask" After="InstallFinalize">
|
||||
Installed AND (REMOVE="ALL")
|
||||
Installed AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
|
||||
</Custom>
|
||||
<!-- TODO: Use to activate embedded MSIX -->
|
||||
<!--<Custom Action="UninstallEmbeddedMSIXTask" After="InstallFinalize">
|
||||
|
||||
@@ -383,7 +383,16 @@
|
||||
<RegistryValue Type="string" Name="Launcher_History_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Id="Launcher_History_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)modules\launcher\Plugins\History\$(var.Language)\Microsoft.PowerToys.Run.Plugin.History.resources.dll" />
|
||||
</Component>
|
||||
</Component>
|
||||
<Component
|
||||
Id="Launcher_PowerToys_$(var.IdSafeLanguage)_Component"
|
||||
Directory="Resource$(var.IdSafeLanguage)PowerToysPluginFolder"
|
||||
Guid="$(var.CompGUIDPrefix)1C">
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="Launcher_PowerToys_$(var.IdSafeLanguage)_Component" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<File Id="Launcher_PowerToys_$(var.IdSafeLanguage)_File" Source="$(var.BinDir)modules\launcher\Plugins\PowerToys\$(var.Language)\Microsoft.PowerToys.Run.Plugin.PowerToys.resources.dll" />
|
||||
</Component>
|
||||
<?undef IdSafeLanguage?>
|
||||
<?undef CompGUIDPrefix?>
|
||||
<?endforeach?>
|
||||
|
||||
@@ -106,14 +106,6 @@
|
||||
<?define PowerToysImagesCmpFilesPath=$(var.BinDir)modules\launcher\Plugins\PowerToys\Images\?>
|
||||
|
||||
<Fragment>
|
||||
<Component Id="launcherShortcutComponent" Directory="LauncherInstallFolder" >
|
||||
<!-- Toast Notification AUMID -->
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="SOFTWARE\Classes\AppUserModelId\PowerToysRun">
|
||||
<RegistryValue Type="string" Name="DisplayName" Value="PowerToys Run" />
|
||||
<RegistryValue Type="string" Name="IconUri" Value="[LauncherImagesFolder]RunAsset.ico" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
|
||||
<DirectoryRef Id="LauncherInstallFolder" FileSource="$(var.launcherFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--launcherFiles_Component_Def-->
|
||||
@@ -374,7 +366,6 @@
|
||||
<RemoveFolder Id="RemoveFolderPowerToysPluginFolder" Directory="PowerToysPluginFolder" On="uninstall"/>
|
||||
<RemoveFolder Id="RemoveFolderPowerToysImagesFolder" Directory="PowerToysImagesFolder" On="uninstall"/>
|
||||
</Component>
|
||||
<ComponentRef Id="launcherShortcutComponent" />
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
||||
|
||||
@@ -198,6 +198,11 @@ Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName WinTermImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\WindowsTerminal\Images"""
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinTermCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""WinTermImagesCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
|
||||
###PowerToys
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\PowerToys\Microsoft.PowerToys.Run.Plugin.PowerToys.deps.json"" -fileListName PowerToysCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1"
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName PowerToysImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\modules\launcher\Plugins\PowerToys\Images"""
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""PowerToysCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
|
||||
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""PowerToysImagesCmpFiles"" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot"
|
||||
## Plugins
|
||||
|
||||
#ShortcutGuide
|
||||
|
||||
@@ -50,7 +50,7 @@ if ($isWinAppSdkProj -eq $True) {
|
||||
|
||||
$fileExclusionList = @("*Test*", "*.pdb", "*.lastcodeanalysissucceeded", "createdump.exe") + $interopFilesList + $winAppSDKfilesList
|
||||
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*png", "*gif", "*ico", "*cur", "*svg", "index.html", "reg.js", "monacoSpecialLanguages.js", "resources.pri")
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*png", "*gif", "*ico", "*cur", "*svg", "index.html", "reg.js", "gitignore.js", "monacoSpecialLanguages.js", "resources.pri")
|
||||
|
||||
$dllsToIgnore = @("System.CodeDom.dll", "WindowsBase.dll")
|
||||
|
||||
|
||||
@@ -123,6 +123,8 @@ UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
|
||||
changeSet.unApply();
|
||||
}
|
||||
|
||||
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
|
||||
|
||||
ExitOnFailure(hr, "Failed to extract msix");
|
||||
|
||||
LExit:
|
||||
@@ -387,6 +389,8 @@ UINT __stdcall CreateScheduledTaskCA(MSIHANDLE hInstall)
|
||||
ExitOnFailure(hr, "Cannot put_ExecutionTimeLimit setting info: %x", hr);
|
||||
hr = pSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
|
||||
ExitOnFailure(hr, "Cannot put_DisallowStartIfOnBatteries setting info: %x", hr);
|
||||
hr = pSettings->put_Priority(4);
|
||||
ExitOnFailure(hr, "Cannot put_Priority setting info : %x", hr);
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Get the trigger collection to insert the logon trigger.
|
||||
@@ -1466,9 +1470,9 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
|
||||
L"PowerToys.PdfPreviewHandler.exe",
|
||||
L"PowerToys.SvgPreviewHandler.exe",
|
||||
L"PowerToys.Peek.UI.exe",
|
||||
L"PowerToys.MouseWithoutBorders.exe"
|
||||
L"PowerToys.MouseWithoutBordersHelper.exe"
|
||||
L"PowerToys.MouseWithoutBordersService.exe"
|
||||
L"PowerToys.MouseWithoutBorders.exe",
|
||||
L"PowerToys.MouseWithoutBordersHelper.exe",
|
||||
L"PowerToys.MouseWithoutBordersService.exe",
|
||||
L"PowerToys.exe",
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <strsafe.h>
|
||||
#include <msiquery.h>
|
||||
#include <Msi.h>
|
||||
#include <shlobj_core.h>
|
||||
|
||||
// WiX Header Files:
|
||||
#include <wcautil.h>
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Common.UI
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
var eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, eventName);
|
||||
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
|
||||
while (true)
|
||||
{
|
||||
if (WaitHandle.WaitAny(new WaitHandle[] { cancel.WaitHandle, eventHandle }) == 1)
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
<None Update="customLanguages\reg.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="customLanguages\gitignore.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="index.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
13
src/common/FilePreviewCommon/customLanguages/gitignore.js
Normal file
13
src/common/FilePreviewCommon/customLanguages/gitignore.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export function gitignoreDefinition() {
|
||||
return {
|
||||
defaultToken: 'invalid',
|
||||
|
||||
tokenizer: {
|
||||
root: [
|
||||
[/^#.*$/, 'comment'],
|
||||
[/^\s*!.*/, 'invalid'],
|
||||
[/^\s*[^#]+/, "tag"]
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -95,9 +95,9 @@
|
||||
// A rule to evaluate on top of the precondition in order to dispatch the keybindings.
|
||||
keybindingContext: null,
|
||||
|
||||
contextMenuGroupId: 'navigation',
|
||||
contextMenuGroupId: 'cutcopypaste',
|
||||
|
||||
contextMenuOrder: 1.5,
|
||||
contextMenuOrder: 100,
|
||||
|
||||
// Method that will be executed when the action is triggered.
|
||||
// @param editor The editor instance is passed in as a convenience
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@
|
||||
#include "dwmapi.h"
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#pragma comment (lib,"Dwmapi.lib")
|
||||
|
||||
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||
#define HKEY_WINDOWS_THEME L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"
|
||||
|
||||
@@ -49,7 +49,6 @@ namespace // Strings in this namespace should not be localized
|
||||
constexpr std::wstring_view TASK_NAME = L"PowerToysBackgroundNotificationsHandler";
|
||||
constexpr std::wstring_view TASK_ENTRYPOINT = L"BackgroundActivator.BackgroundHandler";
|
||||
constexpr std::wstring_view PACKAGED_APPLICATION_ID = L"PowerToys";
|
||||
constexpr std::wstring_view APPIDS_REGISTRY = LR"(Software\Classes\AppUserModelId\)";
|
||||
|
||||
std::wstring APPLICATION_ID = L"Microsoft.PowerToysWin32";
|
||||
constexpr std::wstring_view DEFAULT_TOAST_GROUP = L"PowerToysToastTag";
|
||||
@@ -132,68 +131,6 @@ void notifications::run_desktop_app_activator_loop()
|
||||
CoRevokeClassObject(token);
|
||||
}
|
||||
|
||||
bool notifications::register_application_id(const std::wstring_view appName, const std::wstring_view iconPath)
|
||||
{
|
||||
std::wstring aumidPath{ APPIDS_REGISTRY };
|
||||
aumidPath += APPLICATION_ID;
|
||||
wil::unique_hkey aumidKey;
|
||||
if (FAILED(RegCreateKeyW(HKEY_CURRENT_USER, aumidPath.c_str(), &aumidKey)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (FAILED(RegSetKeyValueW(aumidKey.get(),
|
||||
nullptr,
|
||||
L"DisplayName",
|
||||
REG_SZ,
|
||||
appName.data(),
|
||||
static_cast<DWORD>((size(appName) + 1) * sizeof(wchar_t)))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(RegSetKeyValueW(aumidKey.get(),
|
||||
nullptr,
|
||||
L"IconUri",
|
||||
REG_SZ,
|
||||
iconPath.data(),
|
||||
static_cast<DWORD>((size(iconPath) + 1) * sizeof(wchar_t)))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::wstring_view iconColor = L"FFDDDDDD";
|
||||
if (FAILED(RegSetKeyValueW(aumidKey.get(),
|
||||
nullptr,
|
||||
L"IconBackgroundColor",
|
||||
REG_SZ,
|
||||
iconColor.data(),
|
||||
static_cast<DWORD>((size(iconColor) + 1) * sizeof(wchar_t)))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void notifications::unregister_application_id()
|
||||
{
|
||||
std::wstring aumidPath{ APPIDS_REGISTRY };
|
||||
aumidPath += APPLICATION_ID;
|
||||
wil::unique_hkey registryRoot;
|
||||
RegOpenKeyW(HKEY_CURRENT_USER, aumidPath.c_str(), ®istryRoot);
|
||||
if (!registryRoot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
RegDeleteTreeW(registryRoot.get(), nullptr);
|
||||
registryRoot.reset();
|
||||
RegOpenKeyW(HKEY_CURRENT_USER, APPIDS_REGISTRY.data(), ®istryRoot);
|
||||
if (!registryRoot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
RegDeleteKeyW(registryRoot.get(), APPLICATION_ID.data());
|
||||
}
|
||||
|
||||
void notifications::override_application_id(const std::wstring_view appID)
|
||||
{
|
||||
APPLICATION_ID = appID;
|
||||
|
||||
@@ -14,9 +14,6 @@ namespace notifications
|
||||
void override_application_id(const std::wstring_view appID);
|
||||
void run_desktop_app_activator_loop();
|
||||
|
||||
bool register_application_id(const std::wstring_view appName, const std::wstring_view iconPath);
|
||||
void unregister_application_id();
|
||||
|
||||
struct snooze_duration
|
||||
{
|
||||
std::wstring label;
|
||||
|
||||
@@ -12,7 +12,8 @@ struct UpdateState
|
||||
upToDate = 0,
|
||||
errorDownloading = 1,
|
||||
readyToDownload = 2,
|
||||
readyToInstall = 3
|
||||
readyToInstall = 3,
|
||||
networkError = 4
|
||||
} state = upToDate;
|
||||
std::wstring releasePageUrl;
|
||||
std::optional<std::time_t> githubUpdateLastCheckedDate;
|
||||
|
||||
@@ -353,7 +353,7 @@ struct ProcessInfo
|
||||
DWORD processID = {};
|
||||
};
|
||||
|
||||
inline std::optional<ProcessInfo> RunNonElevatedFailsafe(const std::wstring& file, const std::wstring& params, const std::wstring& working_dir)
|
||||
inline std::optional<ProcessInfo> RunNonElevatedFailsafe(const std::wstring& file, const std::wstring& params, const std::wstring& working_dir, DWORD handleAccess = 0)
|
||||
{
|
||||
bool launched = RunNonElevatedEx(file, params, working_dir);
|
||||
if (!launched)
|
||||
@@ -373,7 +373,7 @@ inline std::optional<ProcessInfo> RunNonElevatedFailsafe(const std::wstring& fil
|
||||
}
|
||||
}
|
||||
|
||||
auto handles = getProcessHandlesByName(std::filesystem::path{ file }.filename().wstring(), PROCESS_QUERY_INFORMATION | SYNCHRONIZE);
|
||||
auto handles = getProcessHandlesByName(std::filesystem::path{ file }.filename().wstring(), PROCESS_QUERY_INFORMATION | SYNCHRONIZE | handleAccess );
|
||||
|
||||
if (handles.empty())
|
||||
return std::nullopt;
|
||||
|
||||
@@ -30,3 +30,36 @@ inline bool find_folder_in_path(const std::wstring& where, const std::vector<std
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define MAX_TITLE_LENGTH 255
|
||||
inline bool check_excluded_app_with_title(const HWND& hwnd, std::wstring& processPath, const std::vector<std::wstring>& excludedApps)
|
||||
{
|
||||
WCHAR title[MAX_TITLE_LENGTH];
|
||||
int len = GetWindowTextW(hwnd, title, MAX_TITLE_LENGTH);
|
||||
if (len <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring titleStr(title);
|
||||
auto lastBackslashPos = processPath.find_last_of(L'\\');
|
||||
if (lastBackslashPos != std::wstring::npos)
|
||||
{
|
||||
processPath = processPath.substr(0, lastBackslashPos + 1); // retain up to the last backslash
|
||||
processPath.append(titleStr); // append the title
|
||||
}
|
||||
CharUpperBuffW(processPath.data(), static_cast<DWORD>(processPath.length()));
|
||||
return find_app_name_in_path(processPath, excludedApps);
|
||||
}
|
||||
|
||||
inline bool check_excluded_app(const HWND& hwnd, std::wstring& processPath, const std::vector<std::wstring>& excludedApps)
|
||||
{
|
||||
bool res = find_app_name_in_path(processPath, excludedApps);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
res = check_excluded_app_with_title(hwnd, processPath, excludedApps);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -192,6 +192,28 @@ inline registry::ChangeSet getStlThumbnailHandlerChangeSet(const std::wstring in
|
||||
NonLocalizable::ExtSTL);
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getRegistryPreviewSetDefaultAppChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
|
||||
|
||||
using vec_t = std::vector<registry::ValueChange>;
|
||||
vec_t changes;
|
||||
|
||||
std::wstring appName = L"Registry Preview";
|
||||
std::wstring fullAppName = L"PowerToys.RegistryPreview";
|
||||
std::wstring registryKeyPrefix = L"Software\\Classes\\";
|
||||
|
||||
std::wstring appPath = installationDir + L"\\modules\\RegistryPreview\\PowerToys.RegistryPreview.exe";
|
||||
std::wstring command = appPath + L" \"----ms-protocol:ms-encodedlaunch:App?ContractId=Windows.File&Verb=open&File=%1\"";
|
||||
|
||||
changes.push_back({ scope, registryKeyPrefix + fullAppName + L"\\" + L"Application", L"ApplicationName", appName });
|
||||
changes.push_back({ scope, registryKeyPrefix + fullAppName + L"\\" + L"DefaultIcon", std::nullopt, appPath });
|
||||
changes.push_back({ scope, registryKeyPrefix + fullAppName + L"\\" + L"shell\\open\\command", std::nullopt, command });
|
||||
changes.push_back({ scope, registryKeyPrefix + L".reg\\OpenWithProgIDs", fullAppName, L"" });
|
||||
|
||||
return { changes };
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getRegistryPreviewChangeSet(const std::wstring installationDir,const bool perUser)
|
||||
{
|
||||
const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
|
||||
@@ -235,5 +257,6 @@ inline std::vector<registry::ChangeSet> getAllModulesChangeSets(const std::wstri
|
||||
getPdfThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getStlThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getRegistryPreviewChangeSet(installationDir, PER_USER) };
|
||||
getRegistryPreviewChangeSet(installationDir, PER_USER),
|
||||
getRegistryPreviewSetDefaultAppChangeSet(installationDir, PER_USER) };
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ namespace constants::nonlocalizable
|
||||
// JSON key used to store whether the module is enabled
|
||||
constexpr WCHAR JsonKeyEnabled[] = L"Enabled";
|
||||
|
||||
// JSON key used to store extended menu enabled
|
||||
constexpr WCHAR JsonKeyShowInExtendedContextMenu[] = L"showInExtendedContextMenu";
|
||||
|
||||
// Path of the JSON file used to store settings
|
||||
constexpr WCHAR DataFilePath[] = L"\\file-locksmith-settings.json";
|
||||
|
||||
|
||||
@@ -69,14 +69,25 @@ IFACEMETHODIMP ExplorerCommand::GetCanonicalName(GUID* pguidCommandName)
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::GetState(IShellItemArray* psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE* pCmdState)
|
||||
{
|
||||
if (globals::enabled)
|
||||
{
|
||||
*pCmdState = ECS_ENABLED;
|
||||
}
|
||||
else
|
||||
if (!globals::enabled)
|
||||
{
|
||||
*pCmdState = ECS_HIDDEN;
|
||||
}
|
||||
|
||||
if (FileLocksmithSettingsInstance().GetShowInExtendedContextMenu())
|
||||
{
|
||||
*pCmdState = ECS_HIDDEN;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// When right clicking directory background, selection is empty.
|
||||
if (nullptr == psiItemArray)
|
||||
{
|
||||
*pCmdState = ECS_HIDDEN;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*pCmdState = ECS_ENABLED;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -101,8 +112,16 @@ IFACEMETHODIMP ExplorerCommand::EnumSubCommands(IEnumExplorerCommand** ppEnum)
|
||||
|
||||
IFACEMETHODIMP ExplorerCommand::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID)
|
||||
{
|
||||
m_data_obj = pdtobj;
|
||||
m_data_obj->AddRef();
|
||||
if (!FileLocksmithSettingsInstance().GetEnabled())
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (pdtobj)
|
||||
{
|
||||
m_data_obj = pdtobj;
|
||||
m_data_obj->AddRef();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -116,6 +135,11 @@ IFACEMETHODIMP ExplorerCommand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UI
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (FileLocksmithSettingsInstance().GetShowInExtendedContextMenu() && !(uFlags & CMF_EXTENDEDVERBS))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr = E_UNEXPECTED;
|
||||
if (m_data_obj && !(uFlags & (CMF_DEFAULTONLY | CMF_VERBSONLY | CMF_OPTIMIZEFORINVOKE)))
|
||||
{
|
||||
|
||||
@@ -62,7 +62,8 @@ public:
|
||||
PowerToysSettings::PowerToyValues values =
|
||||
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||
|
||||
// Currently, there are no settings, so we don't do anything.
|
||||
toggle_extended_only(values.get_bool_value(L"bool_show_extended_menu").value());
|
||||
save_settings();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@@ -89,6 +90,18 @@ public:
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
virtual void toggle_extended_only(bool extended_only)
|
||||
{
|
||||
Logger::info(L"File Locksmith toggle extended only");
|
||||
m_extended_only = extended_only;
|
||||
save_settings();
|
||||
}
|
||||
|
||||
virtual bool is_extended_only()
|
||||
{
|
||||
return m_extended_only;
|
||||
}
|
||||
|
||||
virtual void destroy() override
|
||||
{
|
||||
delete this;
|
||||
@@ -96,10 +109,12 @@ public:
|
||||
|
||||
private:
|
||||
bool m_enabled;
|
||||
bool m_extended_only;
|
||||
|
||||
void init_settings()
|
||||
{
|
||||
m_enabled = FileLocksmithSettingsInstance().GetEnabled();
|
||||
m_extended_only = FileLocksmithSettingsInstance().GetShowInExtendedContextMenu();
|
||||
Trace::EnableFileLocksmith(m_enabled);
|
||||
}
|
||||
|
||||
@@ -107,6 +122,8 @@ private:
|
||||
{
|
||||
auto& settings = FileLocksmithSettingsInstance();
|
||||
settings.SetEnabled(m_enabled);
|
||||
settings.SetExtendedContextMenuOnly(m_extended_only);
|
||||
|
||||
settings.Save();
|
||||
Trace::EnableFileLocksmith(m_enabled);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ void FileLocksmithSettings::Save()
|
||||
json::JsonObject jsonData;
|
||||
|
||||
jsonData.SetNamedValue(constants::nonlocalizable::JsonKeyEnabled, json::value(settings.enabled));
|
||||
jsonData.SetNamedValue(constants::nonlocalizable::JsonKeyShowInExtendedContextMenu, json::value(settings.showInExtendedContextMenu));
|
||||
|
||||
json::to_file(jsonFilePath, jsonData);
|
||||
GetSystemTimeAsFileTime(&lastLoadedTime);
|
||||
@@ -70,6 +71,11 @@ void FileLocksmithSettings::ParseJson()
|
||||
{
|
||||
settings.enabled = jsonSettings.GetNamedBoolean(constants::nonlocalizable::JsonKeyEnabled);
|
||||
}
|
||||
|
||||
if (json::has(jsonSettings, constants::nonlocalizable::JsonKeyShowInExtendedContextMenu, json::JsonValueType::Boolean))
|
||||
{
|
||||
settings.showInExtendedContextMenu = jsonSettings.GetNamedBoolean(constants::nonlocalizable::JsonKeyShowInExtendedContextMenu);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
|
||||
@@ -25,6 +25,16 @@ public:
|
||||
Save();
|
||||
}
|
||||
|
||||
inline bool GetShowInExtendedContextMenu() const
|
||||
{
|
||||
return settings.showInExtendedContextMenu;
|
||||
}
|
||||
|
||||
inline void SetExtendedContextMenuOnly(bool extendedOnly)
|
||||
{
|
||||
settings.showInExtendedContextMenu = extendedOnly;
|
||||
}
|
||||
|
||||
void Save();
|
||||
void Load();
|
||||
|
||||
@@ -32,6 +42,7 @@ private:
|
||||
struct Settings
|
||||
{
|
||||
bool enabled{ true };
|
||||
bool showInExtendedContextMenu{ false };
|
||||
};
|
||||
|
||||
void Reload();
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
x:Class="FileLocksmithUI.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
|
||||
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
|
||||
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
|
||||
xmlns:converters1="using:PowerToys.FileLocksmithUI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:interop="using:FileLocksmith.Interop"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="using:PowerToys.FileLocksmithUI.Views"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
@@ -18,9 +13,9 @@
|
||||
IsShownInSwitchers="True"
|
||||
IsTitleBarVisible="True"
|
||||
mc:Ignorable="d">
|
||||
<winuiex:WindowEx.Backdrop>
|
||||
<winuiex:MicaSystemBackdrop />
|
||||
</winuiex:WindowEx.Backdrop>
|
||||
<Window.SystemBackdrop>
|
||||
<MicaBackdrop />
|
||||
</Window.SystemBackdrop>
|
||||
<Grid>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
|
||||
@@ -74,6 +74,8 @@ namespace Hosts.Tests
|
||||
[DataRow("\t\thost\t\t10.1.1.1")]
|
||||
[DataRow(" host 10.1.1.1")]
|
||||
[DataRow("host 10.1.1.1")]
|
||||
[DataRow("# comment 10.1.1.1 host # comment")]
|
||||
[DataRow("10.1.1.1 host01 host02 host03 host04 host05 host06 host07 host08 host09 host10")]
|
||||
public void Not_Valid_Entry(string line)
|
||||
{
|
||||
var entry = new Entry(0, line);
|
||||
|
||||
@@ -69,9 +69,10 @@ namespace Hosts.Tests
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var (_, entries) = await service.ReadAsync();
|
||||
var data = await service.ReadAsync();
|
||||
var entries = data.Entries.ToList();
|
||||
entries.Add(new Entry(0, "10.1.1.30", "host30 host30.local", "new entry", false));
|
||||
await service.WriteAsync(string.Empty, entries);
|
||||
await service.WriteAsync(data.AdditionalLines, entries);
|
||||
|
||||
var result = fileSystem.GetFile(service.HostsFilePath);
|
||||
Assert.AreEqual(result.TextContents, contentResult);
|
||||
@@ -94,9 +95,10 @@ namespace Hosts.Tests
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var (_, entries) = await service.ReadAsync();
|
||||
var data = await service.ReadAsync();
|
||||
var entries = data.Entries.ToList();
|
||||
entries.RemoveAt(0);
|
||||
await service.WriteAsync(string.Empty, entries);
|
||||
await service.WriteAsync(data.AdditionalLines, entries);
|
||||
|
||||
var result = fileSystem.GetFile(service.HostsFilePath);
|
||||
Assert.AreEqual(result.TextContents, contentResult);
|
||||
@@ -120,13 +122,13 @@ namespace Hosts.Tests
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var (_, entries) = await service.ReadAsync();
|
||||
var entry = entries[0];
|
||||
var data = await service.ReadAsync();
|
||||
var entry = data.Entries[0];
|
||||
entry.Address = "10.1.1.10";
|
||||
entry.Hosts = "host host.local host1.local";
|
||||
entry.Comment = "updated comment";
|
||||
entry.Active = false;
|
||||
await service.WriteAsync(string.Empty, entries);
|
||||
await service.WriteAsync(data.AdditionalLines, data.Entries);
|
||||
|
||||
var result = fileSystem.GetFile(service.HostsFilePath);
|
||||
Assert.AreEqual(result.TextContents, contentResult);
|
||||
@@ -168,12 +170,12 @@ namespace Hosts.Tests
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
userSettings.Setup(m => m.AdditionalLinesPosition).Returns(AdditionalLinesPosition.Top);
|
||||
userSettings.Setup(m => m.AdditionalLinesPosition).Returns(HostsAdditionalLinesPosition.Top);
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var (additionalLines, entries) = await service.ReadAsync();
|
||||
await service.WriteAsync(additionalLines, entries);
|
||||
var data = await service.ReadAsync();
|
||||
await service.WriteAsync(data.AdditionalLines, data.Entries);
|
||||
|
||||
var result = fileSystem.GetFile(service.HostsFilePath);
|
||||
Assert.AreEqual(result.TextContents, contentResult);
|
||||
@@ -200,13 +202,38 @@ namespace Hosts.Tests
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
userSettings.Setup(m => m.AdditionalLinesPosition).Returns(AdditionalLinesPosition.Bottom);
|
||||
userSettings.Setup(m => m.AdditionalLinesPosition).Returns(HostsAdditionalLinesPosition.Bottom);
|
||||
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var (additionalLines, entries) = await service.ReadAsync();
|
||||
await service.WriteAsync(additionalLines, entries);
|
||||
var data = await service.ReadAsync();
|
||||
await service.WriteAsync(data.AdditionalLines, data.Entries);
|
||||
|
||||
var result = fileSystem.GetFile(service.HostsFilePath);
|
||||
Assert.AreEqual(result.TextContents, contentResult);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LongHosts_Splitted()
|
||||
{
|
||||
var content =
|
||||
@"10.1.1.1 host01 host02 host03 host04 host05 host06 host07 host08 host09 host10 host11 host12 host13 host14 host15 host16 host17 host18 host19 # comment
|
||||
";
|
||||
|
||||
var contentResult =
|
||||
@"10.1.1.1 host01 host02 host03 host04 host05 host06 host07 host08 host09 # comment
|
||||
10.1.1.1 host10 host11 host12 host13 host14 host15 host16 host17 host18 # comment
|
||||
10.1.1.1 host19 # comment
|
||||
";
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var data = await service.ReadAsync();
|
||||
await service.WriteAsync(data.AdditionalLines, data.Entries);
|
||||
|
||||
var result = fileSystem.GetFile(service.HostsFilePath);
|
||||
Assert.AreEqual(result.TextContents, contentResult);
|
||||
|
||||
14
src/modules/Hosts/Hosts/Consts.cs
Normal file
14
src/modules/Hosts/Hosts/Consts.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
// 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 Hosts
|
||||
{
|
||||
public static class Consts
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum number of hosts detected by the system in a single line
|
||||
/// </summary>
|
||||
public const int MaxHostsCount = 9;
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,8 @@ namespace Hosts.Helpers
|
||||
|
||||
public event EventHandler FileChanged;
|
||||
|
||||
public Encoding Encoding => _userSettings.Encoding == HostsEncoding.Utf8 ? new UTF8Encoding(false) : new UTF8Encoding(true);
|
||||
|
||||
public HostsService(
|
||||
IFileSystem fileSystem,
|
||||
IUserSettings userSettings,
|
||||
@@ -62,17 +64,20 @@ namespace Hosts.Helpers
|
||||
return _fileSystem.File.Exists(HostsFilePath);
|
||||
}
|
||||
|
||||
public async Task<(string Unparsed, List<Entry> Entries)> ReadAsync()
|
||||
public async Task<HostsData> ReadAsync()
|
||||
{
|
||||
var entries = new List<Entry>();
|
||||
var unparsedBuilder = new StringBuilder();
|
||||
var splittedEntries = false;
|
||||
|
||||
if (!Exists())
|
||||
{
|
||||
return (unparsedBuilder.ToString(), entries);
|
||||
return new HostsData(entries, unparsedBuilder.ToString(), false);
|
||||
}
|
||||
|
||||
var lines = await _fileSystem.File.ReadAllLinesAsync(HostsFilePath);
|
||||
var lines = await _fileSystem.File.ReadAllLinesAsync(HostsFilePath, Encoding);
|
||||
|
||||
var id = 0;
|
||||
|
||||
for (var i = 0; i < lines.Length; i++)
|
||||
{
|
||||
@@ -83,11 +88,25 @@ namespace Hosts.Helpers
|
||||
continue;
|
||||
}
|
||||
|
||||
var entry = new Entry(i, line);
|
||||
var entry = new Entry(id, line);
|
||||
|
||||
if (entry.Valid)
|
||||
{
|
||||
entries.Add(entry);
|
||||
id++;
|
||||
}
|
||||
else if (entry.Validate(false))
|
||||
{
|
||||
foreach (var hostsChunk in entry.SplittedHosts.Chunk(Consts.MaxHostsCount))
|
||||
{
|
||||
var clonedEntry = entry.Clone();
|
||||
clonedEntry.Id = id;
|
||||
clonedEntry.Hosts = string.Join(' ', hostsChunk);
|
||||
entries.Add(clonedEntry);
|
||||
id++;
|
||||
}
|
||||
|
||||
splittedEntries = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -100,7 +119,7 @@ namespace Hosts.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
return (unparsedBuilder.ToString(), entries);
|
||||
return new HostsData(entries, unparsedBuilder.ToString(), splittedEntries);
|
||||
}
|
||||
|
||||
public async Task<bool> WriteAsync(string additionalLines, IEnumerable<Entry> entries)
|
||||
@@ -124,7 +143,7 @@ namespace Hosts.Helpers
|
||||
|
||||
if (!e.Valid)
|
||||
{
|
||||
lineBuilder.Append(e.GetLine());
|
||||
lineBuilder.Append(e.Line);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -153,11 +172,11 @@ namespace Hosts.Helpers
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(additionalLines))
|
||||
{
|
||||
if (_userSettings.AdditionalLinesPosition == AdditionalLinesPosition.Top)
|
||||
if (_userSettings.AdditionalLinesPosition == HostsAdditionalLinesPosition.Top)
|
||||
{
|
||||
lines.Insert(0, additionalLines);
|
||||
}
|
||||
else if (_userSettings.AdditionalLinesPosition == AdditionalLinesPosition.Bottom)
|
||||
else if (_userSettings.AdditionalLinesPosition == HostsAdditionalLinesPosition.Bottom)
|
||||
{
|
||||
lines.Add(additionalLines);
|
||||
}
|
||||
@@ -174,7 +193,7 @@ namespace Hosts.Helpers
|
||||
_backupDone = true;
|
||||
}
|
||||
|
||||
await _fileSystem.File.WriteAllLinesAsync(HostsFilePath, lines);
|
||||
await _fileSystem.File.WriteAllLinesAsync(HostsFilePath, lines, Encoding);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Hosts.Helpers
|
||||
|
||||
event EventHandler FileChanged;
|
||||
|
||||
Task<(string Unparsed, List<Entry> Entries)> ReadAsync();
|
||||
Task<HostsData> ReadAsync();
|
||||
|
||||
Task<bool> WriteAsync(string additionalLines, IEnumerable<Entry> entries);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Hosts.Helpers
|
||||
@@ -39,16 +40,23 @@ namespace Hosts.Helpers
|
||||
/// <summary>
|
||||
/// Determines whether the hosts are valid
|
||||
/// </summary>
|
||||
public static bool ValidHosts(string hosts)
|
||||
public static bool ValidHosts(string hosts, bool validateHostsLength)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(hosts))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var host in hosts.Split(' '))
|
||||
var splittedHosts = hosts.Split(' ');
|
||||
|
||||
if (validateHostsLength && splittedHosts.Length > Consts.MaxHostsCount)
|
||||
{
|
||||
if (System.Uri.CheckHostName(host) == System.UriHostNameType.Unknown)
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var host in splittedHosts)
|
||||
{
|
||||
if (Uri.CheckHostName(host) == UriHostNameType.Unknown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Hosts.Helpers
|
||||
{
|
||||
// Taken from https://github.com/microsoft/microsoft-ui-xaml/blob/main/test/MUXControlsTestApp/Utilities/VisualTreeUtils.cs
|
||||
// Original copyright header:
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See LICENSE in the project root for license information.
|
||||
public static class VisualTreeUtils
|
||||
{
|
||||
public static T FindVisualChildByType<T>(this DependencyObject element)
|
||||
where T : DependencyObject
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (element is T elementAsT)
|
||||
{
|
||||
return elementAsT;
|
||||
}
|
||||
|
||||
int childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
||||
for (int i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var result = VisualTreeHelper.GetChild(element, i).FindVisualChildByType<T>();
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FrameworkElement FindVisualChildByName(this DependencyObject element, string name)
|
||||
{
|
||||
if (element == null || string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (element is FrameworkElement elementAsFE && elementAsFE.Name == name)
|
||||
{
|
||||
return elementAsFE;
|
||||
}
|
||||
|
||||
int childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
||||
for (int i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var result = VisualTreeHelper.GetChild(element, i).FindVisualChildByName(name);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,9 @@
|
||||
MinWidth="480"
|
||||
MinHeight="320"
|
||||
mc:Ignorable="d">
|
||||
<winuiex:WindowEx.Backdrop>
|
||||
<winuiex:MicaSystemBackdrop />
|
||||
</winuiex:WindowEx.Backdrop>
|
||||
<Window.SystemBackdrop>
|
||||
<MicaBackdrop />
|
||||
</Window.SystemBackdrop>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Hosts.Helpers;
|
||||
using Microsoft.UI.Windowing;
|
||||
using WinUIEx;
|
||||
|
||||
namespace Hosts
|
||||
|
||||
@@ -12,32 +12,35 @@ namespace Hosts.Models
|
||||
{
|
||||
public partial class Entry : ObservableObject
|
||||
{
|
||||
private string _line;
|
||||
private static readonly char[] _spaceCharacters = new char[] { ' ', '\t' };
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(Valid))]
|
||||
private string _address;
|
||||
|
||||
public string Address
|
||||
partial void OnAddressChanged(string value)
|
||||
{
|
||||
get => _address;
|
||||
set
|
||||
if (ValidationHelper.ValidIPv4(value))
|
||||
{
|
||||
SetProperty(ref _address, value);
|
||||
SetAddressType();
|
||||
OnPropertyChanged(nameof(Valid));
|
||||
Type = AddressType.IPv4;
|
||||
}
|
||||
else if (ValidationHelper.ValidIPv6(value))
|
||||
{
|
||||
Type = AddressType.IPv6;
|
||||
}
|
||||
else
|
||||
{
|
||||
Type = AddressType.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(Valid))]
|
||||
private string _hosts;
|
||||
|
||||
public string Hosts
|
||||
partial void OnHostsChanged(string value)
|
||||
{
|
||||
get => _hosts;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _hosts, value);
|
||||
OnPropertyChanged(nameof(Valid));
|
||||
SplittedHosts = _hosts.Split(' ');
|
||||
}
|
||||
SplittedHosts = value.Split(' ');
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
@@ -55,7 +58,9 @@ namespace Hosts.Models
|
||||
[ObservableProperty]
|
||||
private bool _duplicate;
|
||||
|
||||
public bool Valid => ValidationHelper.ValidHosts(_hosts) && Type != AddressType.Invalid;
|
||||
public bool Valid => Validate(true);
|
||||
|
||||
public string Line { get; private set; }
|
||||
|
||||
public AddressType Type { get; private set; }
|
||||
|
||||
@@ -70,7 +75,7 @@ namespace Hosts.Models
|
||||
public Entry(int id, string line)
|
||||
{
|
||||
Id = id;
|
||||
_line = line.Trim();
|
||||
Line = line.Trim();
|
||||
Parse();
|
||||
}
|
||||
|
||||
@@ -85,9 +90,9 @@ namespace Hosts.Models
|
||||
|
||||
public void Parse()
|
||||
{
|
||||
Active = !_line.StartsWith("#", StringComparison.InvariantCultureIgnoreCase);
|
||||
Active = !Line.StartsWith("#", StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
var lineSplit = _line.TrimStart(' ', '#').Split('#');
|
||||
var lineSplit = Line.TrimStart(' ', '#').Split('#');
|
||||
|
||||
if (lineSplit.Length == 0)
|
||||
{
|
||||
@@ -96,7 +101,7 @@ namespace Hosts.Models
|
||||
|
||||
var addressHost = lineSplit[0];
|
||||
|
||||
var addressHostSplit = addressHost.Split(' ', '\t');
|
||||
var addressHostSplit = addressHost.Split(_spaceCharacters, StringSplitOptions.RemoveEmptyEntries);
|
||||
var hostsBuilder = new StringBuilder();
|
||||
var commentBuilder = new StringBuilder();
|
||||
|
||||
@@ -104,17 +109,9 @@ namespace Hosts.Models
|
||||
{
|
||||
var element = addressHostSplit[i].Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(element))
|
||||
if (i == 0 && IPAddress.TryParse(element, out var _) && (element.Contains(':') || element.Contains('.')))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Address == null)
|
||||
{
|
||||
if (IPAddress.TryParse(element, out var _) && (element.Contains(':') || element.Contains('.')))
|
||||
{
|
||||
Address = element;
|
||||
}
|
||||
Address = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -146,7 +143,7 @@ namespace Hosts.Models
|
||||
{
|
||||
return new Entry
|
||||
{
|
||||
_line = _line,
|
||||
Line = Line,
|
||||
Address = Address,
|
||||
Hosts = Hosts,
|
||||
Comment = Comment,
|
||||
@@ -154,25 +151,9 @@ namespace Hosts.Models
|
||||
};
|
||||
}
|
||||
|
||||
public string GetLine()
|
||||
public bool Validate(bool validateHostsLength)
|
||||
{
|
||||
return _line;
|
||||
}
|
||||
|
||||
private void SetAddressType()
|
||||
{
|
||||
if (ValidationHelper.ValidIPv4(_address))
|
||||
{
|
||||
Type = AddressType.IPv4;
|
||||
}
|
||||
else if (ValidationHelper.ValidIPv6(_address))
|
||||
{
|
||||
Type = AddressType.IPv6;
|
||||
}
|
||||
else
|
||||
{
|
||||
Type = AddressType.Invalid;
|
||||
}
|
||||
return Type != AddressType.Invalid && ValidationHelper.ValidHosts(Hosts, validateHostsLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
37
src/modules/Hosts/Hosts/Models/HostsData.cs
Normal file
37
src/modules/Hosts/Hosts/Models/HostsData.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
|
||||
namespace Hosts.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the parsed hosts file
|
||||
/// </summary>
|
||||
public class HostsData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the parsed entries
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<Entry> Entries { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lines that couldn't be parsed
|
||||
/// </summary>
|
||||
public string AdditionalLines { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether some entries been splitted
|
||||
/// </summary>
|
||||
public bool SplittedEntries { get; }
|
||||
|
||||
public HostsData(List<Entry> entries, string additionalLines, bool splittedEntries)
|
||||
{
|
||||
Entries = entries.AsReadOnly();
|
||||
AdditionalLines = additionalLines;
|
||||
SplittedEntries = splittedEntries;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@ namespace Hosts.Settings
|
||||
|
||||
public bool LoopbackDuplicates { get; }
|
||||
|
||||
public AdditionalLinesPosition AdditionalLinesPosition { get; }
|
||||
public HostsAdditionalLinesPosition AdditionalLinesPosition { get; }
|
||||
|
||||
public HostsEncoding Encoding { get; }
|
||||
|
||||
event EventHandler LoopbackDuplicatesChanged;
|
||||
}
|
||||
|
||||
@@ -38,14 +38,17 @@ namespace Hosts.Settings
|
||||
}
|
||||
}
|
||||
|
||||
public AdditionalLinesPosition AdditionalLinesPosition { get; private set; }
|
||||
public HostsAdditionalLinesPosition AdditionalLinesPosition { get; private set; }
|
||||
|
||||
public HostsEncoding Encoding { get; set; }
|
||||
|
||||
public UserSettings()
|
||||
{
|
||||
_settingsUtils = new SettingsUtils();
|
||||
ShowStartupWarning = true;
|
||||
LoopbackDuplicates = false;
|
||||
AdditionalLinesPosition = AdditionalLinesPosition.Top;
|
||||
AdditionalLinesPosition = HostsAdditionalLinesPosition.Top;
|
||||
Encoding = HostsEncoding.Utf8;
|
||||
|
||||
LoadSettingsFromJson();
|
||||
|
||||
@@ -79,6 +82,7 @@ namespace Hosts.Settings
|
||||
{
|
||||
ShowStartupWarning = settings.Properties.ShowStartupWarning;
|
||||
AdditionalLinesPosition = settings.Properties.AdditionalLinesPosition;
|
||||
Encoding = settings.Properties.Encoding;
|
||||
LoopbackDuplicates = settings.Properties.LoopbackDuplicates;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,12 @@
|
||||
<data name="AddEntryBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>New entry</value>
|
||||
</data>
|
||||
<data name="AddEntryBtn.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>New entry (CTRL+N)</value>
|
||||
</data>
|
||||
<data name="AddEntryLink.Content" xml:space="preserve">
|
||||
<value>Add an entry</value>
|
||||
</data>
|
||||
<data name="AdditionalLinesBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Additional content</value>
|
||||
</data>
|
||||
@@ -164,6 +170,9 @@
|
||||
<data name="ClearFiltersBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Clear filters</value>
|
||||
</data>
|
||||
<data name="ClearFiltersLink.Content" xml:space="preserve">
|
||||
<value>Clear filters</value>
|
||||
</data>
|
||||
<data name="Comment.Header" xml:space="preserve">
|
||||
<value>Comment</value>
|
||||
<comment>"Comment" refers to the comment of the entry</comment>
|
||||
@@ -187,6 +196,16 @@
|
||||
<data name="DuplicateEntryIcon.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Duplicate entry</value>
|
||||
</data>
|
||||
<data name="Edit.Text" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
<data name="EmptyFilterResults.Text" xml:space="preserve">
|
||||
<value>No filter results</value>
|
||||
</data>
|
||||
<data name="EmptyHosts.Text" xml:space="preserve">
|
||||
<value>No entries in the hosts file</value>
|
||||
<comment>"Hosts" refers to the system hosts file, do not loc</comment>
|
||||
</data>
|
||||
<data name="Entries.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Entries</value>
|
||||
</data>
|
||||
@@ -212,7 +231,7 @@
|
||||
<comment>"Hosts" refers to the system hosts file, do not loc</comment>
|
||||
</data>
|
||||
<data name="Hosts.[using:Microsoft.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Seperate multiple hosts by space (e.g. server server.local).</value>
|
||||
<value>Seperate multiple hosts by space (e.g. server server.local). Maximum 9 hosts per entry.</value>
|
||||
<comment>Do not localize "server" and "server.local"</comment>
|
||||
</data>
|
||||
<data name="HostsFilter.Header" xml:space="preserve">
|
||||
@@ -253,6 +272,17 @@
|
||||
<data name="ShowOnlyDuplicates.Header" xml:space="preserve">
|
||||
<value>Show only duplicates</value>
|
||||
</data>
|
||||
<data name="TooManyHostsTeachingTip.Subtitle" xml:space="preserve">
|
||||
<value>Only 9 hosts per entry are supported</value>
|
||||
<comment>"Hosts" refers to the system hosts file, do not loc</comment>
|
||||
</data>
|
||||
<data name="TooManyHostsTeachingTip.Title" xml:space="preserve">
|
||||
<value>Entries with too many hosts found</value>
|
||||
<comment>"Hosts" refers to the system hosts file, do not loc</comment>
|
||||
</data>
|
||||
<data name="TooManyHostsTeachingTipContent.Text" xml:space="preserve">
|
||||
<value>The affected entries have been splitted. This will take effect on next change.</value>
|
||||
</data>
|
||||
<data name="UpdateBtn" xml:space="preserve">
|
||||
<value>Update</value>
|
||||
</data>
|
||||
|
||||
@@ -65,23 +65,22 @@ namespace Hosts.ViewModels
|
||||
[ObservableProperty]
|
||||
private bool _filtered;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _showOnlyDuplicates;
|
||||
|
||||
public bool ShowOnlyDuplicates
|
||||
[ObservableProperty]
|
||||
private bool _showSplittedEntriesTooltip;
|
||||
|
||||
partial void OnShowOnlyDuplicatesChanged(bool value)
|
||||
{
|
||||
get => _showOnlyDuplicates;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _showOnlyDuplicates, value);
|
||||
ApplyFilters();
|
||||
}
|
||||
ApplyFilters();
|
||||
}
|
||||
|
||||
private ObservableCollection<Entry> _entries;
|
||||
|
||||
public AdvancedCollectionView Entries { get; set; }
|
||||
|
||||
public int NextId => _entries.Max(e => e.Id) + 1;
|
||||
public int NextId => _entries?.Count > 0 ? _entries.Max(e => e.Id) + 1 : 0;
|
||||
|
||||
public MainViewModel(IHostsService hostService, IUserSettings userSettings)
|
||||
{
|
||||
@@ -126,11 +125,11 @@ namespace Hosts.ViewModels
|
||||
|
||||
public void UpdateAdditionalLines(string lines)
|
||||
{
|
||||
_additionalLines = lines;
|
||||
AdditionalLines = lines;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var error = !await _hostsService.WriteAsync(_additionalLines, _entries);
|
||||
var error = !await _hostsService.WriteAsync(AdditionalLines, _entries);
|
||||
await _dispatcherQueue.EnqueueAsync(() => Error = error);
|
||||
});
|
||||
}
|
||||
@@ -168,11 +167,13 @@ namespace Hosts.ViewModels
|
||||
Task.Run(async () =>
|
||||
{
|
||||
_readingHosts = true;
|
||||
(_additionalLines, var entries) = await _hostsService.ReadAsync();
|
||||
var data = await _hostsService.ReadAsync();
|
||||
|
||||
await _dispatcherQueue.EnqueueAsync(() =>
|
||||
{
|
||||
_entries = new ObservableCollection<Entry>(entries);
|
||||
ShowSplittedEntriesTooltip = data.SplittedEntries;
|
||||
AdditionalLines = data.AdditionalLines;
|
||||
_entries = new ObservableCollection<Entry>(data.Entries);
|
||||
|
||||
foreach (var e in _entries)
|
||||
{
|
||||
@@ -199,22 +200,22 @@ namespace Hosts.ViewModels
|
||||
{
|
||||
var expressions = new List<Expression<Func<object, bool>>>(4);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_addressFilter))
|
||||
if (!string.IsNullOrWhiteSpace(AddressFilter))
|
||||
{
|
||||
expressions.Add(e => ((Entry)e).Address.Contains(_addressFilter, StringComparison.OrdinalIgnoreCase));
|
||||
expressions.Add(e => ((Entry)e).Address.Contains(AddressFilter, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_hostsFilter))
|
||||
if (!string.IsNullOrWhiteSpace(HostsFilter))
|
||||
{
|
||||
expressions.Add(e => ((Entry)e).Hosts.Contains(_hostsFilter, StringComparison.OrdinalIgnoreCase));
|
||||
expressions.Add(e => ((Entry)e).Hosts.Contains(HostsFilter, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_commentFilter))
|
||||
if (!string.IsNullOrWhiteSpace(CommentFilter))
|
||||
{
|
||||
expressions.Add(e => ((Entry)e).Comment.Contains(_commentFilter, StringComparison.OrdinalIgnoreCase));
|
||||
expressions.Add(e => ((Entry)e).Comment.Contains(CommentFilter, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
if (_showOnlyDuplicates)
|
||||
if (ShowOnlyDuplicates)
|
||||
{
|
||||
expressions.Add(e => ((Entry)e).Duplicate);
|
||||
}
|
||||
@@ -238,16 +239,15 @@ namespace Hosts.ViewModels
|
||||
HostsFilter = null;
|
||||
CommentFilter = null;
|
||||
ShowOnlyDuplicates = false;
|
||||
Entries.Filter = null;
|
||||
Entries.RefreshFilter();
|
||||
ApplyFilters();
|
||||
}
|
||||
|
||||
public async Task PingSelectedAsync()
|
||||
{
|
||||
var selected = _selected;
|
||||
var selected = Selected;
|
||||
selected.Ping = null;
|
||||
selected.Pinging = true;
|
||||
selected.Ping = await _hostsService.PingAsync(_selected.Address);
|
||||
selected.Ping = await _hostsService.PingAsync(Selected.Address);
|
||||
selected.Pinging = false;
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace Hosts.ViewModels
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var error = !await _hostsService.WriteAsync(_additionalLines, _entries);
|
||||
var error = !await _hostsService.WriteAsync(AdditionalLines, _entries);
|
||||
await _dispatcherQueue.EnqueueAsync(() => Error = error);
|
||||
});
|
||||
}
|
||||
@@ -298,7 +298,7 @@ namespace Hosts.ViewModels
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var error = !await _hostsService.WriteAsync(_additionalLines, _entries);
|
||||
var error = !await _hostsService.WriteAsync(AdditionalLines, _entries);
|
||||
await _dispatcherQueue.EnqueueAsync(() => Error = error);
|
||||
});
|
||||
}
|
||||
@@ -350,12 +350,28 @@ namespace Hosts.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
var hosts = entry.SplittedHosts;
|
||||
var duplicate = false;
|
||||
|
||||
var duplicate = _entries.FirstOrDefault(e => e != entry
|
||||
/*
|
||||
* Duplicate are based on the following criteria:
|
||||
* Entries with the same type and at least one host in common
|
||||
* Entries with the same type and address, except when there is only one entry with less than 9 hosts for that type and address
|
||||
*/
|
||||
if (_entries.Any(e => e != entry
|
||||
&& e.Type == entry.Type
|
||||
&& (string.Equals(e.Address, entry.Address, StringComparison.OrdinalIgnoreCase)
|
||||
|| hosts.Intersect(e.SplittedHosts, StringComparer.OrdinalIgnoreCase).Any())) != null;
|
||||
&& entry.SplittedHosts.Intersect(e.SplittedHosts, StringComparer.OrdinalIgnoreCase).Any()))
|
||||
{
|
||||
duplicate = true;
|
||||
}
|
||||
else if (_entries.Any(e => e != entry
|
||||
&& e.Type == entry.Type
|
||||
&& string.Equals(e.Address, entry.Address, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
duplicate = entry.SplittedHosts.Length < Consts.MaxHostsCount
|
||||
&& _entries.Count(e => e.Type == entry.Type
|
||||
&& string.Equals(e.Address, entry.Address, StringComparison.OrdinalIgnoreCase)
|
||||
&& e.SplittedHosts.Length < Consts.MaxHostsCount) > 1;
|
||||
}
|
||||
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
x:Key="BoolToInvertedVisibilityConverter"
|
||||
TrueValue="Collapsed"
|
||||
FalseValue="Visible" />
|
||||
<converters:DoubleToVisibilityConverter
|
||||
x:Key="DoubleToVisibilityConverter"
|
||||
FalseValue="Visible"
|
||||
GreaterThan="0"
|
||||
TrueValue="Collapsed" />
|
||||
</Page.Resources>
|
||||
|
||||
<Grid>
|
||||
@@ -43,7 +48,7 @@
|
||||
<Button
|
||||
x:Uid="AddEntryBtn"
|
||||
Height="36"
|
||||
Margin="16,0,0,0"
|
||||
Margin="18,0,0,0"
|
||||
Command="{x:Bind NewDialogCommand}">
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
@@ -56,10 +61,15 @@
|
||||
Glyph="" />
|
||||
<TextBlock x:Uid="AddEntry" />
|
||||
</StackPanel>
|
||||
<Button.KeyboardAccelerators>
|
||||
<KeyboardAccelerator
|
||||
Modifiers="Control"
|
||||
Key="N" />
|
||||
</Button.KeyboardAccelerators>
|
||||
</Button>
|
||||
|
||||
<StackPanel
|
||||
Padding="0,0,16,0"
|
||||
Padding="0,0,18,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
@@ -184,169 +194,239 @@
|
||||
CanDragItems="{x:Bind ViewModel.Filtered, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
|
||||
CanReorderItems="{x:Bind ViewModel.Filtered, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
|
||||
-->
|
||||
<ListView
|
||||
x:Name="Entries"
|
||||
x:Uid="Entries"
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Margin="16,8,16,16"
|
||||
Background="{ThemeResource LayerFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="Entries_ItemClick"
|
||||
ItemsSource="{Binding Entries, Mode=TwoWay}"
|
||||
SelectedItem="{Binding Selected, Mode=TwoWay}"
|
||||
Visibility="{x:Bind ViewModel.IsLoading, Converter={StaticResource BoolToInvertedVisibilityConverter}, Mode=OneWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:Entry">
|
||||
<Grid
|
||||
AutomationProperties.Name="{x:Bind Address, Mode=OneWay}"
|
||||
Background="Transparent"
|
||||
IsRightTapEnabled="True"
|
||||
RightTapped="Grid_RightTapped">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="300" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FlyoutBase.AttachedFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="Ping"
|
||||
Click="Ping_Click"
|
||||
Icon="TwoBars" />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="MoveUp"
|
||||
Click="ReorderButtonUp_Click"
|
||||
IsEnabled="{Binding DataContext.Filtered, ElementName=Page, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="MoveDown"
|
||||
Click="ReorderButtonDown_Click"
|
||||
IsEnabled="{Binding DataContext.Filtered, ElementName=Page, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="Delete"
|
||||
Click="Delete_Click"
|
||||
Icon="Delete" />
|
||||
</MenuFlyout>
|
||||
</FlyoutBase.AttachedFlyout>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Address, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind helpers:StringHelper.GetHostsWithComment(Hosts, Comment), Mode=OneWay}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<ProgressRing
|
||||
Grid.Column="2"
|
||||
Width="20"
|
||||
Height="20"
|
||||
Margin="0,0,8,0"
|
||||
IsActive="{x:Bind Pinging, Mode=OneWay}" />
|
||||
<FontIcon
|
||||
x:Uid="PingIcon"
|
||||
x:Name="PingIcon"
|
||||
Grid.Column="2"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="18"
|
||||
Visibility="Collapsed">
|
||||
<i:Interaction.Behaviors>
|
||||
<ic:DataTriggerBehavior
|
||||
Binding="{x:Bind Ping, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Glyph"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Visibility"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="Visible" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Foreground"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="{StaticResource SystemFillColorSuccessBrush}" />
|
||||
</ic:DataTriggerBehavior>
|
||||
<ic:DataTriggerBehavior
|
||||
Binding="{x:Bind Ping, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Glyph"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Visibility"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="Visible" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Foreground"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="{StaticResource SystemFillColorCriticalBrush}" />
|
||||
</ic:DataTriggerBehavior>
|
||||
<ic:DataTriggerBehavior
|
||||
Binding="{x:Bind Ping, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="{x:Null}">
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Visibility"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="Collapsed" />
|
||||
</ic:DataTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
</FontIcon>
|
||||
<FontIcon
|
||||
x:Uid="DuplicateEntryIcon"
|
||||
Grid.Column="3"
|
||||
Margin="0,0,8,0"
|
||||
Foreground="{StaticResource SystemControlErrorTextForegroundBrush}"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="18"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind Duplicate, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<ToggleSwitch
|
||||
x:Uid="ActiveToggle"
|
||||
Grid.Column="4"
|
||||
Width="40"
|
||||
MinWidth="0"
|
||||
HorizontalAlignment="Right"
|
||||
IsOn="{x:Bind Active, Mode=TwoWay}"
|
||||
OffContent=""
|
||||
OnContent="" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
Visibility="{x:Bind ViewModel.IsLoading, Converter={StaticResource BoolToInvertedVisibilityConverter}, Mode=OneWay}">
|
||||
<ListView
|
||||
x:Name="Entries"
|
||||
x:Uid="Entries"
|
||||
Grid.Row="1"
|
||||
Margin="16,8,16,16"
|
||||
Background="{ThemeResource LayerFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="Entries_ItemClick"
|
||||
KeyDown="Entries_KeyDown"
|
||||
GotFocus="Entries_GotFocus"
|
||||
ItemsSource="{x:Bind ViewModel.Entries, Mode=TwoWay}"
|
||||
SelectedItem="{x:Bind ViewModel.Selected, Mode=TwoWay}"
|
||||
Visibility="{x:Bind ViewModel.IsLoading, Converter={StaticResource BoolToInvertedVisibilityConverter}, Mode=OneWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:Entry">
|
||||
<Grid
|
||||
AutomationProperties.Name="{x:Bind Address, Mode=OneWay}"
|
||||
Background="Transparent"
|
||||
IsRightTapEnabled="True"
|
||||
RightTapped="Grid_RightTapped">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="300" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FlyoutBase.AttachedFlyout>
|
||||
<MenuFlyout Opened="MenuFlyout_Opened">
|
||||
<MenuFlyoutItem
|
||||
x:Uid="Edit"
|
||||
Click="Edit_Click"
|
||||
Icon="Edit">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator
|
||||
Modifiers="Control"
|
||||
Key="E" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="Ping"
|
||||
Click="Ping_Click"
|
||||
Icon="TwoBars">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator
|
||||
Modifiers="Control"
|
||||
Key="P" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="MoveUp"
|
||||
Click="ReorderButtonUp_Click"
|
||||
IsEnabled="{Binding DataContext.Filtered, ElementName=Page, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="MoveDown"
|
||||
Click="ReorderButtonDown_Click"
|
||||
IsEnabled="{Binding DataContext.Filtered, ElementName=Page, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<FontIcon Glyph="" />
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="Delete"
|
||||
Click="Delete_Click"
|
||||
Icon="Delete">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="Delete" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
</MenuFlyout>
|
||||
</FlyoutBase.AttachedFlyout>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Address, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind helpers:StringHelper.GetHostsWithComment(Hosts, Comment), Mode=OneWay}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<ProgressRing
|
||||
Grid.Column="2"
|
||||
Width="20"
|
||||
Height="20"
|
||||
Margin="0,0,8,0"
|
||||
IsActive="{x:Bind Pinging, Mode=OneWay}" />
|
||||
<FontIcon
|
||||
x:Uid="PingIcon"
|
||||
x:Name="PingIcon"
|
||||
Grid.Column="2"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="18"
|
||||
Visibility="Collapsed">
|
||||
<i:Interaction.Behaviors>
|
||||
<ic:DataTriggerBehavior
|
||||
Binding="{x:Bind Ping, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Glyph"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Visibility"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="Visible" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Foreground"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="{StaticResource SystemFillColorSuccessBrush}" />
|
||||
</ic:DataTriggerBehavior>
|
||||
<ic:DataTriggerBehavior
|
||||
Binding="{x:Bind Ping, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Glyph"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Visibility"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="Visible" />
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Foreground"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="{StaticResource SystemFillColorCriticalBrush}" />
|
||||
</ic:DataTriggerBehavior>
|
||||
<ic:DataTriggerBehavior
|
||||
Binding="{x:Bind Ping, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="{x:Null}">
|
||||
<ic:ChangePropertyAction
|
||||
PropertyName="Visibility"
|
||||
TargetObject="{Binding ElementName=PingIcon}"
|
||||
Value="Collapsed" />
|
||||
</ic:DataTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
</FontIcon>
|
||||
<FontIcon
|
||||
x:Uid="DuplicateEntryIcon"
|
||||
Grid.Column="3"
|
||||
Margin="0,0,8,0"
|
||||
Foreground="{StaticResource SystemControlErrorTextForegroundBrush}"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="18"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind Duplicate, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<ToggleSwitch
|
||||
x:Uid="ActiveToggle"
|
||||
Grid.Column="4"
|
||||
Width="40"
|
||||
MinWidth="0"
|
||||
HorizontalAlignment="Right"
|
||||
IsOn="{x:Bind Active, Mode=TwoWay}"
|
||||
OffContent=""
|
||||
OnContent="" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{x:Bind ViewModel.Entries.Count, Mode=OneWay, Converter={StaticResource DoubleToVisibilityConverter}}">
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind ViewModel.Filtered, Mode=OneWay, Converter={StaticResource BoolToInvertedVisibilityConverter}}">
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
FontSize="32"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
x:Uid="EmptyHosts"
|
||||
HorizontalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<HyperlinkButton
|
||||
x:Uid="AddEntryLink"
|
||||
HorizontalAlignment="Center"
|
||||
Command="{x:Bind NewDialogCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind ViewModel.Filtered, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
FontSize="32"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
x:Uid="EmptyFilterResults"
|
||||
HorizontalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
<HyperlinkButton
|
||||
x:Uid="ClearFiltersLink"
|
||||
HorizontalAlignment="Center"
|
||||
Command="{x:Bind ViewModel.ClearFiltersCommand}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<ProgressRing
|
||||
Width="48"
|
||||
Height="48"
|
||||
Grid.Row="1"
|
||||
IsActive="{x:Bind ViewModel.IsLoading, Mode=OneWay}" />
|
||||
|
||||
|
||||
<ContentDialog
|
||||
x:Name="EntryDialog"
|
||||
x:Uid="EntryDialog"
|
||||
Loaded="ContentDialog_Loaded_ApplyMargin"
|
||||
IsPrimaryButtonEnabled="{Binding Valid, Mode=TwoWay}"
|
||||
IsPrimaryButtonEnabled="{Binding Valid, Mode=OneWay}"
|
||||
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">
|
||||
<ContentDialog.DataContext>
|
||||
<models:Entry />
|
||||
@@ -355,7 +435,7 @@
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
HorizontalScrollMode="Auto">
|
||||
<StackPanel
|
||||
MinWidth="480"
|
||||
Width="480"
|
||||
Margin="0,12,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="24">
|
||||
@@ -366,10 +446,22 @@
|
||||
<TextBox
|
||||
x:Uid="Hosts"
|
||||
IsSpellCheckEnabled="False"
|
||||
AcceptsReturn="False"
|
||||
TextWrapping="Wrap"
|
||||
Height="100"
|
||||
ScrollViewer.IsVerticalRailEnabled="True"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Visible"
|
||||
ScrollViewer.VerticalScrollMode="Enabled"
|
||||
Text="{Binding Hosts, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBox
|
||||
x:Uid="Comment"
|
||||
IsSpellCheckEnabled="False"
|
||||
IsSpellCheckEnabled="False"
|
||||
AcceptsReturn="False"
|
||||
TextWrapping="Wrap"
|
||||
Height="100"
|
||||
ScrollViewer.IsVerticalRailEnabled="True"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Visible"
|
||||
ScrollViewer.VerticalScrollMode="Enabled"
|
||||
Text="{Binding Comment, Mode=TwoWay}" />
|
||||
<ToggleSwitch
|
||||
x:Uid="Active"
|
||||
@@ -391,7 +483,6 @@
|
||||
<ContentDialog
|
||||
x:Name="AdditionalLinesDialog"
|
||||
x:Uid="AdditionalLinesDialog"
|
||||
Loaded="ContentDialog_Loaded_ApplyMargin"
|
||||
PrimaryButtonCommand="{x:Bind UpdateAdditionalLinesCommand}"
|
||||
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">
|
||||
|
||||
@@ -407,5 +498,20 @@
|
||||
ScrollViewer.VerticalScrollMode="Enabled"
|
||||
TextWrapping="Wrap" />
|
||||
</ContentDialog>
|
||||
|
||||
<TeachingTip
|
||||
x:Uid="TooManyHostsTeachingTip"
|
||||
IsOpen="{x:Bind ViewModel.ShowSplittedEntriesTooltip, Mode=OneWay}"
|
||||
PreferredPlacement="Top"
|
||||
PlacementMargin="20">
|
||||
<TeachingTip.IconSource>
|
||||
<FontIconSource Glyph="" />
|
||||
</TeachingTip.IconSource>
|
||||
<TeachingTip.Content>
|
||||
<TextBlock x:Uid="TooManyHostsTeachingTipContent"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,16,0,0" />
|
||||
</TeachingTip.Content>
|
||||
</TeachingTip>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Hosts.Models;
|
||||
using Hosts.Settings;
|
||||
using Hosts.ViewModels;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using Windows.System;
|
||||
using Windows.UI.Core;
|
||||
|
||||
namespace Hosts.Views
|
||||
{
|
||||
@@ -60,9 +62,14 @@ namespace Hosts.Views
|
||||
}
|
||||
|
||||
private async void Entries_ItemClick(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
await ShowEditDialogAsync(e.ClickedItem as Entry);
|
||||
}
|
||||
|
||||
public async Task ShowEditDialogAsync(Entry entry)
|
||||
{
|
||||
var resourceLoader = ResourceLoader.GetForViewIndependentUse();
|
||||
ViewModel.Selected = e.ClickedItem as Entry;
|
||||
ViewModel.Selected = entry;
|
||||
EntryDialog.Title = resourceLoader.GetString("UpdateEntry_Title");
|
||||
EntryDialog.PrimaryButtonText = resourceLoader.GetString("UpdateBtn");
|
||||
EntryDialog.PrimaryButtonCommand = UpdateCommand;
|
||||
@@ -111,21 +118,40 @@ namespace Hosts.Views
|
||||
|
||||
if (menuFlyoutItem != null)
|
||||
{
|
||||
var selectedEntry = menuFlyoutItem.DataContext as Entry;
|
||||
ViewModel.Selected = selectedEntry;
|
||||
DeleteDialog.Title = selectedEntry.Address;
|
||||
await DeleteDialog.ShowAsync();
|
||||
await ShowDeleteDialogAsync(menuFlyoutItem.DataContext as Entry);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ShowDeleteDialogAsync(Entry entry)
|
||||
{
|
||||
ViewModel.Selected = entry;
|
||||
DeleteDialog.Title = entry.Address;
|
||||
await DeleteDialog.ShowAsync();
|
||||
}
|
||||
|
||||
private async void Ping_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var menuFlyoutItem = sender as MenuFlyoutItem;
|
||||
|
||||
if (menuFlyoutItem != null)
|
||||
{
|
||||
ViewModel.Selected = menuFlyoutItem.DataContext as Entry;
|
||||
await ViewModel.PingSelectedAsync();
|
||||
await PingAsync(menuFlyoutItem.DataContext as Entry);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PingAsync(Entry entry)
|
||||
{
|
||||
ViewModel.Selected = entry;
|
||||
await ViewModel.PingSelectedAsync();
|
||||
}
|
||||
|
||||
private async void Edit_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var menuFlyoutItem = sender as MenuFlyoutItem;
|
||||
|
||||
if (menuFlyoutItem != null)
|
||||
{
|
||||
await ShowEditDialogAsync(menuFlyoutItem.DataContext as Entry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,17 +210,54 @@ namespace Hosts.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void ContentDialog_Loaded_ApplyMargin(object sender, RoutedEventArgs e)
|
||||
/// <summary>
|
||||
/// Handle the keyboard shortcuts at list view level since
|
||||
/// KeyboardAccelerators in FlyoutBase.AttachedFlyout works only when the flyout is open
|
||||
/// </summary>
|
||||
private async void Entries_KeyDown(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
var listView = sender as ListView;
|
||||
if (listView != null && e.KeyStatus.WasKeyDown == false)
|
||||
{
|
||||
// Based on the template from dev/CommonStyles/ContentDialog_themeresources.xaml in https://github.com/microsoft/microsoft-ui-xaml
|
||||
var border = Helpers.VisualTreeUtils.FindVisualChildByName(sender as ContentDialog, "BackgroundElement") as Border;
|
||||
border.Margin = new Thickness(0, 32, 0, 0); // Should be the size reserved for the title bar as in MainWindow.xaml
|
||||
var entry = listView.SelectedItem as Entry;
|
||||
|
||||
if (Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down))
|
||||
{
|
||||
if (e.Key == VirtualKey.E)
|
||||
{
|
||||
await ShowEditDialogAsync(entry);
|
||||
}
|
||||
else if (e.Key == VirtualKey.P)
|
||||
{
|
||||
await PingAsync(entry);
|
||||
}
|
||||
}
|
||||
else if (e.Key == VirtualKey.Delete)
|
||||
{
|
||||
await ShowDeleteDialogAsync(entry);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Focus the first item when the list view gets the focus with keyboard
|
||||
/// </summary>
|
||||
private void Entries_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var listView = sender as ListView;
|
||||
if (listView.SelectedItem == null && listView.Items.Count > 0)
|
||||
{
|
||||
Logger.LogError("Couldn't set the margin for a content dialog. It will appear on top of the title bar.", ex);
|
||||
listView.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void MenuFlyout_Opened(object sender, object e)
|
||||
{
|
||||
// Focus the first item: required for workaround https://github.com/microsoft/PowerToys/issues/21263
|
||||
var menuFlyout = sender as MenuFlyout;
|
||||
if (menuFlyout != null && menuFlyout.Items.Count > 0)
|
||||
{
|
||||
menuFlyout.Items.First().Focus(FocusState.Programmatic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,7 +593,8 @@ bool SuperSonar<D>::IsForegroundAppExcluded()
|
||||
{
|
||||
auto processPath = get_process_path(foregroundApp);
|
||||
CharUpperBuffW(processPath.data(), static_cast<DWORD>(processPath.length()));
|
||||
return find_app_name_in_path(processPath, m_excludedApps);
|
||||
|
||||
return check_excluded_app(foregroundApp, processPath, m_excludedApps);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -540,11 +540,6 @@ namespace MouseWithoutBorders
|
||||
else
|
||||
{
|
||||
SendHeartBeat();
|
||||
|
||||
if (Setting.Values.BlockScreenSaverEx && lastInputEventCount == Common.InputEventCount && Common.DesMachineID == Common.MachineID)
|
||||
{
|
||||
PokeMyself();
|
||||
}
|
||||
}
|
||||
|
||||
lastInputEventCount = Common.InputEventCount;
|
||||
|
||||
@@ -356,15 +356,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (Common.DesMachineID == ID.NONE || Common.DesMachineID == ID.ALL || Common.DesMachineID == Common.MachineID)
|
||||
{
|
||||
if (nCode >= 0 && Setting.Values.UseVKMap && Setting.Values.VKMap != null && Setting.Values.VKMap.ContainsKey(hookCallbackKeybdData.wVk) && !CtrlDown)
|
||||
{
|
||||
InputSimulation.SendKey(hookCallbackKeybdData);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NativeMethods.CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
return NativeMethods.CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -569,6 +561,13 @@ namespace MouseWithoutBorders.Class
|
||||
Common.MainForm.Quit(false, false);
|
||||
});
|
||||
}
|
||||
else if (shiftDown || winDown)
|
||||
{
|
||||
// The following else cases should work if control and alt modifiers are pressed. The hotkeys should still be captured.
|
||||
// But if any of the other 2 modifiers (shift or win) are pressed, they hotkeys should not be activated.
|
||||
// Issue #26597
|
||||
return true;
|
||||
}
|
||||
else if (vkCode == Setting.Values.HotKeySwitchMachine ||
|
||||
vkCode == Setting.Values.HotKeySwitchMachine + 1 ||
|
||||
vkCode == Setting.Values.HotKeySwitchMachine + 2 ||
|
||||
@@ -645,14 +644,6 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (shiftDown && Setting.Values.VKMap != null && vkCode == (Setting.Values.VKMap.ContainsKey(0) ? (int)Setting.Values.VKMap[0] : 'K'))
|
||||
{
|
||||
if (Common.DesMachineID == Common.MachineID || Common.DesMachineID == ID.ALL)
|
||||
{
|
||||
Setting.Values.UseVKMap = !Setting.Values.UseVKMap;
|
||||
return Common.DesMachineID == ID.ALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -96,11 +96,6 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
InputProcessKeyEx(kd.wVk, kd.dwFlags, out bool eatKey);
|
||||
|
||||
if (Setting.Values.UseVKMap && Setting.Values.VKMap != null && Setting.Values.VKMap.ContainsKey(kd.wVk) && !ctrlDown)
|
||||
{
|
||||
kd.wVk = (int)Setting.Values.VKMap[kd.wVk];
|
||||
}
|
||||
|
||||
if (!eatKey)
|
||||
{
|
||||
InputHook.RealData = false;
|
||||
@@ -380,15 +375,6 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Setting.Values.VKMap != null && vkCode == (Setting.Values.VKMap.ContainsKey(0) ? (int)Setting.Values.VKMap[0] : 'K'))
|
||||
{
|
||||
if (ctrlDown && altDown && shiftDown)
|
||||
{
|
||||
ctrlDown = altDown = shiftDown = false;
|
||||
Setting.Values.UseVKMap = !Setting.Values.UseVKMap;
|
||||
eatKey = true;
|
||||
}
|
||||
}
|
||||
else if (vkCode == Setting.Values.HotKeyCaptureScreen && ctrlDown && shiftDown && !altDown)
|
||||
{
|
||||
ctrlDown = shiftDown = false;
|
||||
|
||||
@@ -86,15 +86,25 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
// If we're started from the .dll module or from the service process, we should
|
||||
// assume the service mode.
|
||||
if (serviceMode || runningAsSystem)
|
||||
if (serviceMode && !runningAsSystem)
|
||||
{
|
||||
if (!runningAsSystem)
|
||||
try
|
||||
{
|
||||
var sc = new ServiceController(ServiceName);
|
||||
sc.Start();
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Common.Log("Couldn't start the service. Will try to continue as not a service.");
|
||||
Common.Log(ex);
|
||||
serviceMode = false;
|
||||
Setting.Values.UseService = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceMode || runningAsSystem)
|
||||
{
|
||||
if (args.Length > 2)
|
||||
{
|
||||
Helper.UserLocalAppDataPath = args[2].Trim();
|
||||
@@ -350,7 +360,6 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
internal static void StartInputCallbackThread()
|
||||
{
|
||||
System.Collections.Hashtable dummy = Setting.Values.VKMap; // Reading from registry to memory.
|
||||
Thread inputCallback = new(new ThreadStart(InputCallbackThread), "InputCallback Thread");
|
||||
inputCallback.SetApartmentState(ApartmentState.STA);
|
||||
inputCallback.Priority = ThreadPriority.Highest;
|
||||
|
||||
@@ -303,7 +303,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.MatrixOneRow = true;
|
||||
_properties.MatrixOneRow = value;
|
||||
if (!PauseInstantSaving)
|
||||
{
|
||||
SaveSettings();
|
||||
@@ -501,25 +501,6 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
internal bool BlockScreenSaverEx
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.BlockScreenSaverOnOtherMachines;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.BlockScreenSaverOnOtherMachines = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal bool MoveMouseRelatively
|
||||
{
|
||||
get
|
||||
@@ -877,25 +858,6 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
internal bool UseVKMap
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.UseVKMap;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.UseVKMap = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal bool FirstCtrlShiftS
|
||||
{
|
||||
get
|
||||
@@ -915,15 +877,9 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
internal Hashtable VKMap
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Hashtable();
|
||||
}
|
||||
}
|
||||
|
||||
internal bool StealFocusWhenSwitchingMachine => _properties.StealFocusWhenSwitchingMachine;
|
||||
// Was a value read from registry on original Mouse Without Border, but default should be true. We wrongly released it as false, so we're forcing true here.
|
||||
// This value wasn't changeable from UI, anyway.
|
||||
internal bool StealFocusWhenSwitchingMachine => true;
|
||||
|
||||
private string deviceId;
|
||||
|
||||
@@ -1023,6 +979,30 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
// If starting the service fails, work in not service mode.
|
||||
internal bool UseService
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
return _properties.UseService;
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
lock (_loadingSettingsLock)
|
||||
{
|
||||
_properties.UseService = value;
|
||||
if (!PauseInstantSaving)
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal bool SendErrorLogV2
|
||||
{
|
||||
get
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
checkBoxEnabled.Checked = value;
|
||||
Editable = value;
|
||||
pictureBoxLogo.Image = value ? Resources.MachineEnabled : (System.Drawing.Image)Resources.MachineDisabled;
|
||||
pictureBoxLogo.Image = value ? Images.MachineEnabled : (System.Drawing.Image)Images.MachineDisabled;
|
||||
OnEnabledChanged(EventArgs.Empty); // Borrow this event since we do not use it for any other purpose:) (we can create one but l...:))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
//
|
||||
// ComputerPictureBox
|
||||
//
|
||||
this.ComputerPictureBox.Image = global::MouseWithoutBorders.Properties.Resources.computer_connected;
|
||||
this.ComputerPictureBox.Image = global::MouseWithoutBorders.Properties.Images.computer_connected;
|
||||
this.ComputerPictureBox.Location = new System.Drawing.Point(5, 5);
|
||||
this.ComputerPictureBox.Name = "ComputerPictureBox";
|
||||
this.ComputerPictureBox.Padding = new System.Windows.Forms.Padding(0, 10, 0, 0);
|
||||
@@ -86,12 +86,12 @@
|
||||
// RemoveButton
|
||||
//
|
||||
this.RemoveButton.DisabledImage = null;
|
||||
this.RemoveButton.DownImage = global::MouseWithoutBorders.Properties.Resources.red_close_button_click;
|
||||
this.RemoveButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.red_close_button_hover;
|
||||
this.RemoveButton.Image = global::MouseWithoutBorders.Properties.Resources.red_close_button_normal;
|
||||
this.RemoveButton.DownImage = global::MouseWithoutBorders.Properties.Images.red_close_button_click;
|
||||
this.RemoveButton.HoverImage = global::MouseWithoutBorders.Properties.Images.red_close_button_hover;
|
||||
this.RemoveButton.Image = global::MouseWithoutBorders.Properties.Images.red_close_button_normal;
|
||||
this.RemoveButton.Location = new System.Drawing.Point(224, 15);
|
||||
this.RemoveButton.Name = "RemoveButton";
|
||||
this.RemoveButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.red_close_button_normal;
|
||||
this.RemoveButton.NormalImage = global::MouseWithoutBorders.Properties.Images.red_close_button_normal;
|
||||
this.RemoveButton.Size = new System.Drawing.Size(12, 12);
|
||||
this.RemoveButton.TabIndex = 5;
|
||||
this.RemoveButton.TabStop = false;
|
||||
@@ -101,12 +101,12 @@
|
||||
//
|
||||
this.OnButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.OnButton.DisabledImage = null;
|
||||
this.OnButton.DownImage = global::MouseWithoutBorders.Properties.Resources.switch_on_click;
|
||||
this.OnButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.switch_on_hover;
|
||||
this.OnButton.Image = global::MouseWithoutBorders.Properties.Resources.switch_on_normal;
|
||||
this.OnButton.DownImage = global::MouseWithoutBorders.Properties.Images.switch_on_click;
|
||||
this.OnButton.HoverImage = global::MouseWithoutBorders.Properties.Images.switch_on_hover;
|
||||
this.OnButton.Image = global::MouseWithoutBorders.Properties.Images.switch_on_normal;
|
||||
this.OnButton.Location = new System.Drawing.Point(277, 20);
|
||||
this.OnButton.Name = "OnButton";
|
||||
this.OnButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.switch_on_normal;
|
||||
this.OnButton.NormalImage = global::MouseWithoutBorders.Properties.Images.switch_on_normal;
|
||||
this.OnButton.Size = new System.Drawing.Size(30, 15);
|
||||
this.OnButton.TabIndex = 3;
|
||||
this.OnButton.TabStop = false;
|
||||
@@ -116,12 +116,12 @@
|
||||
//
|
||||
this.OffButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.OffButton.DisabledImage = null;
|
||||
this.OffButton.DownImage = global::MouseWithoutBorders.Properties.Resources.switch_off_click;
|
||||
this.OffButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.switch_off_hover;
|
||||
this.OffButton.Image = global::MouseWithoutBorders.Properties.Resources.switch_off_normal;
|
||||
this.OffButton.DownImage = global::MouseWithoutBorders.Properties.Images.switch_off_click;
|
||||
this.OffButton.HoverImage = global::MouseWithoutBorders.Properties.Images.switch_off_hover;
|
||||
this.OffButton.Image = global::MouseWithoutBorders.Properties.Images.switch_off_normal;
|
||||
this.OffButton.Location = new System.Drawing.Point(241, 42);
|
||||
this.OffButton.Name = "OffButton";
|
||||
this.OffButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.switch_off_normal;
|
||||
this.OffButton.NormalImage = global::MouseWithoutBorders.Properties.Images.switch_off_normal;
|
||||
this.OffButton.Size = new System.Drawing.Size(30, 15);
|
||||
this.OffButton.TabIndex = 4;
|
||||
this.OffButton.TabStop = false;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
// SingleRowRadioButton
|
||||
//
|
||||
this.SingleRowRadioButton.Checked = true;
|
||||
this.SingleRowRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Resources.one_row_button_checked;
|
||||
this.SingleRowRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Images.one_row_button_checked;
|
||||
this.SingleRowRadioButton.ImageLocation = new System.Drawing.Point(0, 0);
|
||||
this.SingleRowRadioButton.Location = new System.Drawing.Point(0, 0);
|
||||
this.SingleRowRadioButton.Margin = new System.Windows.Forms.Padding(0);
|
||||
@@ -57,13 +57,13 @@
|
||||
this.SingleRowRadioButton.TabIndex = 4;
|
||||
this.SingleRowRadioButton.TabStop = true;
|
||||
this.SingleRowRadioButton.TextLocation = new System.Drawing.Point(0, 0);
|
||||
this.SingleRowRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.one_row_button_unchecked;
|
||||
this.SingleRowRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Images.one_row_button_unchecked;
|
||||
this.SingleRowRadioButton.UseVisualStyleBackColor = true;
|
||||
this.SingleRowRadioButton.CheckedChanged += new System.EventHandler(this.SingleRowRadioButtonCheckedChanged);
|
||||
//
|
||||
// TwoRowsRadioButton
|
||||
//
|
||||
this.TwoRowsRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Resources.two_row_button_checked;
|
||||
this.TwoRowsRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Images.two_row_button_checked;
|
||||
this.TwoRowsRadioButton.ImageLocation = new System.Drawing.Point(0, 0);
|
||||
this.TwoRowsRadioButton.Location = new System.Drawing.Point(0, 27);
|
||||
this.TwoRowsRadioButton.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
|
||||
@@ -71,7 +71,7 @@
|
||||
this.TwoRowsRadioButton.Size = new System.Drawing.Size(27, 24);
|
||||
this.TwoRowsRadioButton.TabIndex = 5;
|
||||
this.TwoRowsRadioButton.TextLocation = new System.Drawing.Point(0, 0);
|
||||
this.TwoRowsRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.two_row_button_unchecked;
|
||||
this.TwoRowsRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Images.two_row_button_unchecked;
|
||||
this.TwoRowsRadioButton.UseVisualStyleBackColor = true;
|
||||
this.TwoRowsRadioButton.CheckedChanged += new System.EventHandler(this.TwoRowsRadioButtonCheckedChanged);
|
||||
//
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
//
|
||||
this.closeWindowButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.closeWindowButton.DisabledImage = null;
|
||||
this.closeWindowButton.DownImage = global::MouseWithoutBorders.Properties.Resources.close_window_click;
|
||||
this.closeWindowButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.close_window_hover;
|
||||
this.closeWindowButton.DownImage = global::MouseWithoutBorders.Properties.Images.close_window_click;
|
||||
this.closeWindowButton.HoverImage = global::MouseWithoutBorders.Properties.Images.close_window_hover;
|
||||
this.closeWindowButton.Location = new System.Drawing.Point(454, 6);
|
||||
this.closeWindowButton.Name = "closeWindowButton";
|
||||
this.closeWindowButton.NormalImage = null;
|
||||
@@ -67,7 +67,7 @@
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackgroundImage = global::MouseWithoutBorders.Properties.Resources.dialog_background;
|
||||
this.BackgroundImage = global::MouseWithoutBorders.Properties.Images.dialog_background;
|
||||
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
|
||||
this.ClientSize = new System.Drawing.Size(477, 476);
|
||||
this.Controls.Add(this.closeWindowButton);
|
||||
|
||||
@@ -52,12 +52,12 @@
|
||||
// BackButton
|
||||
//
|
||||
this.BackButton.DisabledImage = null;
|
||||
this.BackButton.DownImage = global::MouseWithoutBorders.Properties.Resources.back_button_click;
|
||||
this.BackButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.back_button_hover;
|
||||
this.BackButton.Image = global::MouseWithoutBorders.Properties.Resources.back_button_normal;
|
||||
this.BackButton.DownImage = global::MouseWithoutBorders.Properties.Images.back_button_click;
|
||||
this.BackButton.HoverImage = global::MouseWithoutBorders.Properties.Images.back_button_hover;
|
||||
this.BackButton.Image = global::MouseWithoutBorders.Properties.Images.back_button_normal;
|
||||
this.BackButton.Location = new System.Drawing.Point(6, 6);
|
||||
this.BackButton.Name = "BackButton";
|
||||
this.BackButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.back_button_normal;
|
||||
this.BackButton.NormalImage = global::MouseWithoutBorders.Properties.Images.back_button_normal;
|
||||
this.BackButton.Size = new System.Drawing.Size(24, 24);
|
||||
this.BackButton.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
||||
this.BackButton.TabIndex = 0;
|
||||
|
||||
@@ -72,13 +72,13 @@
|
||||
//
|
||||
this.DoneButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.DoneButton.DisabledImage = null;
|
||||
this.DoneButton.DownImage = global::MouseWithoutBorders.Properties.Resources.done_button_click;
|
||||
this.DoneButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.done_button_hover;
|
||||
this.DoneButton.Image = global::MouseWithoutBorders.Properties.Resources.done_button_normal;
|
||||
this.DoneButton.InitialImage = global::MouseWithoutBorders.Properties.Resources.yes_button_normal;
|
||||
this.DoneButton.DownImage = global::MouseWithoutBorders.Properties.Images.done_button_click;
|
||||
this.DoneButton.HoverImage = global::MouseWithoutBorders.Properties.Images.done_button_hover;
|
||||
this.DoneButton.Image = global::MouseWithoutBorders.Properties.Images.done_button_normal;
|
||||
this.DoneButton.InitialImage = global::MouseWithoutBorders.Properties.Images.yes_button_normal;
|
||||
this.DoneButton.Location = new System.Drawing.Point(199, 366);
|
||||
this.DoneButton.Name = "DoneButton";
|
||||
this.DoneButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.done_button_normal;
|
||||
this.DoneButton.NormalImage = global::MouseWithoutBorders.Properties.Images.done_button_normal;
|
||||
this.DoneButton.Size = new System.Drawing.Size(55, 55);
|
||||
this.DoneButton.TabIndex = 8;
|
||||
this.DoneButton.TabStop = false;
|
||||
@@ -89,13 +89,13 @@
|
||||
//
|
||||
this.CloseButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.CloseButton.DisabledImage = null;
|
||||
this.CloseButton.DownImage = global::MouseWithoutBorders.Properties.Resources.close_button_click;
|
||||
this.CloseButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.close_button_hover;
|
||||
this.CloseButton.Image = global::MouseWithoutBorders.Properties.Resources.close_button_normal;
|
||||
this.CloseButton.InitialImage = global::MouseWithoutBorders.Properties.Resources.yes_button_normal;
|
||||
this.CloseButton.DownImage = global::MouseWithoutBorders.Properties.Images.close_button_click;
|
||||
this.CloseButton.HoverImage = global::MouseWithoutBorders.Properties.Images.close_button_hover;
|
||||
this.CloseButton.Image = global::MouseWithoutBorders.Properties.Images.close_button_normal;
|
||||
this.CloseButton.InitialImage = global::MouseWithoutBorders.Properties.Images.yes_button_normal;
|
||||
this.CloseButton.Location = new System.Drawing.Point(199, 366);
|
||||
this.CloseButton.Name = "CloseButton";
|
||||
this.CloseButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.close_button_normal;
|
||||
this.CloseButton.NormalImage = global::MouseWithoutBorders.Properties.Images.close_button_normal;
|
||||
this.CloseButton.Size = new System.Drawing.Size(55, 55);
|
||||
this.CloseButton.TabIndex = 7;
|
||||
this.CloseButton.TabStop = false;
|
||||
|
||||
@@ -53,12 +53,12 @@
|
||||
// AddComputerButton
|
||||
//
|
||||
this.AddComputerButton.DisabledImage = null;
|
||||
this.AddComputerButton.DownImage = global::MouseWithoutBorders.Properties.Resources.computer_button_click;
|
||||
this.AddComputerButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.computer_button_hover;
|
||||
this.AddComputerButton.Image = global::MouseWithoutBorders.Properties.Resources.computer_button_normal;
|
||||
this.AddComputerButton.DownImage = global::MouseWithoutBorders.Properties.Images.computer_button_click;
|
||||
this.AddComputerButton.HoverImage = global::MouseWithoutBorders.Properties.Images.computer_button_hover;
|
||||
this.AddComputerButton.Image = global::MouseWithoutBorders.Properties.Images.computer_button_normal;
|
||||
this.AddComputerButton.Location = new System.Drawing.Point(50, 317);
|
||||
this.AddComputerButton.Name = "AddComputerButton";
|
||||
this.AddComputerButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.computer_button_normal;
|
||||
this.AddComputerButton.NormalImage = global::MouseWithoutBorders.Properties.Images.computer_button_normal;
|
||||
this.AddComputerButton.Size = new System.Drawing.Size(74, 23);
|
||||
this.AddComputerButton.TabIndex = 9;
|
||||
this.AddComputerButton.TabStop = false;
|
||||
@@ -67,12 +67,12 @@
|
||||
// KeyboardShortcutsButton
|
||||
//
|
||||
this.KeyboardShortcutsButton.DisabledImage = null;
|
||||
this.KeyboardShortcutsButton.DownImage = global::MouseWithoutBorders.Properties.Resources.keyboard_button_click;
|
||||
this.KeyboardShortcutsButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.keyboard_button_hover;
|
||||
this.KeyboardShortcutsButton.Image = global::MouseWithoutBorders.Properties.Resources.keyboard_button_normal;
|
||||
this.KeyboardShortcutsButton.DownImage = global::MouseWithoutBorders.Properties.Images.keyboard_button_click;
|
||||
this.KeyboardShortcutsButton.HoverImage = global::MouseWithoutBorders.Properties.Images.keyboard_button_hover;
|
||||
this.KeyboardShortcutsButton.Image = global::MouseWithoutBorders.Properties.Images.keyboard_button_normal;
|
||||
this.KeyboardShortcutsButton.Location = new System.Drawing.Point(327, 317);
|
||||
this.KeyboardShortcutsButton.Name = "KeyboardShortcutsButton";
|
||||
this.KeyboardShortcutsButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.keyboard_button_normal;
|
||||
this.KeyboardShortcutsButton.NormalImage = global::MouseWithoutBorders.Properties.Images.keyboard_button_normal;
|
||||
this.KeyboardShortcutsButton.Size = new System.Drawing.Size(84, 23);
|
||||
this.KeyboardShortcutsButton.TabIndex = 11;
|
||||
this.KeyboardShortcutsButton.TabStop = false;
|
||||
@@ -81,12 +81,12 @@
|
||||
// AdvancedOptionsButton
|
||||
//
|
||||
this.AdvancedOptionsButton.DisabledImage = null;
|
||||
this.AdvancedOptionsButton.DownImage = global::MouseWithoutBorders.Properties.Resources.advanced_button_click;
|
||||
this.AdvancedOptionsButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.advanced_button_hover;
|
||||
this.AdvancedOptionsButton.Image = global::MouseWithoutBorders.Properties.Resources.advanced_button_normal;
|
||||
this.AdvancedOptionsButton.DownImage = global::MouseWithoutBorders.Properties.Images.advanced_button_click;
|
||||
this.AdvancedOptionsButton.HoverImage = global::MouseWithoutBorders.Properties.Images.advanced_button_hover;
|
||||
this.AdvancedOptionsButton.Image = global::MouseWithoutBorders.Properties.Images.advanced_button_normal;
|
||||
this.AdvancedOptionsButton.Location = new System.Drawing.Point(244, 317);
|
||||
this.AdvancedOptionsButton.Name = "AdvancedOptionsButton";
|
||||
this.AdvancedOptionsButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.advanced_button_normal;
|
||||
this.AdvancedOptionsButton.NormalImage = global::MouseWithoutBorders.Properties.Images.advanced_button_normal;
|
||||
this.AdvancedOptionsButton.Size = new System.Drawing.Size(74, 23);
|
||||
this.AdvancedOptionsButton.TabIndex = 12;
|
||||
this.AdvancedOptionsButton.TabStop = false;
|
||||
@@ -95,12 +95,12 @@
|
||||
// LinkComputerButton
|
||||
//
|
||||
this.LinkComputerButton.DisabledImage = null;
|
||||
this.LinkComputerButton.DownImage = global::MouseWithoutBorders.Properties.Resources.small_link_button_click;
|
||||
this.LinkComputerButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.small_link_button_hover;
|
||||
this.LinkComputerButton.Image = global::MouseWithoutBorders.Properties.Resources.small_link_button_normal;
|
||||
this.LinkComputerButton.DownImage = global::MouseWithoutBorders.Properties.Images.small_link_button_click;
|
||||
this.LinkComputerButton.HoverImage = global::MouseWithoutBorders.Properties.Images.small_link_button_hover;
|
||||
this.LinkComputerButton.Image = global::MouseWithoutBorders.Properties.Images.small_link_button_normal;
|
||||
this.LinkComputerButton.Location = new System.Drawing.Point(133, 317);
|
||||
this.LinkComputerButton.Name = "LinkComputerButton";
|
||||
this.LinkComputerButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.small_link_button_normal;
|
||||
this.LinkComputerButton.NormalImage = global::MouseWithoutBorders.Properties.Images.small_link_button_normal;
|
||||
this.LinkComputerButton.Size = new System.Drawing.Size(74, 23);
|
||||
this.LinkComputerButton.TabIndex = 13;
|
||||
this.LinkComputerButton.TabStop = false;
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
// ShareClipboardCheckbox
|
||||
//
|
||||
this.ShareClipboardCheckbox.AutoSize = true;
|
||||
this.ShareClipboardCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_checked;
|
||||
this.ShareClipboardCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_checked;
|
||||
this.ShareClipboardCheckbox.DisabledImage = null;
|
||||
this.ShareClipboardCheckbox.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F);
|
||||
this.ShareClipboardCheckbox.Location = new System.Drawing.Point(54, 188);
|
||||
@@ -76,14 +76,14 @@
|
||||
this.ShareClipboardCheckbox.Size = new System.Drawing.Size(128, 34);
|
||||
this.ShareClipboardCheckbox.TabIndex = 16;
|
||||
this.ShareClipboardCheckbox.Text = "Share Clipboard (Text \r\nand Image)";
|
||||
this.ShareClipboardCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_unchecked;
|
||||
this.ShareClipboardCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_unchecked;
|
||||
this.ShareClipboardCheckbox.UseVisualStyleBackColor = true;
|
||||
this.ShareClipboardCheckbox.CheckedChanged += new System.EventHandler(this.ShareClipboardCheckbox_CheckedChanged);
|
||||
//
|
||||
// HideOnLoginCheckbox
|
||||
//
|
||||
this.HideOnLoginCheckbox.AutoSize = true;
|
||||
this.HideOnLoginCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_checked;
|
||||
this.HideOnLoginCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_checked;
|
||||
this.HideOnLoginCheckbox.DisabledImage = null;
|
||||
this.HideOnLoginCheckbox.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F);
|
||||
this.HideOnLoginCheckbox.Location = new System.Drawing.Point(54, 238);
|
||||
@@ -92,14 +92,14 @@
|
||||
this.HideOnLoginCheckbox.Size = new System.Drawing.Size(143, 34);
|
||||
this.HideOnLoginCheckbox.TabIndex = 17;
|
||||
this.HideOnLoginCheckbox.Text = "Hide Mouse w/o Borders \r\non the Login Desktop";
|
||||
this.HideOnLoginCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_unchecked;
|
||||
this.HideOnLoginCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_unchecked;
|
||||
this.HideOnLoginCheckbox.UseVisualStyleBackColor = true;
|
||||
this.HideOnLoginCheckbox.CheckedChanged += new System.EventHandler(this.HideOnLoginCheckbox_CheckedChanged);
|
||||
//
|
||||
// EnableEasyMouseCheckbox
|
||||
//
|
||||
this.EnableEasyMouseCheckbox.AutoSize = true;
|
||||
this.EnableEasyMouseCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_checked;
|
||||
this.EnableEasyMouseCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_checked;
|
||||
this.EnableEasyMouseCheckbox.DisabledImage = null;
|
||||
this.EnableEasyMouseCheckbox.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F);
|
||||
this.EnableEasyMouseCheckbox.Location = new System.Drawing.Point(54, 288);
|
||||
@@ -108,14 +108,14 @@
|
||||
this.EnableEasyMouseCheckbox.Size = new System.Drawing.Size(114, 19);
|
||||
this.EnableEasyMouseCheckbox.TabIndex = 18;
|
||||
this.EnableEasyMouseCheckbox.Text = "Enable Easy Mouse";
|
||||
this.EnableEasyMouseCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_unchecked;
|
||||
this.EnableEasyMouseCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_unchecked;
|
||||
this.EnableEasyMouseCheckbox.UseVisualStyleBackColor = true;
|
||||
this.EnableEasyMouseCheckbox.CheckedChanged += new System.EventHandler(this.EnableEasyMouseCheckbox_CheckedChanged);
|
||||
//
|
||||
// WrapMouseCheckbox
|
||||
//
|
||||
this.WrapMouseCheckbox.AutoSize = true;
|
||||
this.WrapMouseCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_checked;
|
||||
this.WrapMouseCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_checked;
|
||||
this.WrapMouseCheckbox.DisabledImage = null;
|
||||
this.WrapMouseCheckbox.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.WrapMouseCheckbox.Location = new System.Drawing.Point(238, 288);
|
||||
@@ -124,14 +124,14 @@
|
||||
this.WrapMouseCheckbox.Size = new System.Drawing.Size(85, 19);
|
||||
this.WrapMouseCheckbox.TabIndex = 19;
|
||||
this.WrapMouseCheckbox.Text = "Wrap Mouse";
|
||||
this.WrapMouseCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_unchecked;
|
||||
this.WrapMouseCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_unchecked;
|
||||
this.WrapMouseCheckbox.UseVisualStyleBackColor = true;
|
||||
this.WrapMouseCheckbox.CheckedChanged += new System.EventHandler(this.WrapMouseCheckbox_CheckedChanged);
|
||||
//
|
||||
// DisableCADCheckbox
|
||||
//
|
||||
this.DisableCADCheckbox.AutoSize = true;
|
||||
this.DisableCADCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_checked;
|
||||
this.DisableCADCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_checked;
|
||||
this.DisableCADCheckbox.DisabledImage = null;
|
||||
this.DisableCADCheckbox.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F);
|
||||
this.DisableCADCheckbox.Location = new System.Drawing.Point(238, 188);
|
||||
@@ -140,14 +140,14 @@
|
||||
this.DisableCADCheckbox.Size = new System.Drawing.Size(154, 34);
|
||||
this.DisableCADCheckbox.TabIndex = 20;
|
||||
this.DisableCADCheckbox.Text = "Disable Ctrl+Alt+Del on the \r\nLogin Screen";
|
||||
this.DisableCADCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_unchecked;
|
||||
this.DisableCADCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_unchecked;
|
||||
this.DisableCADCheckbox.UseVisualStyleBackColor = true;
|
||||
this.DisableCADCheckbox.CheckedChanged += new System.EventHandler(this.DisableCADCheckbox_CheckedChanged);
|
||||
//
|
||||
// BlockScreenSaverCheckbox
|
||||
//
|
||||
this.BlockScreenSaverCheckbox.AutoSize = true;
|
||||
this.BlockScreenSaverCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_checked;
|
||||
this.BlockScreenSaverCheckbox.CheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_checked;
|
||||
this.BlockScreenSaverCheckbox.DisabledImage = null;
|
||||
this.BlockScreenSaverCheckbox.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F);
|
||||
this.BlockScreenSaverCheckbox.Location = new System.Drawing.Point(238, 238);
|
||||
@@ -156,7 +156,7 @@
|
||||
this.BlockScreenSaverCheckbox.Size = new System.Drawing.Size(158, 34);
|
||||
this.BlockScreenSaverCheckbox.TabIndex = 21;
|
||||
this.BlockScreenSaverCheckbox.Text = "Block Screen Saver on Other\r\nMachines";
|
||||
this.BlockScreenSaverCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.checkbox_unchecked;
|
||||
this.BlockScreenSaverCheckbox.UncheckedImage = global::MouseWithoutBorders.Properties.Images.checkbox_unchecked;
|
||||
this.BlockScreenSaverCheckbox.UseVisualStyleBackColor = true;
|
||||
this.BlockScreenSaverCheckbox.CheckedChanged += new System.EventHandler(this.BlockScreenSaverCheckbox_CheckedChanged);
|
||||
//
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
// DisabledRadioButton
|
||||
//
|
||||
this.DisabledRadioButton.AutoSize = true;
|
||||
this.DisabledRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Resources.radio_button_checked;
|
||||
this.DisabledRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Images.radio_button_checked;
|
||||
this.DisabledRadioButton.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.DisabledRadioButton.ForeColor = System.Drawing.Color.White;
|
||||
this.DisabledRadioButton.ImageLocation = new System.Drawing.Point(0, 3);
|
||||
@@ -222,14 +222,14 @@
|
||||
this.DisabledRadioButton.TabIndex = 2;
|
||||
this.DisabledRadioButton.Text = "Disabled";
|
||||
this.DisabledRadioButton.TextLocation = new System.Drawing.Point(14, 0);
|
||||
this.DisabledRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.radio_button_unchecked;
|
||||
this.DisabledRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Images.radio_button_unchecked;
|
||||
this.DisabledRadioButton.UseVisualStyleBackColor = true;
|
||||
this.DisabledRadioButton.CheckedChanged += new System.EventHandler(this.DisabledRadioButton_CheckedChanged);
|
||||
//
|
||||
// NumbersRadioButton
|
||||
//
|
||||
this.NumbersRadioButton.AutoSize = true;
|
||||
this.NumbersRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Resources.radio_button_checked;
|
||||
this.NumbersRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Images.radio_button_checked;
|
||||
this.NumbersRadioButton.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.NumbersRadioButton.ForeColor = System.Drawing.Color.White;
|
||||
this.NumbersRadioButton.ImageLocation = new System.Drawing.Point(0, 3);
|
||||
@@ -239,14 +239,14 @@
|
||||
this.NumbersRadioButton.TabIndex = 1;
|
||||
this.NumbersRadioButton.Text = "1, 2, 3, 4";
|
||||
this.NumbersRadioButton.TextLocation = new System.Drawing.Point(14, 0);
|
||||
this.NumbersRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.radio_button_unchecked;
|
||||
this.NumbersRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Images.radio_button_unchecked;
|
||||
this.NumbersRadioButton.UseVisualStyleBackColor = true;
|
||||
this.NumbersRadioButton.CheckedChanged += new System.EventHandler(this.NumbersRadioButton_CheckedChanged);
|
||||
//
|
||||
// FKeysRadioButton
|
||||
//
|
||||
this.FKeysRadioButton.AutoSize = true;
|
||||
this.FKeysRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Resources.radio_button_checked;
|
||||
this.FKeysRadioButton.CheckedImage = global::MouseWithoutBorders.Properties.Images.radio_button_checked;
|
||||
this.FKeysRadioButton.Font = new System.Drawing.Font(DefaultFont.Name, 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.FKeysRadioButton.ForeColor = System.Drawing.Color.White;
|
||||
this.FKeysRadioButton.ImageLocation = new System.Drawing.Point(0, 3);
|
||||
@@ -256,7 +256,7 @@
|
||||
this.FKeysRadioButton.TabIndex = 0;
|
||||
this.FKeysRadioButton.Text = "F1, F2, F3, F4";
|
||||
this.FKeysRadioButton.TextLocation = new System.Drawing.Point(14, 0);
|
||||
this.FKeysRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Resources.radio_button_unchecked;
|
||||
this.FKeysRadioButton.UncheckedImage = global::MouseWithoutBorders.Properties.Images.radio_button_unchecked;
|
||||
this.FKeysRadioButton.UseVisualStyleBackColor = true;
|
||||
this.FKeysRadioButton.CheckedChanged += new System.EventHandler(this.FKeysRadioButton_CheckedChanged);
|
||||
//
|
||||
|
||||
@@ -110,13 +110,13 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
this.NoButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.NoButton.DisabledImage = null;
|
||||
this.NoButton.DownImage = global::MouseWithoutBorders.Properties.Resources.no_button_click;
|
||||
this.NoButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.no_button_hover;
|
||||
this.NoButton.Image = global::MouseWithoutBorders.Properties.Resources.no_button_normal;
|
||||
this.NoButton.InitialImage = global::MouseWithoutBorders.Properties.Resources.yes_button_normal;
|
||||
this.NoButton.DownImage = global::MouseWithoutBorders.Properties.Images.no_button_click;
|
||||
this.NoButton.HoverImage = global::MouseWithoutBorders.Properties.Images.no_button_hover;
|
||||
this.NoButton.Image = global::MouseWithoutBorders.Properties.Images.no_button_normal;
|
||||
this.NoButton.InitialImage = global::MouseWithoutBorders.Properties.Images.yes_button_normal;
|
||||
this.NoButton.Location = new System.Drawing.Point(234, 366);
|
||||
this.NoButton.Name = "NoButton";
|
||||
this.NoButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.no_button_normal;
|
||||
this.NoButton.NormalImage = global::MouseWithoutBorders.Properties.Images.no_button_normal;
|
||||
this.NoButton.Size = new System.Drawing.Size(55, 55);
|
||||
this.NoButton.TabIndex = 7;
|
||||
this.NoButton.TabStop = false;
|
||||
@@ -126,13 +126,13 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
this.YesButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.YesButton.DisabledImage = null;
|
||||
this.YesButton.DownImage = global::MouseWithoutBorders.Properties.Resources.yes_button_click;
|
||||
this.YesButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.yes_button_hover;
|
||||
this.YesButton.Image = global::MouseWithoutBorders.Properties.Resources.yes_button_normal;
|
||||
this.YesButton.InitialImage = global::MouseWithoutBorders.Properties.Resources.yes_button_normal;
|
||||
this.YesButton.DownImage = global::MouseWithoutBorders.Properties.Images.yes_button_click;
|
||||
this.YesButton.HoverImage = global::MouseWithoutBorders.Properties.Images.yes_button_hover;
|
||||
this.YesButton.Image = global::MouseWithoutBorders.Properties.Images.yes_button_normal;
|
||||
this.YesButton.InitialImage = global::MouseWithoutBorders.Properties.Images.yes_button_normal;
|
||||
this.YesButton.Location = new System.Drawing.Point(164, 366);
|
||||
this.YesButton.Name = "YesButton";
|
||||
this.YesButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.yes_button_normal;
|
||||
this.YesButton.NormalImage = global::MouseWithoutBorders.Properties.Images.yes_button_normal;
|
||||
this.YesButton.Size = new System.Drawing.Size(55, 55);
|
||||
this.YesButton.TabIndex = 6;
|
||||
this.YesButton.TabStop = false;
|
||||
@@ -140,7 +140,7 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.Image = global::MouseWithoutBorders.Properties.Resources.Mouse;
|
||||
this.pictureBox1.Image = global::MouseWithoutBorders.Properties.Images.Mouse;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(206, 40);
|
||||
this.pictureBox1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
|
||||
@@ -98,14 +98,14 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
// LinkButton
|
||||
//
|
||||
this.LinkButton.DisabledImage = global::MouseWithoutBorders.Properties.Resources.link_button_disabled;
|
||||
this.LinkButton.DownImage = global::MouseWithoutBorders.Properties.Resources.link_button_click;
|
||||
this.LinkButton.DisabledImage = global::MouseWithoutBorders.Properties.Images.link_button_disabled;
|
||||
this.LinkButton.DownImage = global::MouseWithoutBorders.Properties.Images.link_button_click;
|
||||
this.LinkButton.Enabled = false;
|
||||
this.LinkButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.link_button_hover;
|
||||
this.LinkButton.Image = global::MouseWithoutBorders.Properties.Resources.link_button_normal;
|
||||
this.LinkButton.HoverImage = global::MouseWithoutBorders.Properties.Images.link_button_hover;
|
||||
this.LinkButton.Image = global::MouseWithoutBorders.Properties.Images.link_button_normal;
|
||||
this.LinkButton.Location = new System.Drawing.Point(199, 366);
|
||||
this.LinkButton.Name = "LinkButton";
|
||||
this.LinkButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.link_button_normal;
|
||||
this.LinkButton.NormalImage = global::MouseWithoutBorders.Properties.Images.link_button_normal;
|
||||
this.LinkButton.Size = new System.Drawing.Size(55, 55);
|
||||
this.LinkButton.TabIndex = 15;
|
||||
this.LinkButton.TabStop = false;
|
||||
@@ -126,12 +126,12 @@ namespace MouseWithoutBorders
|
||||
// ExpandHelpButton
|
||||
//
|
||||
this.ExpandHelpButton.DisabledImage = null;
|
||||
this.ExpandHelpButton.DownImage = global::MouseWithoutBorders.Properties.Resources.expand_button_click;
|
||||
this.ExpandHelpButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.expand_button_highlight;
|
||||
this.ExpandHelpButton.Image = global::MouseWithoutBorders.Properties.Resources.expand_button_normal;
|
||||
this.ExpandHelpButton.DownImage = global::MouseWithoutBorders.Properties.Images.expand_button_click;
|
||||
this.ExpandHelpButton.HoverImage = global::MouseWithoutBorders.Properties.Images.expand_button_highlight;
|
||||
this.ExpandHelpButton.Image = global::MouseWithoutBorders.Properties.Images.expand_button_normal;
|
||||
this.ExpandHelpButton.Location = new System.Drawing.Point(360, 211);
|
||||
this.ExpandHelpButton.Name = "ExpandHelpButton";
|
||||
this.ExpandHelpButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.expand_button_normal;
|
||||
this.ExpandHelpButton.NormalImage = global::MouseWithoutBorders.Properties.Images.expand_button_normal;
|
||||
this.ExpandHelpButton.Size = new System.Drawing.Size(11, 11);
|
||||
this.ExpandHelpButton.TabIndex = 24;
|
||||
this.ExpandHelpButton.TabStop = false;
|
||||
@@ -140,12 +140,12 @@ namespace MouseWithoutBorders
|
||||
// CollapseHelpButton
|
||||
//
|
||||
this.CollapseHelpButton.DisabledImage = null;
|
||||
this.CollapseHelpButton.DownImage = global::MouseWithoutBorders.Properties.Resources.collapse_button_click;
|
||||
this.CollapseHelpButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.collapse_button_hover;
|
||||
this.CollapseHelpButton.Image = global::MouseWithoutBorders.Properties.Resources.collapse_button_normal;
|
||||
this.CollapseHelpButton.DownImage = global::MouseWithoutBorders.Properties.Images.collapse_button_click;
|
||||
this.CollapseHelpButton.HoverImage = global::MouseWithoutBorders.Properties.Images.collapse_button_hover;
|
||||
this.CollapseHelpButton.Image = global::MouseWithoutBorders.Properties.Images.collapse_button_normal;
|
||||
this.CollapseHelpButton.Location = new System.Drawing.Point(360, 211);
|
||||
this.CollapseHelpButton.Name = "CollapseHelpButton";
|
||||
this.CollapseHelpButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.collapse_button_normal;
|
||||
this.CollapseHelpButton.NormalImage = global::MouseWithoutBorders.Properties.Images.collapse_button_normal;
|
||||
this.CollapseHelpButton.Size = new System.Drawing.Size(11, 11);
|
||||
this.CollapseHelpButton.TabIndex = 25;
|
||||
this.CollapseHelpButton.TabStop = false;
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.Image = global::MouseWithoutBorders.Properties.Resources.Mouse;
|
||||
this.pictureBox1.Image = global::MouseWithoutBorders.Properties.Images.Mouse;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(206, 365);
|
||||
this.pictureBox1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
// ExamplePicture
|
||||
//
|
||||
this.ExamplePicture.Image = global::MouseWithoutBorders.Properties.Resources.copy_paste_example;
|
||||
this.ExamplePicture.Image = global::MouseWithoutBorders.Properties.Images.copy_paste_example;
|
||||
this.ExamplePicture.Location = new System.Drawing.Point(101, 251);
|
||||
this.ExamplePicture.Name = "ExamplePicture";
|
||||
this.ExamplePicture.Size = new System.Drawing.Size(251, 79);
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
public partial class SetupPage3a : SettingsFormPage
|
||||
{
|
||||
private readonly Image[] _frames = { Resources.copy_paste_example, Resources.drag_example, Resources.keyboard_example };
|
||||
private readonly Image[] _frames = { Images.copy_paste_example, Images.drag_example, Images.keyboard_example };
|
||||
private readonly string[] _messages =
|
||||
{
|
||||
"Copy && paste across screens",
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
// ExamplePicture
|
||||
//
|
||||
this.ExamplePicture.Image = global::MouseWithoutBorders.Properties.Resources.combined_example;
|
||||
this.ExamplePicture.Image = global::MouseWithoutBorders.Properties.Images.combined_example;
|
||||
this.ExamplePicture.Location = new System.Drawing.Point(75, 283);
|
||||
this.ExamplePicture.Name = "ExamplePicture";
|
||||
this.ExamplePicture.Size = new System.Drawing.Size(307, 25);
|
||||
@@ -119,12 +119,12 @@ namespace MouseWithoutBorders
|
||||
// NextButton
|
||||
//
|
||||
this.NextButton.DisabledImage = null;
|
||||
this.NextButton.DownImage = global::MouseWithoutBorders.Properties.Resources.next_button_click;
|
||||
this.NextButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.next_button_hover;
|
||||
this.NextButton.Image = global::MouseWithoutBorders.Properties.Resources.next_button_normal;
|
||||
this.NextButton.DownImage = global::MouseWithoutBorders.Properties.Images.next_button_click;
|
||||
this.NextButton.HoverImage = global::MouseWithoutBorders.Properties.Images.next_button_hover;
|
||||
this.NextButton.Image = global::MouseWithoutBorders.Properties.Images.next_button_normal;
|
||||
this.NextButton.Location = new System.Drawing.Point(199, 366);
|
||||
this.NextButton.Name = "NextButton";
|
||||
this.NextButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.next_button_normal;
|
||||
this.NextButton.NormalImage = global::MouseWithoutBorders.Properties.Images.next_button_normal;
|
||||
this.NextButton.Size = new System.Drawing.Size(55, 55);
|
||||
this.NextButton.TabIndex = 16;
|
||||
this.NextButton.TabStop = false;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.Image = global::MouseWithoutBorders.Properties.Resources.Mouse;
|
||||
this.pictureBox1.Image = global::MouseWithoutBorders.Properties.Images.Mouse;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(206, 40);
|
||||
this.pictureBox1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
@@ -106,12 +106,12 @@ namespace MouseWithoutBorders
|
||||
// DoneButton
|
||||
//
|
||||
this.DoneButton.DisabledImage = null;
|
||||
this.DoneButton.DownImage = global::MouseWithoutBorders.Properties.Resources.done_button_click;
|
||||
this.DoneButton.HoverImage = global::MouseWithoutBorders.Properties.Resources.done_button_hover;
|
||||
this.DoneButton.Image = global::MouseWithoutBorders.Properties.Resources.done_button_normal;
|
||||
this.DoneButton.DownImage = global::MouseWithoutBorders.Properties.Images.done_button_click;
|
||||
this.DoneButton.HoverImage = global::MouseWithoutBorders.Properties.Images.done_button_hover;
|
||||
this.DoneButton.Image = global::MouseWithoutBorders.Properties.Images.done_button_normal;
|
||||
this.DoneButton.Location = new System.Drawing.Point(199, 366);
|
||||
this.DoneButton.Name = "DoneButton";
|
||||
this.DoneButton.NormalImage = global::MouseWithoutBorders.Properties.Resources.done_button_normal;
|
||||
this.DoneButton.NormalImage = global::MouseWithoutBorders.Properties.Images.done_button_normal;
|
||||
this.DoneButton.Size = new System.Drawing.Size(55, 56);
|
||||
this.DoneButton.TabIndex = 26;
|
||||
this.DoneButton.TabStop = false;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
// logoPictureBox
|
||||
//
|
||||
this.logoPictureBox.ErrorImage = null;
|
||||
this.logoPictureBox.Image = global::MouseWithoutBorders.Properties.Resources.Logo;
|
||||
this.logoPictureBox.Image = global::MouseWithoutBorders.Properties.Images.Logo;
|
||||
this.logoPictureBox.Location = new System.Drawing.Point(12, 12);
|
||||
this.logoPictureBox.Name = "logoPictureBox";
|
||||
this.logoPictureBox.Size = new System.Drawing.Size(131, 136);
|
||||
|
||||
@@ -452,6 +452,7 @@ namespace MouseWithoutBorders
|
||||
//
|
||||
// checkBoxVKMap
|
||||
//
|
||||
this.checkBoxVKMap.Enabled = false;
|
||||
this.checkBoxVKMap.AutoSize = true;
|
||||
this.checkBoxVKMap.Location = new System.Drawing.Point(268, 98);
|
||||
this.checkBoxVKMap.Name = "checkBoxVKMap";
|
||||
|
||||
@@ -411,8 +411,8 @@ namespace MouseWithoutBorders
|
||||
AddNewMachine();
|
||||
}
|
||||
|
||||
checkBoxVKMap.Checked = Setting.Values.UseVKMap;
|
||||
|
||||
// NOTE(@yuyoyuppe): this option is deprecated
|
||||
// checkBoxVKMap.Checked = Setting.Values.UseVKMap;
|
||||
foreach (Machine m in machines)
|
||||
{
|
||||
if (m.StatusClient != SocketStatus.NA)
|
||||
@@ -729,8 +729,9 @@ namespace MouseWithoutBorders
|
||||
checkBoxDrawMouse.Checked = Setting.Values.DrawMouse;
|
||||
checkBoxReverseLookup.Checked = Setting.Values.ReverseLookup;
|
||||
checkBoxSameSubNet.Checked = Setting.Values.SameSubNetOnly;
|
||||
checkBoxVKMap.Checked = Setting.Values.UseVKMap;
|
||||
|
||||
// NOTE(@yuyoyuppe): this option is deprecated
|
||||
// checkBoxVKMap.Checked = Setting.Values.UseVKMap;
|
||||
foreach (Machine m in machines)
|
||||
{
|
||||
m.MachineName = string.Empty;
|
||||
@@ -1088,7 +1089,8 @@ namespace MouseWithoutBorders
|
||||
|
||||
private void CheckBoxVKMap_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Setting.Values.UseVKMap = checkBoxVKMap.Checked;
|
||||
// NOTE(@yuyoyuppe): this option is deprecated
|
||||
// Setting.Values.UseVKMap = checkBoxVKMap.Checked;
|
||||
ShowUpdateMessage();
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
// picLogonLogo
|
||||
//
|
||||
this.picLogonLogo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
|
||||
this.picLogonLogo.Image = global::MouseWithoutBorders.Properties.Resources.MouseWithoutBorders;
|
||||
this.picLogonLogo.Image = global::MouseWithoutBorders.Properties.Images.MouseWithoutBorders;
|
||||
this.picLogonLogo.Location = new System.Drawing.Point(99, 62);
|
||||
this.picLogonLogo.Name = "picLogonLogo";
|
||||
this.picLogonLogo.Size = new System.Drawing.Size(95, 17);
|
||||
|
||||
@@ -433,6 +433,11 @@ namespace MouseWithoutBorders
|
||||
Program.DotForm.TopMost = true;
|
||||
Program.DotForm.Show();
|
||||
Application.DoEvents();
|
||||
|
||||
// Simulate input to help bring to the foreground, as it doesn't seem to work in every case otherwise.
|
||||
NativeMethods.INPUT input = new NativeMethods.INPUT { type = (int)NativeMethods.InputType.INPUT_MOUSE, mi = { } };
|
||||
NativeMethods.INPUT[] inputs = new NativeMethods.INPUT[] { input };
|
||||
_ = NativeMethods.SendInput(1, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT)));
|
||||
m.Result = SetForeGround() ? new IntPtr(1) : IntPtr.Zero;
|
||||
break;
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ namespace MouseWithoutBorders
|
||||
CallingConvention = CallingConvention.StdCall)]
|
||||
internal static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
|
||||
|
||||
private enum InputType
|
||||
internal enum InputType
|
||||
{
|
||||
INPUT_MOUSE = 0,
|
||||
INPUT_KEYBOARD = 1,
|
||||
|
||||
@@ -22,14 +22,14 @@ namespace MouseWithoutBorders.Properties {
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
internal class Images {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
internal Images() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -39,7 +39,7 @@ namespace MouseWithoutBorders.Properties {
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MouseWithoutBorders.Properties.Resources", typeof(Resources).Assembly);
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MouseWithoutBorders.Properties.Images", typeof(Images).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
@@ -10,13 +10,14 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using PowerOCR.Helpers;
|
||||
using PowerOCR.Models;
|
||||
using Windows.Globalization;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Media.Ocr;
|
||||
@@ -26,6 +27,26 @@ namespace PowerOCR;
|
||||
|
||||
internal sealed class ImageMethods
|
||||
{
|
||||
internal static Bitmap PadImage(Bitmap image, int minW = 64, int minH = 64)
|
||||
{
|
||||
if (image.Height >= minH && image.Width >= minW)
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
int width = Math.Max(image.Width + 16, minW + 16);
|
||||
int height = Math.Max(image.Height + 16, minH + 16);
|
||||
|
||||
// Create a compatible bitmap
|
||||
Bitmap dest = new(width, height, image.PixelFormat);
|
||||
using Graphics gd = Graphics.FromImage(dest);
|
||||
|
||||
gd.Clear(image.GetPixel(0, 0));
|
||||
gd.DrawImageUnscaled(image, 8, 8);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
internal static ImageSource GetWindowBoundsImage(Window passedWindow)
|
||||
{
|
||||
bool isGrabFrame = false;
|
||||
@@ -46,7 +67,7 @@ internal sealed class ImageMethods
|
||||
windowHeight -= (int)(70 * dpi.DpiScaleY);
|
||||
}
|
||||
|
||||
using Bitmap bmp = new Bitmap(windowWidth, windowHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
using Bitmap bmp = new(windowWidth, windowHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
using Graphics g = Graphics.FromImage(bmp);
|
||||
|
||||
g.CopyFromScreen(thisCorrectedLeft, thisCorrectedTop, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
|
||||
@@ -55,7 +76,7 @@ internal sealed class ImageMethods
|
||||
|
||||
internal static async Task<string> GetRegionsText(Window? passedWindow, Rectangle selectedRegion, Language? preferredLanguage)
|
||||
{
|
||||
using Bitmap bmp = new Bitmap(selectedRegion.Width, selectedRegion.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
Bitmap bmp = new(selectedRegion.Width, selectedRegion.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
using Graphics g = Graphics.FromImage(bmp);
|
||||
|
||||
System.Windows.Point absPosPoint = passedWindow == null ? default(System.Windows.Point) : passedWindow.GetAbsolutePosition();
|
||||
@@ -65,7 +86,7 @@ internal sealed class ImageMethods
|
||||
|
||||
g.CopyFromScreen(thisCorrectedLeft, thisCorrectedTop, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
|
||||
|
||||
// bmp = PadImage(bmp);
|
||||
bmp = PadImage(bmp);
|
||||
string? resultText = await ExtractText(bmp, preferredLanguage);
|
||||
|
||||
return resultText != null ? resultText.Trim() : string.Empty;
|
||||
@@ -74,7 +95,7 @@ internal sealed class ImageMethods
|
||||
internal static async Task<string> GetClickedWord(Window passedWindow, System.Windows.Point clickedPoint, Language? preferredLanguage)
|
||||
{
|
||||
DpiScale dpi = VisualTreeHelper.GetDpi(passedWindow);
|
||||
Bitmap bmp = new Bitmap((int)(passedWindow.ActualWidth * dpi.DpiScaleX), (int)(passedWindow.ActualHeight * dpi.DpiScaleY), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
Bitmap bmp = new((int)(passedWindow.ActualWidth * dpi.DpiScaleX), (int)(passedWindow.ActualHeight * dpi.DpiScaleY), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
Graphics g = Graphics.FromImage(bmp);
|
||||
|
||||
System.Windows.Point absPosPoint = passedWindow.GetAbsolutePosition();
|
||||
@@ -91,35 +112,17 @@ internal sealed class ImageMethods
|
||||
|
||||
public static async Task<string> ExtractText(Bitmap bmp, Language? preferredLanguage, System.Windows.Point? singlePoint = null)
|
||||
{
|
||||
Language? selectedLanguage = preferredLanguage;
|
||||
if (selectedLanguage == null)
|
||||
{
|
||||
selectedLanguage = GetOCRLanguage();
|
||||
}
|
||||
|
||||
Language? selectedLanguage = preferredLanguage ?? GetOCRLanguage();
|
||||
if (selectedLanguage == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
bool isCJKLang = false;
|
||||
|
||||
if (selectedLanguage.LanguageTag.StartsWith("zh", StringComparison.InvariantCultureIgnoreCase) == true)
|
||||
{
|
||||
isCJKLang = true;
|
||||
}
|
||||
else if (selectedLanguage.LanguageTag.StartsWith("ja", StringComparison.InvariantCultureIgnoreCase) == true)
|
||||
{
|
||||
isCJKLang = true;
|
||||
}
|
||||
else if (selectedLanguage.LanguageTag.StartsWith("ko", StringComparison.InvariantCultureIgnoreCase) == true)
|
||||
{
|
||||
isCJKLang = true;
|
||||
}
|
||||
|
||||
XmlLanguage lang = XmlLanguage.GetLanguage(selectedLanguage.LanguageTag);
|
||||
CultureInfo culture = lang.GetEquivalentCulture();
|
||||
|
||||
bool isSpaceJoiningLang = LanguageHelper.IsLanguageSpaceJoining(selectedLanguage);
|
||||
|
||||
bool scaleBMP = true;
|
||||
|
||||
if (singlePoint != null
|
||||
@@ -129,68 +132,38 @@ internal sealed class ImageMethods
|
||||
}
|
||||
|
||||
using Bitmap scaledBitmap = scaleBMP ? ScaleBitmapUniform(bmp, 1.5) : ScaleBitmapUniform(bmp, 1.0);
|
||||
StringBuilder text = new StringBuilder();
|
||||
StringBuilder text = new();
|
||||
|
||||
await using (MemoryStream memory = new MemoryStream())
|
||||
await using MemoryStream memoryStream = new();
|
||||
using WrappingStream wrappingStream = new(memoryStream);
|
||||
|
||||
scaledBitmap.Save(wrappingStream, ImageFormat.Bmp);
|
||||
wrappingStream.Position = 0;
|
||||
BitmapDecoder bmpDecoder = await BitmapDecoder.CreateAsync(wrappingStream.AsRandomAccessStream());
|
||||
SoftwareBitmap softwareBmp = await bmpDecoder.GetSoftwareBitmapAsync();
|
||||
|
||||
OcrEngine ocrEngine = OcrEngine.TryCreateFromLanguage(selectedLanguage);
|
||||
OcrResult ocrResult = await ocrEngine.RecognizeAsync(softwareBmp);
|
||||
|
||||
GC.Collect();
|
||||
|
||||
if (singlePoint == null)
|
||||
{
|
||||
scaledBitmap.Save(memory, ImageFormat.Bmp);
|
||||
memory.Position = 0;
|
||||
BitmapDecoder bmpDecoder = await BitmapDecoder.CreateAsync(memory.AsRandomAccessStream());
|
||||
SoftwareBitmap softwareBmp = await bmpDecoder.GetSoftwareBitmapAsync();
|
||||
|
||||
OcrEngine ocrEngine = OcrEngine.TryCreateFromLanguage(selectedLanguage);
|
||||
OcrResult ocrResult = await ocrEngine.RecognizeAsync(softwareBmp);
|
||||
|
||||
if (singlePoint == null)
|
||||
foreach (OcrLine ocrLine in ocrResult.Lines)
|
||||
{
|
||||
if (isCJKLang == false)
|
||||
{
|
||||
foreach (OcrLine line in ocrResult.Lines)
|
||||
{
|
||||
text.AppendLine(line.Text);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Kanji, Hiragana, Katakana, Hankaku-Katakana do not need blank.(not only the symbol in CJKUnifiedIdeographs).
|
||||
// Maybe there are more symbols that don't require spaces like \u3001 \u3002.
|
||||
// var cjkRegex = new Regex(@"\p{IsCJKUnifiedIdeographs}|\p{IsHiragana}|\p{IsKatakana}|[\uFF61-\uFF9F]|[\u3000-\u3003]");
|
||||
var cjkRegex = new Regex(@"\p{IsCJKUnifiedIdeographs}|\p{IsHiragana}|\p{IsKatakana}|[\uFF61-\uFF9F]");
|
||||
|
||||
foreach (OcrLine ocrLine in ocrResult.Lines)
|
||||
{
|
||||
bool isBeginning = true;
|
||||
bool isCJKPrev = false;
|
||||
foreach (OcrWord ocrWord in ocrLine.Words)
|
||||
{
|
||||
bool isCJK = cjkRegex.IsMatch(ocrWord.Text);
|
||||
|
||||
// Use spaces to separate non-CJK words.
|
||||
if (!isBeginning && (!isCJK || !isCJKPrev))
|
||||
{
|
||||
_ = text.Append(' ');
|
||||
}
|
||||
|
||||
_ = text.Append(ocrWord.Text);
|
||||
isCJKPrev = isCJK;
|
||||
isBeginning = false;
|
||||
}
|
||||
|
||||
text.Append(Environment.NewLine);
|
||||
}
|
||||
}
|
||||
ocrLine.GetTextFromOcrLine(isSpaceJoiningLang, text);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
Windows.Foundation.Point fPoint = new Windows.Foundation.Point(singlePoint.Value.X, singlePoint.Value.Y);
|
||||
foreach (OcrLine ocrLine in ocrResult.Lines)
|
||||
{
|
||||
Windows.Foundation.Point fPoint = new Windows.Foundation.Point(singlePoint.Value.X, singlePoint.Value.Y);
|
||||
foreach (OcrLine ocrLine in ocrResult.Lines)
|
||||
foreach (OcrWord ocrWord in ocrLine.Words)
|
||||
{
|
||||
foreach (OcrWord ocrWord in ocrLine.Words)
|
||||
if (ocrWord.BoundingRect.Contains(fPoint))
|
||||
{
|
||||
if (ocrWord.BoundingRect.Contains(fPoint))
|
||||
{
|
||||
_ = text.Append(ocrWord.Text);
|
||||
}
|
||||
_ = text.Append(ocrWord.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +178,7 @@ internal sealed class ImageMethods
|
||||
{
|
||||
List<string> wordArray = textLine.Split().ToList();
|
||||
wordArray.Reverse();
|
||||
_ = isCJKLang == true ? text.Append(string.Join(string.Empty, wordArray)) : text.Append(string.Join(' ', wordArray));
|
||||
_ = text.Append(string.Join(' ', wordArray));
|
||||
|
||||
if (textLine.Length > 0)
|
||||
{
|
||||
@@ -223,27 +196,29 @@ internal sealed class ImageMethods
|
||||
|
||||
public static Bitmap ScaleBitmapUniform(Bitmap passedBitmap, double scale)
|
||||
{
|
||||
using MemoryStream memory = new MemoryStream();
|
||||
passedBitmap.Save(memory, ImageFormat.Bmp);
|
||||
memory.Position = 0;
|
||||
BitmapImage bitmapimage = new BitmapImage();
|
||||
using MemoryStream memoryStream = new();
|
||||
using WrappingStream wrappingStream = new(memoryStream);
|
||||
passedBitmap.Save(wrappingStream, ImageFormat.Bmp);
|
||||
wrappingStream.Position = 0;
|
||||
BitmapImage bitmapimage = new();
|
||||
bitmapimage.BeginInit();
|
||||
bitmapimage.StreamSource = memory;
|
||||
bitmapimage.StreamSource = wrappingStream;
|
||||
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapimage.EndInit();
|
||||
bitmapimage.Freeze();
|
||||
TransformedBitmap transformedBmp = new TransformedBitmap();
|
||||
TransformedBitmap transformedBmp = new();
|
||||
transformedBmp.BeginInit();
|
||||
transformedBmp.Source = bitmapimage;
|
||||
transformedBmp.Transform = new ScaleTransform(scale, scale);
|
||||
transformedBmp.EndInit();
|
||||
transformedBmp.Freeze();
|
||||
GC.Collect();
|
||||
return BitmapSourceToBitmap(transformedBmp);
|
||||
}
|
||||
|
||||
public static Bitmap BitmapSourceToBitmap(BitmapSource source)
|
||||
{
|
||||
Bitmap bmp = new Bitmap(
|
||||
Bitmap bmp = new(
|
||||
source.PixelWidth,
|
||||
source.PixelHeight,
|
||||
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
|
||||
@@ -257,21 +232,24 @@ internal sealed class ImageMethods
|
||||
data.Height * data.Stride,
|
||||
data.Stride);
|
||||
bmp.UnlockBits(data);
|
||||
GC.Collect();
|
||||
return bmp;
|
||||
}
|
||||
|
||||
internal static BitmapImage BitmapToImageSource(Bitmap bitmap)
|
||||
{
|
||||
using MemoryStream memory = new MemoryStream();
|
||||
bitmap.Save(memory, ImageFormat.Bmp);
|
||||
memory.Position = 0;
|
||||
BitmapImage bitmapimage = new BitmapImage();
|
||||
using MemoryStream memoryStream = new();
|
||||
using WrappingStream wrappingStream = new(memoryStream);
|
||||
|
||||
bitmap.Save(wrappingStream, ImageFormat.Bmp);
|
||||
wrappingStream.Position = 0;
|
||||
BitmapImage bitmapimage = new();
|
||||
bitmapimage.BeginInit();
|
||||
bitmapimage.StreamSource = memory;
|
||||
bitmapimage.StreamSource = wrappingStream;
|
||||
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapimage.EndInit();
|
||||
bitmapimage.Freeze();
|
||||
|
||||
GC.Collect();
|
||||
return bitmapimage;
|
||||
}
|
||||
|
||||
@@ -280,7 +258,7 @@ internal sealed class ImageMethods
|
||||
// use currently selected Language
|
||||
string inputLang = InputLanguageManager.Current.CurrentInputLanguage.Name;
|
||||
|
||||
Language? selectedLanguage = new Language(inputLang);
|
||||
Language? selectedLanguage = new(inputLang);
|
||||
List<Language> possibleOcrLanguages = OcrEngine.AvailableRecognizerLanguages.ToList();
|
||||
|
||||
if (possibleOcrLanguages.Count < 1)
|
||||
|
||||
26
src/modules/PowerOCR/PowerOCR/Helpers/LanguageHelper.cs
Normal file
26
src/modules/PowerOCR/PowerOCR/Helpers/LanguageHelper.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 Windows.Globalization;
|
||||
|
||||
namespace PowerOCR.Helpers
|
||||
{
|
||||
internal static class LanguageHelper
|
||||
{
|
||||
public static bool IsLanguageSpaceJoining(Language selectedLanguage)
|
||||
{
|
||||
if (selectedLanguage.LanguageTag.StartsWith("zh", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (selectedLanguage.LanguageTag.Equals("ja", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/modules/PowerOCR/PowerOCR/Helpers/OcrExtensions.cs
Normal file
54
src/modules/PowerOCR/PowerOCR/Helpers/OcrExtensions.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
// 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.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Windows.Media.Ocr;
|
||||
|
||||
namespace PowerOCR.Helpers
|
||||
{
|
||||
internal static class OcrExtensions
|
||||
{
|
||||
public static void GetTextFromOcrLine(this OcrLine ocrLine, bool isSpaceJoiningOCRLang, StringBuilder text)
|
||||
{
|
||||
// (when OCR language is zh or ja)
|
||||
// matches words in a space-joining language, which contains:
|
||||
// - one letter that is not in "other letters" (CJK characters are "other letters")
|
||||
// - one number digit
|
||||
// - any words longer than one character
|
||||
// Chinese and Japanese characters are single-character words
|
||||
// when a word is one punctuation/symbol, join it without spaces
|
||||
if (isSpaceJoiningOCRLang)
|
||||
{
|
||||
text.AppendLine(ocrLine.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isFirstWord = true;
|
||||
bool isPrevWordSpaceJoining = false;
|
||||
|
||||
Regex regexSpaceJoiningWord = new(@"(^[\p{L}-[\p{Lo}]]|\p{Nd}$)|.{2,}");
|
||||
|
||||
foreach (OcrWord ocrWord in ocrLine.Words)
|
||||
{
|
||||
string wordString = ocrWord.Text;
|
||||
|
||||
bool isThisWordSpaceJoining = regexSpaceJoiningWord.IsMatch(wordString);
|
||||
|
||||
if (isFirstWord || (!isThisWordSpaceJoining && !isPrevWordSpaceJoining))
|
||||
{
|
||||
_ = text.Append(wordString);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = text.Append(' ').Append(wordString);
|
||||
}
|
||||
|
||||
isFirstWord = false;
|
||||
isPrevWordSpaceJoining = isThisWordSpaceJoining;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
228
src/modules/PowerOCR/PowerOCR/Helpers/WrappingStream.cs
Normal file
228
src/modules/PowerOCR/PowerOCR/Helpers/WrappingStream.cs
Normal file
@@ -0,0 +1,228 @@
|
||||
// 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;
|
||||
|
||||
namespace PowerOCR.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Stream"/> that wraps another stream. The major feature of <see cref="WrappingStream"/> is that it does not dispose the
|
||||
/// underlying stream when it is disposed; this is useful when using classes such as <see cref="BinaryReader"/> and
|
||||
/// <see cref="System.Security.Cryptography.CryptoStream"/> that take ownership of the stream passed to their constructors.
|
||||
/// </summary>
|
||||
public class WrappingStream : Stream
|
||||
{
|
||||
private Stream? _streamBase;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WrappingStream"/> class.
|
||||
/// </summary>
|
||||
/// <param name="streamBase">The wrapped stream.</param>
|
||||
public WrappingStream(Stream streamBase)
|
||||
{
|
||||
_streamBase = streamBase ?? throw new ArgumentNullException(nameof(streamBase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports reading.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the stream supports reading; otherwise, <c>false</c>.</returns>
|
||||
public override bool CanRead => _streamBase != null && _streamBase.CanRead;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports seeking.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the stream supports seeking; otherwise, <c>false</c>.</returns>
|
||||
public override bool CanSeek => _streamBase != null && _streamBase.CanSeek;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current stream supports writing.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the stream supports writing; otherwise, <c>false</c>.</returns>
|
||||
public override bool CanWrite => _streamBase != null && _streamBase.CanWrite;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length in bytes of the stream.
|
||||
/// </summary>
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return _streamBase is not null ? _streamBase.Length : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the position within the current stream.
|
||||
/// </summary>
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return _streamBase is not null ? _streamBase.Position : 0;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (_streamBase is not null)
|
||||
{
|
||||
_streamBase.Position = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins an asynchronous read operation.
|
||||
/// </summary>
|
||||
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _streamBase is not null && callback is not null && state is not null
|
||||
? _streamBase.BeginRead(buffer, offset, count, callback, state)
|
||||
: new NullAsyncResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins an asynchronous write operation.
|
||||
/// </summary>
|
||||
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _streamBase is not null && callback is not null && state is not null
|
||||
? _streamBase.BeginWrite(buffer, offset, count, callback, state)
|
||||
: new NullAsyncResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the pending asynchronous read to complete.
|
||||
/// </summary>
|
||||
public override int EndRead(IAsyncResult asyncResult)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _streamBase is not null ? _streamBase.EndRead(asyncResult) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ends an asynchronous write operation.
|
||||
/// </summary>
|
||||
public override void EndWrite(IAsyncResult asyncResult)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
_streamBase?.EndWrite(asyncResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
|
||||
/// </summary>
|
||||
public override void Flush()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
_streamBase?.Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a sequence of bytes from the current stream and advances the position
|
||||
/// within the stream by the number of bytes read.
|
||||
/// </summary>
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _streamBase is not null ? _streamBase.Read(buffer, offset, count) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.
|
||||
/// </summary>
|
||||
public override int ReadByte()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _streamBase is not null ? _streamBase.ReadByte() : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position within the current stream.
|
||||
/// </summary>
|
||||
/// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>
|
||||
/// <param name="origin">A value of type see System.IO.SeekOrigin indicating the reference point used to obtain the new position.</param>
|
||||
/// <returns>The new position within the current stream.</returns>
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _streamBase is not null ? _streamBase.Seek(offset, origin) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the length of the current stream.
|
||||
/// </summary>
|
||||
/// <param name="value">The desired length of the current stream in bytes.</param>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
_streamBase?.SetLength(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a sequence of bytes to the current stream and advances the current position
|
||||
/// within this stream by the number of bytes written.
|
||||
/// </summary>
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
_streamBase?.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a byte to the current position in the stream and advances the position within the stream by one byte.
|
||||
/// </summary>
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
_streamBase?.WriteByte(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the wrapped stream.
|
||||
/// </summary>
|
||||
/// <value>The wrapped stream.</value>
|
||||
protected Stream? WrappedStream => _streamBase;
|
||||
|
||||
/// <summary>
|
||||
/// Releases the unmanaged resources used by the <see cref="WrappingStream"/> and optionally releases the managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
// doesn't close the base stream, but just prevents access to it through this WrappingStream
|
||||
if (disposing)
|
||||
{
|
||||
_streamBase = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
// throws an ObjectDisposedException if this object has been disposed
|
||||
if (_streamBase == null)
|
||||
{
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/modules/PowerOCR/PowerOCR/Models/NullAsyncResult.cs
Normal file
19
src/modules/PowerOCR/PowerOCR/Models/NullAsyncResult.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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.Threading;
|
||||
|
||||
namespace PowerOCR.Models;
|
||||
|
||||
public class NullAsyncResult : IAsyncResult
|
||||
{
|
||||
public object? AsyncState => null;
|
||||
|
||||
public WaitHandle AsyncWaitHandle => new NullWaitHandle();
|
||||
|
||||
public bool CompletedSynchronously => true;
|
||||
|
||||
public bool IsCompleted => true;
|
||||
}
|
||||
11
src/modules/PowerOCR/PowerOCR/Models/NullWaitHandle.cs
Normal file
11
src/modules/PowerOCR/PowerOCR/Models/NullWaitHandle.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
// 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.Threading;
|
||||
|
||||
namespace PowerOCR.Models;
|
||||
|
||||
public class NullWaitHandle : WaitHandle
|
||||
{
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public partial class OCROverlay : Window
|
||||
|
||||
private bool IsSelecting { get; set; }
|
||||
|
||||
private Border selectBorder = new Border();
|
||||
private Border selectBorder = new();
|
||||
|
||||
private DpiScale? dpiScale;
|
||||
|
||||
@@ -57,7 +57,7 @@ public partial class OCROverlay : Window
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var userSettings = new UserSettings(new Helpers.ThrottledActionInvoker());
|
||||
var userSettings = new UserSettings(new ThrottledActionInvoker());
|
||||
string? selectedLanguageName = userSettings.PreferredLanguage.Value;
|
||||
|
||||
// build context menu
|
||||
@@ -70,7 +70,7 @@ public partial class OCROverlay : Window
|
||||
List<Language> possibleOcrLanguages = OcrEngine.AvailableRecognizerLanguages.ToList();
|
||||
foreach (Language language in possibleOcrLanguages)
|
||||
{
|
||||
MenuItem menuItem = new MenuItem() { Header = language.NativeName, Tag = language, IsCheckable = true };
|
||||
MenuItem menuItem = new() { Header = language.NativeName, Tag = language, IsCheckable = true };
|
||||
menuItem.IsChecked = language.DisplayName.Equals(selectedLanguageName, StringComparison.Ordinal);
|
||||
if (language.DisplayName.Equals(selectedLanguageName, StringComparison.Ordinal))
|
||||
{
|
||||
@@ -94,9 +94,8 @@ public partial class OCROverlay : Window
|
||||
MenuItem menuItem = (MenuItem)sender;
|
||||
foreach (var item in CanvasContextMenu.Items)
|
||||
{
|
||||
if (item is MenuItem)
|
||||
if (item is MenuItem menuItemLoop)
|
||||
{
|
||||
MenuItem menuItemLoop = (MenuItem)item;
|
||||
menuItemLoop.IsChecked = item.Equals(menuItem);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +194,7 @@ public partial class OCROverlay : Window
|
||||
Canvas.SetTop(selectBorder, clickedPoint.Y);
|
||||
|
||||
var screens = System.Windows.Forms.Screen.AllScreens;
|
||||
System.Drawing.Point formsPoint = new System.Drawing.Point((int)clickedPoint.X, (int)clickedPoint.Y);
|
||||
System.Drawing.Point formsPoint = new((int)clickedPoint.X, (int)clickedPoint.Y);
|
||||
foreach (var scr in screens)
|
||||
{
|
||||
if (scr.Bounds.Contains(formsPoint))
|
||||
@@ -295,7 +294,7 @@ public partial class OCROverlay : Window
|
||||
double xDimScaled = Canvas.GetLeft(selectBorder) * m.M11;
|
||||
double yDimScaled = Canvas.GetTop(selectBorder) * m.M22;
|
||||
|
||||
System.Drawing.Rectangle regionScaled = new System.Drawing.Rectangle(
|
||||
System.Drawing.Rectangle regionScaled = new(
|
||||
(int)xDimScaled,
|
||||
(int)yDimScaled,
|
||||
(int)(selectBorder.Width * m.M11),
|
||||
|
||||
@@ -24,7 +24,8 @@ bool isExcluded(HWND window)
|
||||
{
|
||||
auto processPath = get_process_path(window);
|
||||
CharUpperBuffW(processPath.data(), static_cast<DWORD>(processPath.length()));
|
||||
return find_app_name_in_path(processPath, AlwaysOnTopSettings::settings().excludedApps);
|
||||
|
||||
return check_excluded_app(window, processPath, AlwaysOnTopSettings::settings().excludedApps);
|
||||
}
|
||||
|
||||
AlwaysOnTop::AlwaysOnTop(bool useLLKH) :
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ColorPicker.Common;
|
||||
using ManagedCommon;
|
||||
@@ -23,6 +24,7 @@ namespace ColorPicker.Settings
|
||||
{
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
private const string ColorPickerModuleName = "ColorPicker";
|
||||
private const string ColorPickerHistoryFilename = "colorHistory.json";
|
||||
private const string DefaultActivationShortcut = "Ctrl + Break";
|
||||
private const int MaxNumberOfRetry = 5;
|
||||
private const int SettingsReadOnChangeDelayInMs = 300;
|
||||
@@ -56,11 +58,7 @@ namespace ColorPicker.Settings
|
||||
{
|
||||
if (!_loadingColorsHistory)
|
||||
{
|
||||
var settings = _settingsUtils.GetSettingsOrDefault<ColorPickerSettings, ColorPickerSettingsVersion1>(ColorPickerModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings);
|
||||
ColorHistory.CollectionChanged -= ColorHistory_CollectionChanged;
|
||||
settings.Properties.ColorHistory = ColorHistory.ToList();
|
||||
ColorHistory.CollectionChanged += ColorHistory_CollectionChanged;
|
||||
settings.Save(_settingsUtils);
|
||||
_settingsUtils.SaveSettings(JsonSerializer.Serialize(ColorHistory, new JsonSerializerOptions { WriteIndented = true }), ColorPickerModuleName, ColorPickerHistoryFilename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,14 +118,31 @@ namespace ColorPicker.Settings
|
||||
ColorHistoryLimit.Value = settings.Properties.ColorHistoryLimit;
|
||||
ShowColorName.Value = settings.Properties.ShowColorName;
|
||||
|
||||
if (settings.Properties.ColorHistory == null)
|
||||
List<string> savedColorHistory = new List<string>();
|
||||
try
|
||||
{
|
||||
settings.Properties.ColorHistory = new System.Collections.Generic.List<string>();
|
||||
string filePath = _settingsUtils.GetSettingsFilePath(ColorPickerModuleName, ColorPickerHistoryFilename);
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
if (settings.Properties.ColorHistory != null)
|
||||
{
|
||||
savedColorHistory = settings.Properties.ColorHistory;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string jsonSettingsString = System.IO.File.ReadAllText(filePath).Trim('\0');
|
||||
savedColorHistory = JsonSerializer.Deserialize<List<string>>(jsonSettingsString);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Logger.LogInfo("ColorPicker colorHistory.json was missing or corrupt");
|
||||
}
|
||||
|
||||
_loadingColorsHistory = true;
|
||||
ColorHistory.Clear();
|
||||
foreach (var item in settings.Properties.ColorHistory)
|
||||
foreach (var item in savedColorHistory)
|
||||
{
|
||||
ColorHistory.Add(item);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
DraggingState::DraggingState(const std::function<void()>& keyUpdateCallback) :
|
||||
m_mouseState(false),
|
||||
m_mouseHook(std::bind(&DraggingState::OnMouseDown, this)),
|
||||
m_secondaryMouseState(false),
|
||||
m_middleMouseState(false),
|
||||
m_mouseHook(std::bind(&DraggingState::OnSecondaryMouseDown, this), std::bind(&DraggingState::OnMiddleMouseDown, this)),
|
||||
m_leftShiftKeyState(keyUpdateCallback),
|
||||
m_rightShiftKeyState(keyUpdateCallback),
|
||||
m_ctrlKeyState(keyUpdateCallback),
|
||||
@@ -45,7 +46,8 @@ void DraggingState::Disable()
|
||||
}
|
||||
|
||||
m_dragging = false;
|
||||
m_mouseState = false;
|
||||
m_secondaryMouseState = false;
|
||||
m_middleMouseState = false;
|
||||
|
||||
m_mouseHook.disable();
|
||||
m_leftShiftKeyState.disable();
|
||||
@@ -58,17 +60,28 @@ void DraggingState::UpdateDraggingState() noexcept
|
||||
// This updates m_dragEnabled depending on if the shift key is being held down
|
||||
if (FancyZonesSettings::settings().shiftDrag)
|
||||
{
|
||||
m_dragging = ((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_mouseState);
|
||||
m_dragging = ((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_secondaryMouseState);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dragging = !((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_mouseState);
|
||||
m_dragging = !((m_leftShiftKeyState.state() || m_rightShiftKeyState.state()) ^ m_secondaryMouseState);
|
||||
}
|
||||
}
|
||||
|
||||
void DraggingState::OnMouseDown()
|
||||
void DraggingState::OnSecondaryMouseDown()
|
||||
{
|
||||
m_mouseState = !m_mouseState;
|
||||
m_secondaryMouseState = !m_secondaryMouseState;
|
||||
m_keyUpdateCallback();
|
||||
}
|
||||
|
||||
void DraggingState::OnMiddleMouseDown()
|
||||
{
|
||||
if (!this->IsDragging())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_middleMouseState = !m_middleMouseState;
|
||||
m_keyUpdateCallback();
|
||||
}
|
||||
|
||||
@@ -79,5 +92,5 @@ bool DraggingState::IsDragging() const noexcept
|
||||
|
||||
bool DraggingState::IsSelectManyZonesState() const noexcept
|
||||
{
|
||||
return m_ctrlKeyState.state();
|
||||
return m_ctrlKeyState.state() || m_middleMouseState;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <FancyZonesLib/KeyState.h>
|
||||
#include <FancyZonesLib/SecondaryMouseButtonsHook.h>
|
||||
#include <FancyZonesLib/MouseButtonsHook.h>
|
||||
|
||||
class DraggingState
|
||||
{
|
||||
@@ -17,10 +17,12 @@ public:
|
||||
bool IsSelectManyZonesState() const noexcept;
|
||||
|
||||
private:
|
||||
void OnMouseDown();
|
||||
void OnSecondaryMouseDown();
|
||||
void OnMiddleMouseDown();
|
||||
|
||||
std::atomic<bool> m_mouseState;
|
||||
SecondaryMouseButtonsHook m_mouseHook;
|
||||
std::atomic<bool> m_secondaryMouseState;
|
||||
std::atomic<bool> m_middleMouseState;
|
||||
MouseButtonsHook m_mouseHook;
|
||||
KeyState<VK_LSHIFT> m_leftShiftKeyState;
|
||||
KeyState<VK_RSHIFT> m_rightShiftKeyState;
|
||||
KeyState<VK_LCONTROL, VK_RCONTROL> m_ctrlKeyState;
|
||||
|
||||
@@ -1236,7 +1236,7 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layout->Type() != FancyZonesDataTypes::ZoneSetLayoutType::Blank)
|
||||
if (layout->Zones().size() > 0)
|
||||
{
|
||||
if (vkCode == VK_UP || vkCode == VK_DOWN)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace FancyZonesDataTypes
|
||||
{
|
||||
enum class ZoneSetLayoutType : int
|
||||
{
|
||||
Blank = -1,
|
||||
Blank,
|
||||
Focus,
|
||||
Columns,
|
||||
Rows,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user