mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-18 18:17:43 +01:00
Compare commits
28 Commits
dev/addNew
...
dev/jsincl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9591950875 | ||
|
|
ef672b5564 | ||
|
|
3aec0a06ac | ||
|
|
51586b43f4 | ||
|
|
74a1a6eca2 | ||
|
|
1212ce2216 | ||
|
|
4df8a97256 | ||
|
|
a6c5420f2a | ||
|
|
09ce610dbb | ||
|
|
076461e460 | ||
|
|
a9123bfc23 | ||
|
|
f7c9c80ab2 | ||
|
|
e19590f258 | ||
|
|
eadcf4b120 | ||
|
|
e7f17495bb | ||
|
|
89be43e15d | ||
|
|
e0949cb4ea | ||
|
|
35b9bcacdb | ||
|
|
50b1342234 | ||
|
|
866518e119 | ||
|
|
fe610d4d0e | ||
|
|
54aab5d109 | ||
|
|
db23992aac | ||
|
|
0ee1befe7b | ||
|
|
f565874fc8 | ||
|
|
438ee39252 | ||
|
|
28304838af | ||
|
|
fc29fc7426 |
20
.github/actions/spell-check/allow/code.txt
vendored
20
.github/actions/spell-check/allow/code.txt
vendored
@@ -21,6 +21,9 @@ Pbgra
|
||||
WHITEONBLACK
|
||||
|
||||
|
||||
# COUNTRIES
|
||||
RUS
|
||||
|
||||
# FILES
|
||||
|
||||
AYUV
|
||||
@@ -128,6 +131,9 @@ XBUTTONDOWN
|
||||
XBUTTONUP
|
||||
XDOWN
|
||||
|
||||
# Prefix
|
||||
pcs
|
||||
|
||||
# User32.SYSTEM_METRICS_INDEX.cs
|
||||
|
||||
CLEANBOOT
|
||||
@@ -220,9 +226,23 @@ TABLETPC
|
||||
artanh
|
||||
arsinh
|
||||
arcosh
|
||||
roundf
|
||||
|
||||
# Linux
|
||||
|
||||
dbus
|
||||
anypass
|
||||
github
|
||||
gpg
|
||||
https
|
||||
ssh
|
||||
ubuntu
|
||||
workarounds
|
||||
|
||||
# For upgrade to check-spelling v0.0.24
|
||||
pwa
|
||||
|
||||
# .NET
|
||||
|
||||
AOT
|
||||
Aot
|
||||
|
||||
10
.github/actions/spell-check/allow/names.txt
vendored
10
.github/actions/spell-check/allow/names.txt
vendored
@@ -44,6 +44,7 @@ Bartosz
|
||||
betadele
|
||||
betsegaw
|
||||
bricelam
|
||||
bsky
|
||||
CCcat
|
||||
Chinh
|
||||
chrdavis
|
||||
@@ -53,6 +54,7 @@ Coplen
|
||||
craigloewen
|
||||
crutkas
|
||||
damienleroy
|
||||
daverayment
|
||||
davidegiacometti
|
||||
debian
|
||||
Deibisu
|
||||
@@ -64,6 +66,7 @@ Essey
|
||||
ethanfangg
|
||||
ferraridavide
|
||||
frankychen
|
||||
Gaarden
|
||||
gaardmark
|
||||
gabime
|
||||
Galaxi
|
||||
@@ -71,6 +74,7 @@ Garside
|
||||
Gershaft
|
||||
Giordani
|
||||
Gokce
|
||||
gordon
|
||||
grzhan
|
||||
Guo
|
||||
hanselman
|
||||
@@ -82,6 +86,7 @@ Horvalds
|
||||
Howett
|
||||
htcfreek
|
||||
Huynh
|
||||
Ionut
|
||||
Jaswal
|
||||
jefflord
|
||||
Jordi
|
||||
@@ -90,11 +95,13 @@ Kairu
|
||||
Kamra
|
||||
Kantarci
|
||||
Karthick
|
||||
kaylacinnamon
|
||||
kevinguo
|
||||
Krigun
|
||||
Lambson
|
||||
Laute
|
||||
laviusmotileng
|
||||
Leilei
|
||||
Luecking
|
||||
Mahalingam
|
||||
Markovic
|
||||
@@ -110,6 +117,7 @@ nathancartlidge
|
||||
Nemeth
|
||||
nielslaute
|
||||
oldnewthing
|
||||
onegreatworld
|
||||
palenshus
|
||||
pedrolamas
|
||||
peteblois
|
||||
@@ -120,6 +128,7 @@ Pylyp
|
||||
quachpas
|
||||
Quriz
|
||||
randyrants
|
||||
rayment
|
||||
ricardosantos
|
||||
riri
|
||||
ritchielawrence
|
||||
@@ -148,6 +157,7 @@ waaverecords
|
||||
Whuihuan
|
||||
Xpg
|
||||
ycv
|
||||
yeelam
|
||||
Yuniardi
|
||||
yuyoyuppe
|
||||
Zeol
|
||||
|
||||
184
.github/actions/spell-check/candidate.patterns
vendored
184
.github/actions/spell-check/candidate.patterns
vendored
@@ -1,3 +1,6 @@
|
||||
# D2D
|
||||
#D?2D
|
||||
|
||||
# marker to ignore all code on line
|
||||
^.*/\* #no-spell-check-line \*/.*$
|
||||
# marker to ignore all code on line
|
||||
@@ -8,7 +11,7 @@
|
||||
^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b
|
||||
|
||||
# patch hunk comments
|
||||
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
|
||||
^@@ -\d+(?:,\d+|) \+\d+(?:,\d+|) @@ .*
|
||||
# git index header
|
||||
index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
|
||||
@@ -26,13 +29,13 @@ index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
# data url in quotes
|
||||
([`'"])data:(?:[^ `'"].*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
|
||||
# data url
|
||||
data:[-a-zA-Z=;:/0-9+]*,\S*
|
||||
\bdata:[-a-zA-Z=;:/0-9+]*,\S*
|
||||
|
||||
# https/http/file urls
|
||||
#(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]
|
||||
#(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/*%?=~_|!:,.;]+[-A-Za-z0-9+&@#/*%=~_|]
|
||||
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
#mailto:[-a-zA-Z=;:/?%&0-9+@._]{3,}
|
||||
|
||||
# magnet urls
|
||||
magnet:[?=:\w]+
|
||||
@@ -152,6 +155,9 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||
# GHSA
|
||||
GHSA(?:-[0-9a-z]{4}){3}
|
||||
|
||||
# GitHub actions
|
||||
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
|
||||
|
||||
# GitLab commit
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
|
||||
# GitLab merge requests
|
||||
@@ -210,7 +216,7 @@ accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
# medium link
|
||||
\blink\.medium\.com/[a-zA-Z0-9]+
|
||||
# medium
|
||||
\bmedium\.com/\@?[^/\s"]+/[-\w]+
|
||||
\bmedium\.com/@?[^/\s"]+/[-\w]+
|
||||
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||
@@ -275,7 +281,7 @@ slack://[a-zA-Z0-9?&=]+
|
||||
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
|
||||
|
||||
# Twitter markdown
|
||||
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
|
||||
\[@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
|
||||
# Twitter hashtag
|
||||
\btwitter\.com/hashtag/[\w?_=&]*
|
||||
# Twitter status
|
||||
@@ -330,7 +336,7 @@ ipfs://[0-9a-zA-Z]{3,}
|
||||
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
|
||||
|
||||
# HyperKitty lists
|
||||
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
|
||||
/archives/list/[^@/]+@[^/\s"]*/message/[^/\s"]*/
|
||||
|
||||
# lists
|
||||
/thread\.html/[^"\s]+
|
||||
@@ -348,7 +354,7 @@ ipfs://[0-9a-zA-Z]{3,}
|
||||
\bopen\.spotify\.com/embed/playlist/\w+
|
||||
|
||||
# Mastodon
|
||||
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
|
||||
\bmastodon\.[-a-z.]*/(?:media/|@)[?&=0-9a-zA-Z_]*
|
||||
|
||||
# scastie
|
||||
\bscastie\.scala-lang\.org/[^/]+/\w+
|
||||
@@ -390,9 +396,9 @@ ipfs://[0-9a-zA-Z]{3,}
|
||||
(?:\\(?:u00|x)1[Bb]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+|)m
|
||||
|
||||
# URL escaped characters
|
||||
\%[0-9A-F][A-F]
|
||||
%[0-9A-F][A-F](?=[A-Za-z])
|
||||
# lower URL escaped characters
|
||||
\%[0-9a-f][a-f](?=[a-z]{2,})
|
||||
%[0-9a-f][a-f](?=[a-z]{2,})
|
||||
# IPv6
|
||||
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
|
||||
# c99 hex digits (not the full format, just one I've seen)
|
||||
@@ -400,7 +406,7 @@ ipfs://[0-9a-zA-Z]{3,}
|
||||
# Punycode
|
||||
\bxn--[-0-9a-z]+
|
||||
# sha
|
||||
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
|
||||
sha\d+:[0-9a-f]*?[a-f]{3,}[0-9a-f]*
|
||||
# sha-... -- uses a fancy capture
|
||||
(\\?['"]|")[0-9a-f]{40,}\g{-1}
|
||||
# hex runs
|
||||
@@ -420,10 +426,13 @@ sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
|
||||
# pki
|
||||
-----BEGIN.*-----END
|
||||
|
||||
# pki (base64)
|
||||
LS0tLS1CRUdJT.*
|
||||
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
|
||||
# integrity
|
||||
integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1}
|
||||
|
||||
@@ -441,20 +450,47 @@ integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1}
|
||||
Name\[[^\]]+\]=.*
|
||||
|
||||
# IServiceProvider / isAThing
|
||||
\b(?:I|isA)(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
(?:\b|_)(?:(?:ns|)I|isA)(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
|
||||
# crypt
|
||||
(['"])\$2[ayb]\$.{56}\g{-1}
|
||||
|
||||
# apache/old crypt
|
||||
(['"]|)\$+(?:apr|)1\$+.{8}\$+.{22}\g{-1}
|
||||
|
||||
# sha1 hash
|
||||
\{SHA\}[-a-zA-Z=;:/0-9+]{3,}
|
||||
|
||||
# machine learning (?)
|
||||
#\b(?i)ml(?=[a-z]{2,})
|
||||
|
||||
# python
|
||||
#\b(?i)py(?!gments|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
|
||||
|
||||
# scrypt / argon
|
||||
\$(?:scrypt|argon\d+[di]*)\$\S+
|
||||
|
||||
# go.sum
|
||||
\bh1:\S+
|
||||
|
||||
# scala imports
|
||||
^import (?:[\w.]|\{\w*?(?:,\s*(?:\w*|\*))+\})+
|
||||
|
||||
# scala modules
|
||||
#("[^"]+"\s*%%?\s*){2,3}"[^"]+"
|
||||
|
||||
# container images
|
||||
image: [-\w./:@]+
|
||||
|
||||
# Docker images
|
||||
^\s*FROM\s+\S+:\S+(?:\s+AS\s+\S+|)
|
||||
|
||||
# `docker images` REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
\s*\S+/\S+\s+\S+\s+[0-9a-f]{8,}\s+\d+\s+(?:hour|day|week)s ago\s+[\d.]+[KMGT]B
|
||||
|
||||
# Intel intrinsics
|
||||
_mm_(?!dd)\w+
|
||||
|
||||
# Input to GitHub JSON
|
||||
content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
|
||||
|
||||
@@ -462,34 +498,44 @@ content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
|
||||
# you'll want to remove the `(?=.*?")` suffix.
|
||||
# The `(?=.*?")` suffix should limit the false positives rate
|
||||
# printf
|
||||
#%(?:(?:(?:hh?|ll?|[jzt])?[diuoxn]|l?[cs]|L?[fega]|p)(?=[a-z]{2,})|(?:X|L?[FEGA]|p)(?=[a-zA-Z]{2,}))(?=[_a-zA-Z]+\b)(?!%)(?=.*?['"])
|
||||
#%(?:(?:(?:hh?|ll?|[jzt])?[diuoxn]|l?[cs]|L?[fega]|p)(?=[a-z]{2,})|(?:X|L?[FEGA])(?=[a-zA-Z]{2,}))(?!%)(?=[_a-zA-Z]+(?!%)\b)(?=.*?['"])
|
||||
|
||||
# Alternative printf
|
||||
# %s
|
||||
%(?:s(?=[a-z]{2,}))(?!%)(?=[_a-zA-Z]+(?!%[^s])\b)(?=.*?['"])
|
||||
|
||||
# Python string prefix / binary prefix
|
||||
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
|
||||
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?=[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
|
||||
(?<!['"])\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)['"](?=[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
|
||||
|
||||
# Regular expressions for (P|p)assword
|
||||
\([A-Z]\|[a-z]\)[a-z]+
|
||||
|
||||
# JavaScript regular expressions
|
||||
# javascript test regex
|
||||
/.*/[gim]*\.test\(
|
||||
/.{3,}/[gim]*\.test\(
|
||||
# javascript match regex
|
||||
\.match\(/[^/\s"]*/[gim]*\s*
|
||||
\.match\(/[^/\s"]{3,}/[gim]*\s*
|
||||
# javascript match regex
|
||||
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
|
||||
\.match\(/\\[b].{3,}?/[gim]*\s*\)(?:;|$)
|
||||
# javascript regex
|
||||
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||
^\s*/\\[b].{3,}?/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||
# javascript replace regex
|
||||
\.replace\(/[^/\s"]*/[gim]*\s*,
|
||||
\.replace\(/[^/\s"]{3,}/[gim]*\s*,
|
||||
# assign regex
|
||||
= /[^*]*?(?:[a-z]{3,}|[A-Z]{3,}|[A-Z][a-z]{2,}).*/
|
||||
= /[^*].*?(?:[a-z]{3,}|[A-Z]{3,}|[A-Z][a-z]{2,}).*/[gi]?(?=\W|$)
|
||||
# perl regex test
|
||||
[!=]~ (?:/.*/|m\{.*?\}|m<.*?>|m([|!/@#,;']).*?\g{-1})
|
||||
|
||||
# perl qr regex
|
||||
(?<!\$)\bqr(?:\{.*?\}|<.*?>|\(.*?\)|([|!/@#,;']).*?\g{-1})
|
||||
|
||||
# perl run
|
||||
perl(?:\s+-[a-zA-Z]\w*)+
|
||||
|
||||
# C network byte conversions
|
||||
#(?:\d|\bh)to(?!ken)(?=[a-z])|to(?=[adhiklpun]\()
|
||||
|
||||
# Go regular expressions
|
||||
regexp?\.MustCompile\(`[^`]*`\)
|
||||
|
||||
@@ -503,14 +549,20 @@ regexp?\.MustCompile\(`[^`]*`\)
|
||||
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
|
||||
|
||||
# node packages
|
||||
(["'])\@[^/'" ]+/[^/'" ]+\g{-1}
|
||||
(["'])@[^/'" ]+/[^/'" ]+\g{-1}
|
||||
|
||||
# go install
|
||||
go install(?:\s+[a-z]+\.[-@\w/.]+)+
|
||||
|
||||
# pom.xml
|
||||
<(?:group|artifact)Id>.*?<
|
||||
|
||||
# jetbrains schema https://youtrack.jetbrains.com/issue/RSRP-489571
|
||||
urn:shemas-jetbrains-com
|
||||
|
||||
# Debian changelog severity
|
||||
[-\w]+ \(.*\) (?:\w+|baseline|unstable|experimental); urgency=(?:low|medium|high|emergency|critical)\b
|
||||
|
||||
# kubernetes pod status lists
|
||||
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
|
||||
@@ -518,9 +570,15 @@ urn:shemas-jetbrains-com
|
||||
# kubectl - pods in CrashLoopBackOff
|
||||
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
|
||||
|
||||
# kubernetes applications
|
||||
\.apps/[-\w]+
|
||||
|
||||
# kubernetes object suffix
|
||||
-[0-9a-f]{10}-\w{5}\s
|
||||
|
||||
# kubernetes crd patterns
|
||||
^\s*pattern: .*$
|
||||
|
||||
# posthog secrets
|
||||
([`'"])phc_[^"',]+\g{-1}
|
||||
|
||||
@@ -532,6 +590,9 @@ urn:shemas-jetbrains-com
|
||||
# xcode api botches
|
||||
customObjectInstantitationMethod
|
||||
|
||||
# msvc api botches
|
||||
PrependWithABINamepsace
|
||||
|
||||
# configure flags
|
||||
.* \| --\w{2,}.*?(?=\w+\s\w+)
|
||||
|
||||
@@ -539,21 +600,34 @@ customObjectInstantitationMethod
|
||||
\.fa-[-a-z0-9]+
|
||||
|
||||
# bearer auth
|
||||
(['"])Bear[e][r] .*?\g{-1}
|
||||
(['"])[Bb]ear[e][r] .*?\g{-1}
|
||||
|
||||
# bearer auth
|
||||
\b[Bb]ear[e][r]:? [-a-zA-Z=;:/0-9+.]+
|
||||
|
||||
# basic auth
|
||||
(['"])Basic [-a-zA-Z=;:/0-9+]{3,}\g{-1}
|
||||
(['"])[Bb]asic [-a-zA-Z=;:/0-9+]{3,}\g{-1}
|
||||
|
||||
# base64 encoded content
|
||||
([`'"])[-a-zA-Z=;:/0-9+]+=\g{-1}
|
||||
#([`'"])[-a-zA-Z=;:/0-9+]{3,}=\g{-1}
|
||||
# base64 encoded content in xml/sgml
|
||||
>[-a-zA-Z=;:/0-9+]+=</
|
||||
>[-a-zA-Z=;:/0-9+]{3,}=</
|
||||
# base64 encoded content, possibly wrapped in mime
|
||||
(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
|
||||
# base64 encoded json
|
||||
\beyJ[-a-zA-Z=;:/0-9+]+
|
||||
# base64 encoded pkcs
|
||||
\bMII[-a-zA-Z=;:/0-9+]+
|
||||
|
||||
# DNS rr data
|
||||
(?:\d+\s+){3}(?:[-+/=.\w]{2,}\s*){1,2}
|
||||
|
||||
# encoded-word
|
||||
=\?[-a-zA-Z0-9"*%]+\?[BQ]\?[^?]{0,75}\?=
|
||||
|
||||
# numerator
|
||||
\bnumer\b(?=.*denom)
|
||||
|
||||
# Time Zones
|
||||
\b(?:Africa|Atlantic|America|Antarctica|Asia|Australia|Europe|Indian|Pacific)(?:/\w+)+
|
||||
|
||||
@@ -563,16 +637,22 @@ customObjectInstantitationMethod
|
||||
# systemd mode
|
||||
systemd.*?running in system mode \([-+].*\)$
|
||||
|
||||
# Lorem
|
||||
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
|
||||
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
|
||||
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
|
||||
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||
## You could manually change `(?i)X...` to use `[Xx]...`
|
||||
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||
# Lorem
|
||||
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
|
||||
# ... Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||
# ... You could manually change `(?i)X...` to use `[Xx]...`
|
||||
# ... or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||
(?:(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*)
|
||||
|
||||
# Non-English
|
||||
# Even repositories expecting pure English content can unintentionally have Non-English content... People will occasionally mistakenly enter [homoglyphs](https://en.wikipedia.org/wiki/Homoglyph) which are essentially typos, and using this pattern will mean check-spelling will not complain about them.
|
||||
#
|
||||
# If the content to be checked should be written in English and the only Non-English items will be people's names, then you can consider adding this.
|
||||
#
|
||||
# Alternatively, if you're using check-spelling v0.0.25+, and you would like to _check_ the Non-English content for spelling errors, you can. For information on how to do so, see:
|
||||
# https://docs.check-spelling.dev/Feature:-Configurable-word-characters.html#unicode
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
|
||||
|
||||
# highlighted letters
|
||||
@@ -585,27 +665,48 @@ systemd.*?running in system mode \([-+].*\)$
|
||||
# latex (check-spelling >= 0.0.22)
|
||||
\\\w{2,}\{
|
||||
|
||||
# American Mathematical Society (AMS) / Doxygen
|
||||
TeX/AMS
|
||||
|
||||
# File extensions
|
||||
\*\.[+\w]+,
|
||||
|
||||
# eslint
|
||||
"varsIgnorePattern": ".+"
|
||||
|
||||
# nolint
|
||||
nolint:\w+
|
||||
|
||||
# Windows short paths
|
||||
[/\\][^/\\]{5,6}~\d{1,2}[/\\]
|
||||
[/\\][^/\\]{5,6}~\d{1,2}(?=[/\\])
|
||||
|
||||
# Windows Resources with accelerators
|
||||
\b[A-Z]&[a-z]+\b(?!;)
|
||||
|
||||
# cygwin paths
|
||||
/cygdrive/[a-zA-Z]/(?:Program Files(?: \(.*?\)| ?)(?:/[-+.~\\/()\w ]+)*|[-+.~\\/()\w])+
|
||||
|
||||
# in check-spelling@v0.0.22+, printf markers aren't automatically consumed
|
||||
# printf markers
|
||||
#(?<!\\)\\[nrt](?=[a-z]{2,})
|
||||
# alternate markers if you run into latex and friends
|
||||
# alternate printf markers if you run into latex and friends
|
||||
#(?<!\\)\\[nrt](?=[a-z]{2,})(?=.*['"`])
|
||||
|
||||
# Markdown anchor links
|
||||
\(#\S*?[a-zA-Z]\S*?\)
|
||||
|
||||
# apache
|
||||
a2(?:en|dis)
|
||||
|
||||
# weak e-tag
|
||||
W/"[^"]+"
|
||||
|
||||
# authors/credits
|
||||
^\*(?: [A-Z](?:\w+|\.)){2,} (?=\[|$)
|
||||
|
||||
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
|
||||
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
|
||||
#\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
|
||||
#\\(?:necessary|r(?:elease|eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
|
||||
@@ -624,13 +725,24 @@ W/"[^"]+"
|
||||
# Compiler flags (linker)
|
||||
,-B
|
||||
|
||||
# libraries
|
||||
(?:\b|_)lib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
|
||||
|
||||
# WWNN/WWPN (NAA identifiers)
|
||||
\b(?:0x)?10[0-9a-f]{14}\b|\b(?:0x|3)?[25][0-9a-f]{15}\b|\b(?:0x|3)?6[0-9a-f]{31}\b
|
||||
|
||||
# iSCSI iqn (approximate regex)
|
||||
\biqn\.[0-9]{4}-[0-9]{2}(?:[\.-][a-z][a-z0-9]*)*\b
|
||||
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
# set arguments
|
||||
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||
\b(?:bash|sh|set)(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
|
||||
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
|
||||
# macOS temp folders
|
||||
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/
|
||||
# github runner temp folders
|
||||
/home/runner/work/_temp/[-_/a-z0-9]+
|
||||
|
||||
26
.github/actions/spell-check/excludes.txt
vendored
26
.github/actions/spell-check/excludes.txt
vendored
@@ -1,23 +1,19 @@
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
|
||||
(?:^|/)(?i)COPYRIGHT
|
||||
(?:^|/)(?i)LICEN[CS]E
|
||||
(?:^|/)(?i)third[-_]?party/
|
||||
(?:^|/)3rdparty/
|
||||
(?:^|/)src/Monaco/customLanguages/
|
||||
(?:^|/)src/Monaco/generateLanguagesJson.html
|
||||
(?:^|/)src/Monaco/index.html
|
||||
(?:^|/)src/Monaco/monaco_languages.json
|
||||
(?:^|/)src/Monaco/monacoSpecialLanguages.js
|
||||
(?:^|/)generated/
|
||||
(?:^|/)go\.sum$
|
||||
(?:^|/)monacoSRC/
|
||||
(?:^|/)package(?:-lock|)\.json$
|
||||
(?:^|/)Pipfile$
|
||||
(?:^|/)power-rename-ui-flags$
|
||||
(?:^|/)pyproject.toml
|
||||
(?:^|/)requirements(?:-dev|-doc|-test|)\.txt$
|
||||
(?:^|/)sample\.qoi$
|
||||
(?:^|/)timezones\.json$
|
||||
(?:^|/)vendor/
|
||||
(?:^|/)WindowsSettings\.json$
|
||||
(?:^|/|\b)requirements(?:-dev|-doc|-test|)\.txt$
|
||||
(?:|$^ 92.31% - excluded 12/13)/editor/[^/]+$
|
||||
/images/launcher/[^/]+$
|
||||
/TestFiles/
|
||||
[^/]\.gcode$
|
||||
@@ -28,11 +24,10 @@
|
||||
\.avi$
|
||||
\.bmp$
|
||||
\.bz2$
|
||||
\.cer$
|
||||
\.cert?$|\.crt$
|
||||
\.class$
|
||||
\.coveragerc$
|
||||
\.crl$
|
||||
\.crt$
|
||||
\.csr$
|
||||
\.dll$
|
||||
\.docx?$
|
||||
@@ -97,19 +92,19 @@
|
||||
^\.gitmodules$
|
||||
^\Q.github/workflows/spelling2.yml\E$
|
||||
^\Q.pipelines/ESRPSigning_core.json\E$
|
||||
^\Q.pipelines/sdl.gdnbaselines\E$
|
||||
^\Qinstaller/PowerToysSetup/Settings.wxs\E$
|
||||
^\Qsrc/Monaco/monaco_languages.json\E$
|
||||
^\Qdoc/devdocs/localization.md\E$
|
||||
^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$
|
||||
^\Qsrc/common/notifications/BackgroundActivatorDLL/cpp.hint\E$
|
||||
^\Qsrc/modules/colorPicker/ColorPickerUI/Assets/ColorPicker/colorPicker.cur\E$
|
||||
^\Qsrc/modules/colorPicker/ColorPickerUI/Shaders/GridShader.cso\E$
|
||||
^\Qsrc/modules/MouseUtils/MouseJumpUI/MainForm.resx\E$
|
||||
^\Qsrc/modules/MouseUtils/MouseJumpUI/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs\E$
|
||||
^\Qsrc/modules/MouseUtils/MouseJump.Common/NativeMethods/User32/UI/WindowsAndMessaging/User32.SYSTEM_METRICS_INDEX.cs\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmAbout.cs\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmInputCallback.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmLogon.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmMatrix.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmMessage.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmMouseCursor.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmScreen.resx\E$
|
||||
^\Qsrc/modules/MouseWithoutBorders/ModuleInterface/generateSecurityDescriptor.h\E$
|
||||
^\Qsrc/modules/peek/Peek.Common/NativeMethods.txt\E$
|
||||
@@ -122,6 +117,7 @@
|
||||
^src/modules/MouseWithoutBorders/App/Form/.*\.Designer\.cs$
|
||||
^src/modules/MouseWithoutBorders/App/Form/.*\.resx$
|
||||
^src/modules/MouseWithoutBorders/App/Helper/.*\.resx$
|
||||
^src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag.txt$
|
||||
^src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag\.txt$
|
||||
^src/Monaco/
|
||||
^tools/Verification scripts/Check preview handler registration\.ps1$
|
||||
ignore$
|
||||
|
||||
117
.github/actions/spell-check/expect.txt
vendored
117
.github/actions/spell-check/expect.txt
vendored
@@ -1,6 +1,3 @@
|
||||
# FALSE POSITIVES
|
||||
## "PackagemanagerWrapper.cs" should be "PackageManagerWrapper.cs"
|
||||
## NOTICE.MD > MOZILLA PUBLIC LICENSE v1.1
|
||||
aaaa
|
||||
abcdefghjkmnpqrstuvxyz
|
||||
abgr
|
||||
@@ -22,7 +19,6 @@ ADDUNDORECORD
|
||||
ADifferent
|
||||
adml
|
||||
admx
|
||||
advapi
|
||||
advfirewall
|
||||
AFeature
|
||||
AFFINETRANSFORM
|
||||
@@ -56,9 +52,9 @@ APPBARDATA
|
||||
appdata
|
||||
APPEXECLINK
|
||||
Appium
|
||||
Applicationcan
|
||||
APPLICATIONFRAMEHOST
|
||||
appmanifest
|
||||
appmodel
|
||||
APPNAME
|
||||
appref
|
||||
appsettings
|
||||
@@ -123,7 +119,6 @@ bmi
|
||||
bms
|
||||
BNumber
|
||||
BODGY
|
||||
BOKMAL
|
||||
bootstrapper
|
||||
BOOTSTRAPPERINSTALLFOLDER
|
||||
bostrot
|
||||
@@ -163,7 +158,6 @@ CCom
|
||||
CContext
|
||||
CDeclaration
|
||||
CDEF
|
||||
cdpx
|
||||
CElems
|
||||
CENTERALIGN
|
||||
ceq
|
||||
@@ -179,7 +173,6 @@ cidl
|
||||
cim
|
||||
CImage
|
||||
cla
|
||||
clangformat
|
||||
CLASSDC
|
||||
CLASSNOTAVAILABLE
|
||||
clickable
|
||||
@@ -201,12 +194,10 @@ CMINVOKECOMMANDINFO
|
||||
CMINVOKECOMMANDINFOEX
|
||||
CMock
|
||||
CMONITORS
|
||||
cmpgt
|
||||
cmph
|
||||
cne
|
||||
CNF
|
||||
coclass
|
||||
codeofconduct
|
||||
codereview
|
||||
Codespaces
|
||||
codicon
|
||||
@@ -216,7 +207,6 @@ colorformat
|
||||
colorhistory
|
||||
colorhistorylimit
|
||||
COLORKEY
|
||||
comctl
|
||||
comdef
|
||||
comdlg
|
||||
comexp
|
||||
@@ -226,9 +216,6 @@ commctrl
|
||||
commdlg
|
||||
compmgmt
|
||||
COMPOSITIONFULL
|
||||
comsupp
|
||||
comsuppw
|
||||
comsuppwd
|
||||
comutil
|
||||
CONFIGW
|
||||
CONFLICTINGMODIFIERKEY
|
||||
@@ -248,7 +235,6 @@ COULDNOT
|
||||
countof
|
||||
cph
|
||||
CPower
|
||||
cppblog
|
||||
cppwinrt
|
||||
createdump
|
||||
CREATESCHEDULEDTASK
|
||||
@@ -265,7 +251,6 @@ CSettings
|
||||
cso
|
||||
CSRW
|
||||
CStyle
|
||||
CSY
|
||||
CTest
|
||||
currentculture
|
||||
CURRENTDIR
|
||||
@@ -276,7 +261,6 @@ CUSTOMACTIONTEST
|
||||
CVal
|
||||
cvd
|
||||
CVirtual
|
||||
cvtepu
|
||||
cxfksword
|
||||
CXSCREEN
|
||||
CXSMICON
|
||||
@@ -292,7 +276,6 @@ datareader
|
||||
datatracker
|
||||
dataversion
|
||||
Dayof
|
||||
Dbghelp
|
||||
DBLCLKS
|
||||
DBLEPSILON
|
||||
DCapture
|
||||
@@ -340,6 +323,7 @@ devblogs
|
||||
devdocs
|
||||
devenum
|
||||
devmgmt
|
||||
DEVMODE
|
||||
DEVMODEW
|
||||
DEVMON
|
||||
devpkey
|
||||
@@ -376,7 +360,7 @@ drivedetectionwarning
|
||||
dshow
|
||||
DSTINVERT
|
||||
DUMMYUNIONNAME
|
||||
dutil
|
||||
Dutil
|
||||
DVASPECT
|
||||
DVASPECTINFO
|
||||
DVD
|
||||
@@ -405,21 +389,17 @@ dwrite
|
||||
dxgi
|
||||
dxgidebug
|
||||
dxgiformat
|
||||
dxguid
|
||||
easeofaccess
|
||||
ecount
|
||||
EData
|
||||
Edid
|
||||
EDITKEYBOARD
|
||||
editkeyboardwindow
|
||||
EDITSHORTCUTS
|
||||
editshortcutswindow
|
||||
EFile
|
||||
ekus
|
||||
emmintrin
|
||||
Emoji
|
||||
ENABLEDELAYEDEXPANSION
|
||||
enabledisable
|
||||
ENABLEDPOPUP
|
||||
encodedlaunch
|
||||
encryptor
|
||||
@@ -442,11 +422,9 @@ ESettings
|
||||
esrp
|
||||
etl
|
||||
etw
|
||||
EUQ
|
||||
eurochange
|
||||
eventlog
|
||||
eventvwr
|
||||
everytime
|
||||
evntrace
|
||||
evt
|
||||
EWXFORCE
|
||||
@@ -519,6 +497,7 @@ FZE
|
||||
gacutil
|
||||
Gaeilge
|
||||
Gaidhlig
|
||||
GC'ed
|
||||
GCLP
|
||||
gdi
|
||||
gdiplus
|
||||
@@ -547,12 +526,10 @@ GSM
|
||||
gtm
|
||||
guiddata
|
||||
guiddef
|
||||
guidgenerator
|
||||
GUITHREADINFO
|
||||
GValue
|
||||
gwl
|
||||
GWLP
|
||||
handlekeyboardhookevent
|
||||
hangeul
|
||||
Hanzi
|
||||
Hardlines
|
||||
@@ -606,6 +583,7 @@ hmenu
|
||||
hmodule
|
||||
hmonitor
|
||||
homljgmgpmcbpjbnjpfijnhipfkiclkd
|
||||
HORZSIZE
|
||||
Hostbackdropbrush
|
||||
hotkeycontrol
|
||||
hotkeys
|
||||
@@ -637,37 +615,25 @@ HWNDLAST
|
||||
HWNDNEXT
|
||||
HWNDPREV
|
||||
hyjiacan
|
||||
IApp
|
||||
IBeam
|
||||
ICapture
|
||||
IClass
|
||||
ICONERROR
|
||||
ICONLOCATION
|
||||
IData
|
||||
IDD
|
||||
IDesktop
|
||||
IDirect
|
||||
idl
|
||||
idlist
|
||||
IDOn
|
||||
IDR
|
||||
IDXGI
|
||||
IEnum
|
||||
ietf
|
||||
IExec
|
||||
IEXPLORE
|
||||
IFACEMETHOD
|
||||
IFACEMETHODIMP
|
||||
IFile
|
||||
IFilter
|
||||
IGNOREUNKNOWN
|
||||
IGraphics
|
||||
iid
|
||||
Iindex
|
||||
IJson
|
||||
Ijwhost
|
||||
IKs
|
||||
ILogon
|
||||
iljxck
|
||||
IMAGEHLP
|
||||
IMAGERESIZERCONTEXTMENU
|
||||
IMAGERESIZEREXT
|
||||
@@ -679,7 +645,7 @@ inetcpl
|
||||
Infobar
|
||||
INFOEXAMPLE
|
||||
Infotip
|
||||
initguid
|
||||
INITGUID
|
||||
inorder
|
||||
INPC
|
||||
inproc
|
||||
@@ -687,7 +653,6 @@ INPUTHARDWARE
|
||||
INPUTKEYBOARD
|
||||
INPUTLANGCHANGED
|
||||
INPUTMOUSE
|
||||
inputparser
|
||||
INPUTSINK
|
||||
INPUTTYPE
|
||||
INSTALLDESKTOPSHORTCUT
|
||||
@@ -708,30 +673,21 @@ INTRESOURCE
|
||||
INVALIDARG
|
||||
invalidoperatioexception
|
||||
ipcmanager
|
||||
IPlugin
|
||||
IPower
|
||||
IPREVIEW
|
||||
ipreviewhandlervisualssetfont
|
||||
IProperty
|
||||
IPublic
|
||||
irprops
|
||||
isbi
|
||||
ISearch
|
||||
ISettings
|
||||
IShell
|
||||
isocpp
|
||||
iss
|
||||
issecret
|
||||
ISSEPARATOR
|
||||
ITask
|
||||
ith
|
||||
ITHUMBNAIL
|
||||
ITwoWayPipeMessageIPCManaged
|
||||
IUI
|
||||
IUnknown
|
||||
IUse
|
||||
IWbem
|
||||
IWeb
|
||||
IWIC
|
||||
iwr
|
||||
IYUV
|
||||
@@ -753,7 +709,6 @@ keyboardmanagercommon
|
||||
KEYBOARDMANAGEREDITOR
|
||||
keyboardmanagerstate
|
||||
keyboardmanagerui
|
||||
keydropdowncontrol
|
||||
KEYEVENTF
|
||||
KEYIMAGE
|
||||
keynum
|
||||
@@ -765,24 +720,21 @@ kmph
|
||||
Knownfolders
|
||||
KSPROPERTY
|
||||
Kybd
|
||||
languagesjson
|
||||
lastcodeanalysissucceeded
|
||||
Lastdevice
|
||||
LASTEXITCODE
|
||||
LAYOUTRTL
|
||||
lcb
|
||||
LCIDTo
|
||||
lcl
|
||||
Lclean
|
||||
Ldone
|
||||
ldx
|
||||
LEFTSCROLLBAR
|
||||
lego
|
||||
LError
|
||||
LEVELID
|
||||
LExit
|
||||
lhwnd
|
||||
LIBID
|
||||
licate
|
||||
lindex
|
||||
LINKOVERLAY
|
||||
LINQTo
|
||||
@@ -859,7 +811,6 @@ MAKEINTRESOURCE
|
||||
MAKEINTRESOURCEA
|
||||
MAKEINTRESOURCEW
|
||||
MAKELANGID
|
||||
makepri
|
||||
manifestdependency
|
||||
MAPPEDTOSAMEKEY
|
||||
MAPTOSAMESHORTCUT
|
||||
@@ -887,13 +838,11 @@ mfc
|
||||
mfidl
|
||||
mfobjects
|
||||
mfplat
|
||||
Mfsensorgroup
|
||||
mftransform
|
||||
Mgmt
|
||||
mic
|
||||
midl
|
||||
mii
|
||||
MIIM
|
||||
mindaro
|
||||
Minimatch
|
||||
Minimizable
|
||||
@@ -983,7 +932,6 @@ NCPAINT
|
||||
NCRENDERING
|
||||
ndp
|
||||
NEEDDISPATCH
|
||||
needinfo
|
||||
netcoreapp
|
||||
netcpl
|
||||
netframework
|
||||
@@ -1001,7 +949,6 @@ NEWPLUSSHELLEXTENSIONWIN
|
||||
newrow
|
||||
newsgroups
|
||||
NIF
|
||||
NLD
|
||||
NLog
|
||||
NLSTEXT
|
||||
NNN
|
||||
@@ -1078,7 +1025,6 @@ oldpath
|
||||
oldtheme
|
||||
oleaut
|
||||
OLECHAR
|
||||
onebranch
|
||||
opencode
|
||||
OPENFILENAME
|
||||
opensource
|
||||
@@ -1126,6 +1072,7 @@ pcelt
|
||||
pch
|
||||
pchast
|
||||
PCIDLIST
|
||||
PCTSTR
|
||||
PCWSTR
|
||||
pdbs
|
||||
pdisp
|
||||
@@ -1133,8 +1080,7 @@ pdo
|
||||
pdto
|
||||
pdtobj
|
||||
pdw
|
||||
peb
|
||||
pef
|
||||
Peb
|
||||
PElems
|
||||
Pels
|
||||
PERCEIVEDFLAG
|
||||
@@ -1159,7 +1105,6 @@ pinvoke
|
||||
pipename
|
||||
PKBDLLHOOKSTRUCT
|
||||
plib
|
||||
PLK
|
||||
ploc
|
||||
ploca
|
||||
plocm
|
||||
@@ -1206,7 +1151,6 @@ prgms
|
||||
pri
|
||||
PRINTCLIENT
|
||||
printmanagement
|
||||
privacystatement
|
||||
prm
|
||||
proactively
|
||||
PROCESSENTRY
|
||||
@@ -1221,7 +1165,6 @@ projectname
|
||||
PROPBAG
|
||||
PROPERTYKEY
|
||||
propkey
|
||||
propsys
|
||||
PROPVARIANT
|
||||
propvarutil
|
||||
prvpane
|
||||
@@ -1231,7 +1174,6 @@ PSECURITY
|
||||
psfgao
|
||||
psfi
|
||||
PSMODULEPATH
|
||||
Psr
|
||||
psrm
|
||||
psrree
|
||||
pstatstg
|
||||
@@ -1248,7 +1190,7 @@ PTOKEN
|
||||
PToy
|
||||
ptstr
|
||||
pui
|
||||
pwa
|
||||
PWAs
|
||||
pwcs
|
||||
PWSTR
|
||||
pwsz
|
||||
@@ -1269,6 +1211,7 @@ RAlt
|
||||
Rasterize
|
||||
RAWINPUTDEVICE
|
||||
RAWINPUTHEADER
|
||||
RAWMODE
|
||||
RAWPATH
|
||||
rbhid
|
||||
rclsid
|
||||
@@ -1313,7 +1256,6 @@ Renamer
|
||||
reparented
|
||||
reparenting
|
||||
reparse
|
||||
reportbug
|
||||
reportfileaccesses
|
||||
requery
|
||||
requerying
|
||||
@@ -1325,7 +1267,6 @@ RESIZETOFIT
|
||||
resmimetype
|
||||
RESOURCEID
|
||||
RESTORETOMAXIMIZED
|
||||
restrictedcapabilities
|
||||
restrictederrorinfo
|
||||
resultlist
|
||||
RETURNONLYFSDIRS
|
||||
@@ -1352,7 +1293,6 @@ Rsp
|
||||
rstringalnum
|
||||
rstringalpha
|
||||
rstringdigit
|
||||
Rstrtmgr
|
||||
RTB
|
||||
RTLREADING
|
||||
ruleset
|
||||
@@ -1361,7 +1301,6 @@ rundll
|
||||
rungameid
|
||||
RUNLEVEL
|
||||
runtimeclass
|
||||
runtimeobject
|
||||
runtimepack
|
||||
runtimes
|
||||
ruuid
|
||||
@@ -1381,14 +1320,13 @@ Scode
|
||||
screensaver
|
||||
screenshots
|
||||
scrollviewer
|
||||
sddl
|
||||
SDDL
|
||||
SDKDDK
|
||||
sdns
|
||||
searchterm
|
||||
SEARCHUI
|
||||
secpol
|
||||
SENDCHANGE
|
||||
sendinput
|
||||
sendvirtualinput
|
||||
serverside
|
||||
SETCONTEXT
|
||||
@@ -1404,7 +1342,6 @@ settingsheader
|
||||
settingshotkeycontrol
|
||||
setvariable
|
||||
SETWORKAREA
|
||||
setzero
|
||||
sfgao
|
||||
SFGAOF
|
||||
SHANDLE
|
||||
@@ -1412,7 +1349,7 @@ sharpkeys
|
||||
SHCNE
|
||||
SHCNF
|
||||
SHCONTF
|
||||
shcore
|
||||
Shcore
|
||||
shellapi
|
||||
SHELLDETAILS
|
||||
SHELLDLL
|
||||
@@ -1433,7 +1370,6 @@ shmem
|
||||
SHNAMEMAPPING
|
||||
shobjidl
|
||||
SHORTCUTATLEAST
|
||||
shortcutcontrol
|
||||
SHORTCUTMAXONEACTIONKEY
|
||||
SHORTCUTNOREPEATEDMODIFIER
|
||||
SHORTCUTONEACTIONKEY
|
||||
@@ -1462,7 +1398,6 @@ sigdn
|
||||
SIGNINGSCENARIO
|
||||
Signtool
|
||||
SINGLEKEY
|
||||
singlekeyremapcontrol
|
||||
sipolicy
|
||||
SIZEBOX
|
||||
Sizename
|
||||
@@ -1533,7 +1468,6 @@ STRINGIZE
|
||||
stringtable
|
||||
stringval
|
||||
Strm
|
||||
Strmiids
|
||||
strret
|
||||
strsafe
|
||||
strutil
|
||||
@@ -1574,7 +1508,6 @@ SYSLIB
|
||||
SYSMENU
|
||||
SYSTEMAPPS
|
||||
SYSTEMTIME
|
||||
SYSTEMWOW
|
||||
tailwindcss
|
||||
tapp
|
||||
TApplication
|
||||
@@ -1587,7 +1520,7 @@ TARGETHEADER
|
||||
targetver
|
||||
taskkill
|
||||
taskschd
|
||||
tchar
|
||||
TCHAR
|
||||
Tcollab
|
||||
tcs
|
||||
tcscpy
|
||||
@@ -1609,6 +1542,7 @@ THISCOMPONENT
|
||||
THotkey
|
||||
thumbcache
|
||||
TILEDWINDOW
|
||||
TILLSON
|
||||
timedate
|
||||
timediff
|
||||
timeunion
|
||||
@@ -1638,7 +1572,6 @@ traies
|
||||
transicc
|
||||
TRAYMOUSEMESSAGE
|
||||
triaging
|
||||
TRK
|
||||
trl
|
||||
trx
|
||||
tsa
|
||||
@@ -1673,7 +1606,7 @@ uniquifier
|
||||
Uniquifies
|
||||
unitconverter
|
||||
unittests
|
||||
unknwn
|
||||
Unknwn
|
||||
UNLEN
|
||||
UNORM
|
||||
unregistering
|
||||
@@ -1691,14 +1624,13 @@ Usb
|
||||
USEDEFAULT
|
||||
USEFILEATTRIBUTES
|
||||
USERDATA
|
||||
Userenv
|
||||
USESHOWWINDOW
|
||||
USESTDHANDLES
|
||||
USRDLL
|
||||
UType
|
||||
uuidv
|
||||
uwp
|
||||
uxtheme
|
||||
Uxtheme
|
||||
vabdq
|
||||
validmodulename
|
||||
valuegenerator
|
||||
@@ -1720,6 +1652,7 @@ VERBW
|
||||
VERIFYCONTEXT
|
||||
verrsrc
|
||||
VERSIONINFO
|
||||
VERTSIZE
|
||||
VFT
|
||||
vget
|
||||
vgetq
|
||||
@@ -1761,8 +1694,6 @@ Vtbl
|
||||
WANTMAPPINGHANDLE
|
||||
WANTPALM
|
||||
wbem
|
||||
Wbemidl
|
||||
wbemuuid
|
||||
WBounds
|
||||
Wca
|
||||
wcautil
|
||||
@@ -1780,9 +1711,9 @@ webcam
|
||||
webpage
|
||||
websites
|
||||
wekyb
|
||||
Wevtapi
|
||||
wgpocpl
|
||||
WIC
|
||||
wifi
|
||||
wil
|
||||
winapi
|
||||
wincodec
|
||||
@@ -1798,7 +1729,6 @@ WINDOWPOSCHANGED
|
||||
WINDOWPOSCHANGING
|
||||
windowsapp
|
||||
WINDOWSBUILDNUMBER
|
||||
Windowscodecs
|
||||
windowssearch
|
||||
windowssettings
|
||||
WINDOWSTYLES
|
||||
@@ -1809,20 +1739,17 @@ WINEVENT
|
||||
winevt
|
||||
winexe
|
||||
winforms
|
||||
winfx
|
||||
winget
|
||||
wingetcreate
|
||||
Winhook
|
||||
WINL
|
||||
winlogon
|
||||
winmd
|
||||
winmm
|
||||
winnt
|
||||
WINNT
|
||||
winres
|
||||
winrt
|
||||
winsdk
|
||||
winsdkver
|
||||
winspool
|
||||
winsta
|
||||
winternl
|
||||
WINTHRESHOLD
|
||||
@@ -1849,7 +1776,6 @@ WNDCLASSEXW
|
||||
WNDCLASSW
|
||||
WNDPROC
|
||||
wnode
|
||||
workarounds
|
||||
WORKSPACESEDITOR
|
||||
WORKSPACESLAUNCHER
|
||||
WORKSPACESSNAPSHOTTOOL
|
||||
@@ -1889,7 +1815,6 @@ XElement
|
||||
xfd
|
||||
XFile
|
||||
XIncrement
|
||||
XLoc
|
||||
XNamespace
|
||||
Xoshiro
|
||||
XPels
|
||||
|
||||
266
.github/actions/spell-check/line_forbidden.patterns
vendored
266
.github/actions/spell-check/line_forbidden.patterns
vendored
@@ -1,119 +1,289 @@
|
||||
# reject `m_data` as VxWorks defined it and that breaks things if it's used elsewhere
|
||||
# see [fprime](https://github.com/nasa/fprime/commit/d589f0a25c59ea9a800d851ea84c2f5df02fb529)
|
||||
# and [Qt](https://github.com/qtproject/qt-solutions/blame/fb7bc42bfcc578ff3fa3b9ca21a41e96eb37c1c7/qtscriptclassic/src/qscriptbuffer_p.h#L46)
|
||||
# \bm_data\b
|
||||
#\bm_data\b
|
||||
|
||||
# Were you debugging using a framework with `fit()`?
|
||||
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
|
||||
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
|
||||
# to use this:
|
||||
# you might not want to check in code where you skip all the other tests.
|
||||
#\bfit\(
|
||||
|
||||
# s.b. anymore
|
||||
# Should be `HH:MM:SS`
|
||||
\bHH:SS:MM\b
|
||||
|
||||
# Should be `86400` (seconds in a standard day)
|
||||
\b84600\b(?:.*\bday\b)
|
||||
|
||||
# Should probably be `2006-01-02` (yyyy-mm-dd)
|
||||
# Assuming that the time is being passed to https://go.dev/src/time/format.go
|
||||
\b2006-02-01\b
|
||||
|
||||
# Should probably be `YYYYMMDD`
|
||||
\b[Yy]{4}[Dd]{2}[Mm]{2}(?!.*[Yy]{4}[Dd]{2}[Mm]{2}).*$
|
||||
|
||||
# Should be `a priori` or `and prior`
|
||||
(?i)(?<!posteriori)\sand priori\s
|
||||
|
||||
# Should only be one of `a`, `an`, or `the`
|
||||
\b(?:(?:an?|the)\s+){2,}\b
|
||||
|
||||
# Should be `anymore`
|
||||
\bany more[,.]
|
||||
|
||||
# s.b. GitHub
|
||||
(?<![&*.]|// |\btype )\bGithub\b(?![{)])
|
||||
# Should be `'`
|
||||
(?i)\b(?:(?:i|s?he|they|what|who|you)"ll|(?:are|ca|did|do|does|ha[ds]|have|is|should|were|wo|would)n"t|(?:s?he|let|that|there|what|where|who)"s|(?:i|they|we|what|who|you)"ve)\b
|
||||
|
||||
# s.b. GitLab
|
||||
(?<![&*.]|// |\btype )\bGitlab\b(?![{)])
|
||||
# Should be `briefcase`
|
||||
\bbrief-case\b
|
||||
|
||||
# s.b. JavaScript
|
||||
# Should be `can, not only ..., ... also...`
|
||||
\bcan not only.*can also\b
|
||||
|
||||
# Should be `cannot` (or `can't`)
|
||||
# See https://www.grammarly.com/blog/cannot-or-can-not/
|
||||
# > Don't use `can not` when you mean `cannot`. The only time you're likely to see `can not` written as separate words is when the word `can` happens to precede some other phrase that happens to start with `not`.
|
||||
# > `Can't` is a contraction of `cannot`, and it's best suited for informal writing.
|
||||
# > In formal writing and where contractions are frowned upon, use `cannot`.
|
||||
# > It is possible to write `can not`, but you generally find it only as part of some other construction, such as `not only . . . but also.`
|
||||
# - if you encounter such a case, add a pattern for that case to patterns.txt.
|
||||
\b[Cc]an not\b
|
||||
|
||||
# Do not use `(click) here` links
|
||||
# For more information, see:
|
||||
# * https://www.w3.org/QA/Tips/noClickHere
|
||||
# * https://webaim.org/techniques/hypertext/link_text
|
||||
# * https://granicus.com/blog/why-click-here-links-are-bad/
|
||||
# * https://heyoka.medium.com/dont-use-click-here-f32f445d1021
|
||||
(?i)(?:>|\[)(?:(?:click |)here|this(?=\]\([^\)]+:/)|link|(?:read |)more(?!</value))(?:</|\]\()
|
||||
|
||||
# Should be `equals` to `is equal to`
|
||||
\bequals to\b
|
||||
|
||||
# Should be `GitHub`
|
||||
(?<![&*.]|// |\b(?:from|import|type) )\bGithub\b(?![{()])
|
||||
|
||||
# Should be `GitLab`
|
||||
(?<![&*.]|// |\b(?:from|import|type) )\bGitlab\b(?![{()])
|
||||
|
||||
# Should probably be `https://`...
|
||||
# Markdown generally doesn't assume that links are to urls
|
||||
\]\(www\.\w
|
||||
|
||||
# Should be `JavaScript`
|
||||
\bJavascript\b
|
||||
|
||||
# s.b. macOS or Mac OS X or ...
|
||||
# Should be `macOS` or `Mac OS X` or ...
|
||||
\bMacOS\b
|
||||
|
||||
# s.b. Microsoft
|
||||
# Should be `Microsoft`
|
||||
\bMicroSoft\b
|
||||
|
||||
# s.b. TypeScript
|
||||
# Should be `OAuth`
|
||||
(?:^|[^-/*$])[ '"]oAuth(?: [a-z]|\d+ |[^ a-zA-Z0-9:;_.()])
|
||||
|
||||
# Should be `RabbitMQ`
|
||||
\bRabbitmq\b
|
||||
|
||||
# Should be `TypeScript`
|
||||
\bTypescript\b
|
||||
|
||||
# s.b. another
|
||||
# Should be `another`
|
||||
\ban[- ]other\b
|
||||
|
||||
# s.b. deprecation warning
|
||||
# Should be `case-(in)sensitive`
|
||||
\bcase (?:in|)sensitive\b
|
||||
|
||||
# Should be `coinciding`
|
||||
\bco-inciding\b
|
||||
|
||||
# Should be `deprecation warning(s)`
|
||||
\b[Dd]epreciation [Ww]arnings?\b
|
||||
|
||||
# s.b. greater than
|
||||
# Should be `greater than`
|
||||
\bgreater then\b
|
||||
|
||||
# s.b. in front of
|
||||
# Should be `has`
|
||||
\b[Ii]t only have\b
|
||||
|
||||
# Should be `here-in`, `the`, `them`, `this`, `these` or reworded in some other way
|
||||
\bthe here(?:\.|,| (?!and|defined))
|
||||
|
||||
# Should be `greater than`
|
||||
\bhigher than\b
|
||||
|
||||
# Should be `ID`
|
||||
#\bId\b
|
||||
|
||||
# Should be `in front of`
|
||||
\bin from of\b
|
||||
|
||||
# s.b. into
|
||||
# Should be `into`
|
||||
# when not phrasal and when `in order to` would be wrong:
|
||||
# https://thewritepractice.com/into-vs-in-to/
|
||||
\sin to\s(?!if\b)
|
||||
|
||||
# s.b. is obsolete
|
||||
# Should be `use`
|
||||
\sin used by\b
|
||||
|
||||
# Should be `is obsolete`
|
||||
\bis obsolescent\b
|
||||
|
||||
# s.b. it's or its
|
||||
# Should be `it's` or `its`
|
||||
\bits['’]
|
||||
|
||||
# s.b. opt-in
|
||||
(?<!\sfor)\sopt in\s
|
||||
# Should be `its`
|
||||
\bit's(?= own\b)
|
||||
|
||||
# s.b. less than
|
||||
# Should be `log in`
|
||||
\blogin to the
|
||||
|
||||
# Should be `long-standing`
|
||||
\blong standing\b
|
||||
|
||||
# Should probably be a person named `Nick` or the abbreviation `NIC`
|
||||
\bNic\b
|
||||
|
||||
# Should be `not supposed`
|
||||
\bsupposed not\b
|
||||
|
||||
# Should probably be `much more`
|
||||
\bmore much\b
|
||||
|
||||
# Should be `perform its`
|
||||
\bperform it's\b
|
||||
|
||||
# Should be `opt-in`
|
||||
(?<!\scan|for)(?<!\sif)\sopt in\s
|
||||
|
||||
# Should be `less than`
|
||||
\bless then\b
|
||||
|
||||
# s.b. one of
|
||||
\bon of\b
|
||||
# Should be `load balancer`
|
||||
\b[Ll]oud balancer
|
||||
|
||||
# s.b. otherwise
|
||||
# Should be `moot`
|
||||
\bmute point\b
|
||||
|
||||
# Should be `one of`
|
||||
(?<!-)\bon of\b
|
||||
|
||||
# Should be `on the other hand`
|
||||
\b(?i)on another hand\b
|
||||
|
||||
# Most people only have two hands. Reword.
|
||||
\b(?i)on the third hand\b
|
||||
|
||||
# Should be `otherwise`
|
||||
\bother[- ]wise\b
|
||||
|
||||
# s.b. or (more|less)
|
||||
# Should be `or (more|less)`
|
||||
\bore (?:more|less)\b
|
||||
|
||||
# s.b. nonexistent
|
||||
# Should be `rather than`
|
||||
\brather then\b
|
||||
|
||||
# Should be `regardless, ...` or `regardless of (whether)`
|
||||
\b[Rr]egardless if you\b
|
||||
|
||||
# Should be `no longer needed`
|
||||
\bno more needed\b(?! than\b)
|
||||
|
||||
# Should be `did not exist`
|
||||
\bwere not existent\b
|
||||
|
||||
# Should be `nonexistent`
|
||||
\bnon existing\b
|
||||
|
||||
# Should be `nonexistent`
|
||||
\b[Nn]o[nt][- ]existent\b
|
||||
|
||||
# s.b. brief / details/ param / return / retval
|
||||
# Should be `@brief` / `@details` / `@param` / `@return` / `@retval`
|
||||
(?:^\s*|(?:\*|//|/*)\s+`)[\\@](?:breif|(?:detail|detials)|(?:params(?!\.)|prama?)|ret(?:uns?)|retvl)\b
|
||||
|
||||
# s.b. preexisting
|
||||
# Should be `preexisting`
|
||||
[Pp]re[- ]existing
|
||||
|
||||
# s.b. preempt
|
||||
# Should be `preempt`
|
||||
[Pp]re[- ]empt\b
|
||||
|
||||
# s.b. preemptively
|
||||
# Should be `preemptively`
|
||||
[Pp]re[- ]emptively
|
||||
|
||||
# s.b. recently changed or recent changes
|
||||
# Should be `prepopulate`
|
||||
[Pp]re[- ]populate
|
||||
|
||||
# Should be `prerequisite`
|
||||
[Pp]re[- ]requisite
|
||||
|
||||
# Should be `recently changed` or `recent changes`
|
||||
[Rr]ecent changed
|
||||
|
||||
# s.b. reentrancy
|
||||
# Should be `reentrancy`
|
||||
[Rr]e[- ]entrancy
|
||||
|
||||
# s.b. reentrant
|
||||
# Should be `reentrant`
|
||||
[Rr]e[- ]entrant
|
||||
|
||||
# s.b. understand
|
||||
# Should be `strong suit`
|
||||
\b(?:my|his|her|their) strong suite\b
|
||||
|
||||
# Should be `understand`
|
||||
\bunder stand\b
|
||||
|
||||
# s.b. workarounds
|
||||
# Should be `URI` or `uri` unless it refers to a person named `Uri`
|
||||
#(?<!\.)\bUri\b(?![(])
|
||||
|
||||
# Should be `it uses is`
|
||||
/\bis uses is\b/
|
||||
|
||||
# Should be `uses it as`
|
||||
(?:^|\. |and )uses is as (?!an?\b|follows|livestock|[^.]+\s+as\b)
|
||||
|
||||
# Should be `was`
|
||||
\bhas been(?= removed in v?\d)
|
||||
|
||||
# Should be `where`
|
||||
\bwere they are\b
|
||||
|
||||
# should be `vCenter`
|
||||
\bV[Cc]enter\b
|
||||
|
||||
# Should be `VM`
|
||||
\bVm\b
|
||||
|
||||
# Should be `workarounds`
|
||||
#\bwork[- ]arounds\b
|
||||
|
||||
# s.b. workaround
|
||||
# Should be `workaround`
|
||||
(?:(?:[Aa]|[Tt]he|ugly)\swork[- ]around\b|\swork[- ]around\s+for)
|
||||
|
||||
# s.b. (coarse|fine)-grained
|
||||
# Should be `worst`
|
||||
(?i)worse-case
|
||||
|
||||
# Should be `you are not` or reworded
|
||||
\byour not\b
|
||||
|
||||
# Should be `(coarse|fine)-grained`
|
||||
\b(?:coarse|fine) grained\b
|
||||
|
||||
# s.b. neither/nor -- or reword
|
||||
#\bnot\b[^.?!"/(]+\bnor\b
|
||||
# Homoglyph (Cyrillic) should be `A`/`B`/`C`/`E`/`H`/`I`/`I`/`J`/`K`/`M`/`O`/`P`/`S`/`T`/`Y`
|
||||
# It's possible that your content is intentionally mixing Cyrllic and Latin scripts, but if it isn't, you definitely want to correct this.
|
||||
(?<=[A-Z]{2})[АВСЕНІӀЈКМОРЅТУ]|[АВСЕНІӀЈКМОРЅТУ](?=[A-Z]+(?:\b|[a-z]+)|[a-z]+(?:[^a-z]|$))
|
||||
|
||||
# probably a double negative
|
||||
# s.b. neither/nor (plus rewording the beginning)
|
||||
\bnot\b[^.?!"/]*\bneither\b[^.?!"/(]*\bnor\b
|
||||
# Homoglyph (Cyrillic) should be `a`/`b`/`e`
|
||||
# It's possible that your content is intentionally mixing Cyrllic and Latin scripts, but if it isn't, you definitely want to correct this.
|
||||
[аве](?=[A-Za-z]{2,})|(?<=[A-Za-z]{2})[аве]|(?<=[A-Za-z])[аве](?=[A-Za-z])
|
||||
|
||||
# In English, it is generally wrong to have the same word twice in a row without punctuation.
|
||||
# Duplicated words are generally mistakes.
|
||||
# There are a few exceptions where it is acceptable (e.g. "that that").
|
||||
# If the highlighted doubled word pair is in a code snippet, you can write a pattern to mask it.
|
||||
# If the highlighted doubled word pair is in prose, have someone read the English before you dismiss this error.
|
||||
# Should be `neither/nor` -- or reword
|
||||
#(?!<do )\bnot\b([^.?!"/(](?!neither|,.*?,))+\bnor\b
|
||||
|
||||
# Should be `neither/nor` (plus rewording the beginning)
|
||||
# This is probably a double negative...
|
||||
\bnot\b[^.?!"/(]*\bneither\b[^.?!"/(]*\bnor\b
|
||||
|
||||
# In English, duplicated words are generally mistakes
|
||||
# There are a few exceptions (e.g. "that that").
|
||||
# If the highlighted doubled word pair is in:
|
||||
# * code, write a pattern to mask it.
|
||||
# * prose, have someone read the English before you dismiss this error.
|
||||
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
|
||||
|
||||
279
.github/actions/spell-check/patterns.txt
vendored
279
.github/actions/spell-check/patterns.txt
vendored
@@ -1,41 +1,22 @@
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
|
||||
|
||||
# Automatically suggested patterns
|
||||
# hit-count: 3011 file-count: 842
|
||||
# IServiceProvider / isAThing
|
||||
\b(?:I|isA)(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
# #includes
|
||||
^\s*#include\s*(?:<.*?>|".*?")
|
||||
|
||||
# hit-count: 2239 file-count: 134
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
# #pragma lib
|
||||
^\s*#pragma comment\(lib, ".*?"\)
|
||||
|
||||
# hit-count: 1868 file-count: 1
|
||||
# sha-... -- uses a fancy capture
|
||||
(\\?['"]|")[0-9a-f]{40,}\g{-1}
|
||||
# languageHashTable
|
||||
"\w+(?:-\w+|)"\s+=\s+@\(".*"\)
|
||||
|
||||
# hit-count: 1100 file-count: 97
|
||||
# base64 encoded content, possibly wrapped in mime
|
||||
(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
|
||||
# wikipedia
|
||||
\b\w\w\.wikipedia\.org/wiki/[-\w%.#]+
|
||||
|
||||
# hit-count: 426 file-count: 165
|
||||
# GitHub SHAs (markdown)
|
||||
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
|
||||
# css fonts
|
||||
\bfont-family:[^;}]+
|
||||
|
||||
# hit-count: 331 file-count: 117
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
|
||||
|
||||
# hit-count: 275 file-count: 45
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 209 file-count: 97
|
||||
# w3
|
||||
\bw3\.org/[-0-9a-zA-Z/#.]+
|
||||
|
||||
# hit-count: 137 file-count: 38
|
||||
# alternate markers if you run into latex and friends
|
||||
(?<!\\)\\[nrt](?=[a-z]{2,})(?=.*['"`](?:, "[^{]|\]))
|
||||
# .github/policies/resourceManagement.yml
|
||||
pattern: '.*'
|
||||
|
||||
# tabs in c#
|
||||
\$"\\t
|
||||
@@ -46,81 +27,6 @@
|
||||
# windows line breaks in strings
|
||||
\\r\\n
|
||||
|
||||
# hit-count: 104 file-count: 43
|
||||
# regex choice
|
||||
\(\?:[^)]+\|[^)]+\)
|
||||
|
||||
# hit-count: 76 file-count: 28
|
||||
# base64 encoded content
|
||||
([`'"])[-a-zA-Z=;:/0-9+]+=\g{-1}
|
||||
|
||||
# hit-count: 70 file-count: 5
|
||||
# Contributor
|
||||
\[[^\]]+\]\(https://github\.com/[^/\s"]+/?\)
|
||||
|
||||
# hit-count: 28 file-count: 22
|
||||
# stackexchange -- https://stackexchange.com/feeds/sites
|
||||
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
|
||||
|
||||
# hit-count: 21 file-count: 2
|
||||
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
|
||||
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
|
||||
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
|
||||
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||
## You could manually change `(?i)X...` to use `[Xx]...`
|
||||
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||
# Lorem
|
||||
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
|
||||
|
||||
# hit-count: 18 file-count: 15
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||
|
||||
# hit-count: 14 file-count: 5
|
||||
# githubusercontent
|
||||
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
||||
|
||||
# hit-count: 14 file-count: 3
|
||||
# node packages
|
||||
(["'])\@[^/'" ]+/[^/'" ]+\g{-1}
|
||||
|
||||
# hit-count: 10 file-count: 4
|
||||
# URL escaped characters
|
||||
\%[0-9A-F][A-F]
|
||||
|
||||
# hit-count: 9 file-count: 5
|
||||
# Wikipedia
|
||||
\ben\.wikipedia\.org/wiki/[-\w%.#]+
|
||||
|
||||
# hit-count: 6 file-count: 3
|
||||
# css url wrappings
|
||||
\burl\([^)]+\)
|
||||
|
||||
# hit-count: 5 file-count: 3
|
||||
# vs devops
|
||||
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
|
||||
|
||||
# hit-count: 4 file-count: 3
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
|
||||
|
||||
# hit-count: 4 file-count: 2
|
||||
# data url in quotes
|
||||
([`'"])data:(?:[^ `'"].*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
|
||||
|
||||
# hit-count: 2 file-count: 2
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# msdn
|
||||
\b(?:download\.visualstudio|docs|msdn|learn)\.microsoft\.com/[-_a-zA-Z0-9()=./]*
|
||||
aka\.ms/[a-zA-Z0-9]+
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||
# YouTube url
|
||||
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||
|
||||
# power shell gallery website
|
||||
\bpowershellgallery.com/[-_a-zA-Z0-9()=./%]*
|
||||
|
||||
@@ -136,48 +42,183 @@ L?(["']|[-<({>]|\b)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{10,12}(?:\g{
|
||||
# UnitTests
|
||||
\[DataRow\(.*\)\]
|
||||
|
||||
# AdditionalDependencies
|
||||
<AdditionalDependencies>.*<
|
||||
|
||||
# the last line of mimetype="application/x-microsoft.net.object.bytearray.base64" things in .resx files
|
||||
^\s*[-a-zA-Z=;:/0-9+]*[-a-zA-Z;:/0-9+][-a-zA-Z=;:/0-9+]*=$
|
||||
|
||||
# Automatically suggested patterns
|
||||
|
||||
# hit-count: 3715 file-count: 992
|
||||
# IServiceProvider / isAThing
|
||||
(?:\b|_)(?:(?:ns|)I|isA)(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
|
||||
# hit-count: 404 file-count: 42
|
||||
# base64 encoded content, possibly wrapped in mime
|
||||
(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
|
||||
|
||||
# hit-count: 402 file-count: 160
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
|
||||
# hit-count: 337 file-count: 110
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
|
||||
|
||||
# hit-count: 311 file-count: 43
|
||||
# D2D
|
||||
D?2D
|
||||
D?2D(?!efault)
|
||||
|
||||
# hit-count: 272 file-count: 75
|
||||
# GitHub SHAs (markdown)
|
||||
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
|
||||
|
||||
# hit-count: 146 file-count: 27
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 105 file-count: 103
|
||||
# w3
|
||||
\bw3\.org/[-0-9a-zA-Z/#.]+
|
||||
|
||||
# hit-count: 94 file-count: 6
|
||||
# Contributor
|
||||
\[[^\]]+\]\(https://github\.com/[^/\s"]+/?\)
|
||||
|
||||
RegExp\(([`'"]).*?\g{-1}\)|(?:escapes|regEx):\s*(?:/.*/|([`'"]).*?\g{-1})|return/.*?/
|
||||
|
||||
# hit-count: 65 file-count: 38
|
||||
# regex choice
|
||||
\(\?:[^)]+\|[^)]+\)
|
||||
|
||||
# hit-count: 37 file-count: 14
|
||||
# Markdown anchor links
|
||||
\(#\S*?[a-zA-Z]\S*?\)
|
||||
|
||||
# hit-count: 33 file-count: 5
|
||||
# base64 encoded pkcs
|
||||
\bMII[-a-zA-Z=;:/0-9+]+
|
||||
|
||||
# hit-count: 28 file-count: 22
|
||||
# stackexchange -- https://stackexchange.com/feeds/sites
|
||||
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
|
||||
|
||||
# hit-count: 14 file-count: 3
|
||||
# node packages
|
||||
(["'])@[^/'" ]+/[^/'" ]+\g{-1}
|
||||
|
||||
# hit-count: 13 file-count: 1
|
||||
# Intel intrinsics
|
||||
_mm_(?!dd)\w+
|
||||
|
||||
# hit-count: 11 file-count: 5
|
||||
# URL escaped characters
|
||||
%[0-9A-F][A-F](?=[A-Za-z])
|
||||
|
||||
# hit-count: 9 file-count: 5
|
||||
# Wikipedia
|
||||
\ben\.wikipedia\.org/wiki/[-\w%.#]+
|
||||
|
||||
# hit-count: 5 file-count: 4
|
||||
# vs devops
|
||||
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
|
||||
|
||||
# hit-count: 5 file-count: 4
|
||||
# Alternatively, if you're using check-spelling v0.0.25+, and you would like to _check_ the Non-English content for spelling errors, you can. For information on how to do so, see:
|
||||
# https://docs.check-spelling.dev/Feature:-Configurable-word-characters.html#unicode
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
|
||||
|
||||
# hit-count: 4 file-count: 4
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]*
|
||||
|
||||
aka\.ms/[a-zA-Z0-9]+
|
||||
|
||||
# hit-count: 3 file-count: 3
|
||||
# githubusercontent
|
||||
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
||||
|
||||
# hit-count: 3 file-count: 2
|
||||
# css url wrappings
|
||||
\burl\([^)]+\)
|
||||
|
||||
# hit-count: 3 file-count: 1
|
||||
# kubernetes crd patterns
|
||||
^\s*pattern: .*$
|
||||
|
||||
# hit-count: 3 file-count: 1
|
||||
# Lorem
|
||||
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
|
||||
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
|
||||
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
|
||||
# ... Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||
# ... You could manually change `(?i)X...` to use `[Xx]...`
|
||||
# ... or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||
(?:(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*)
|
||||
|
||||
# hit-count: 3 file-count: 1
|
||||
# libraries
|
||||
(?:\b|_)lib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||
# YouTube url
|
||||
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# GHSA
|
||||
GHSA(?:-[0-9a-z]{4}){3}
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# medium
|
||||
\bmedium\.com/\@?[^/\s"]+/[-\w]+
|
||||
# GitHub actions
|
||||
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# kubectl.kubernetes.io/last-applied-configuration
|
||||
"kubectl.kubernetes.io/last-applied-configuration": ".*"
|
||||
# medium
|
||||
\bmedium\.com/@?[^/\s"]+/[-\w]+
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# sha-... -- uses a fancy capture
|
||||
(\\?['"]|")[0-9a-f]{40,}\g{-1}
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
|
||||
\bSecur32
|
||||
|
||||
# Questionably acceptable forms of `in to`
|
||||
# Personally, I prefer `log into`, but people object
|
||||
# https://www.tprteaching.com/log-into-log-in-to-login/
|
||||
\b(?:[Ll]og|[Ss]ign) in to\b
|
||||
\b(?:(?:[Ll]og(?:g(?=[a-z])|)|[Ss]ign)(?:ed|ing)?) in to\b
|
||||
|
||||
# to opt in
|
||||
\bto opt in\b
|
||||
|
||||
# acceptable duplicates
|
||||
# ls directory listings
|
||||
[-bcdlpsw](?:[-r][-w][-Ssx]){3}\s+\d+\s+\S+\s+\S+\s+\d+\s+
|
||||
[-bcdlpsw](?:[-r][-w][-SsTtx]){3}[\.+*]?\s+\d+\s+\S+\s+\S+\s+[.\d]+(?:[KMGT]|)\s+
|
||||
# mount
|
||||
\bmount\s+-t\s+(\w+)\s+\g{-1}\b
|
||||
# C types and repeated CSS values
|
||||
\s(auto|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?: \g{-1})+\s
|
||||
# C struct
|
||||
\bstruct\s+(\w+)\s+\g{-1}\b
|
||||
\s(auto|buffalo|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?: \g{-1})+\s
|
||||
# C enum and struct
|
||||
\b(?:enum|struct)\s+(\w+)\s+\g{-1}\b
|
||||
# go templates
|
||||
\s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml):
|
||||
# doxygen / javadoc / .net
|
||||
(?:[\\@](?:brief|groupname|t?param|return|retval)|(?:public|private|\[Parameter(?:\(.+\)|)\])(?:\s+static|\s+override|\s+readonly)*)(?:\s+\{\w+\}|)\s+(\w+)\s+\g{-1}\s
|
||||
(?:[\\@](?:brief|defgroup|groupname|link|t?param|return|retval)|(?:public|private|\[Parameter(?:\(.+\)|)\])(?:\s+(?:static|override|readonly|required|virtual))*)(?:\s+\{\w+\}|)\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
# macOS file path
|
||||
(?:Contents\W+|(?!iOS)/)MacOS\b
|
||||
|
||||
# Python package registry has incorrect spelling for macOS / Mac OS X
|
||||
"Operating System :: MacOS :: MacOS X"
|
||||
|
||||
# "company" in Germany
|
||||
\bGmbH\b
|
||||
|
||||
# IntelliJ
|
||||
\bIntelliJ\b
|
||||
|
||||
# Commit message -- Signed-off-by and friends
|
||||
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
|
||||
|
||||
2
.github/actions/spell-check/reject.txt
vendored
2
.github/actions/spell-check/reject.txt
vendored
@@ -3,9 +3,11 @@
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^diables?$
|
||||
^oer$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^Teh$
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether.*
|
||||
|
||||
174
.github/workflows/spelling2.yml
vendored
174
.github/workflows/spelling2.yml
vendored
@@ -34,14 +34,14 @@ name: Spell checking
|
||||
#
|
||||
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
|
||||
|
||||
# Sarif reporting
|
||||
# SARIF reporting
|
||||
#
|
||||
# Access to Sarif reports is generally restricted (by GitHub) to members of the repository.
|
||||
# Access to SARIF reports is generally restricted (by GitHub) to members of the repository.
|
||||
#
|
||||
# Requires enabling `security-events: write`
|
||||
# and configuring the action with `use_sarif: 1`
|
||||
#
|
||||
# For information on the feature, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Sarif-output
|
||||
# For information on the feature, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-SARIF-output
|
||||
|
||||
# Minimal workflow structure:
|
||||
#
|
||||
@@ -60,23 +60,23 @@ name: Spell checking
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
- "**"
|
||||
pull_request_target:
|
||||
branches:
|
||||
- "**"
|
||||
- "**"
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
- 'synchronize'
|
||||
- "opened"
|
||||
- "reopened"
|
||||
- "synchronize"
|
||||
issue_comment:
|
||||
types:
|
||||
- 'created'
|
||||
- "created"
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
name: Spell checking
|
||||
name: Check Spelling
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
@@ -91,52 +91,59 @@ jobs:
|
||||
# note: If you use only_check_changed_files, you do not want cancel-in-progress
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.22
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
||||
checkout: true
|
||||
check_file_names: 1
|
||||
spell_check_this: microsoft/PowerToys@main
|
||||
post_comment: 0
|
||||
use_magic_file: 1
|
||||
warnings: bad-regex,binary-file,deprecated-feature,ignored-expect-variant,large-file,limited-references,no-newline-at-eof,noisy-file,non-alpha-in-dictionary,token-is-substring,unexpected-line-ending,whitespace-in-dictionary,minified-file,unsupported-configuration,no-files-to-check
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }}
|
||||
extra_dictionary_limit: 20
|
||||
extra_dictionaries:
|
||||
cspell:aws/aws.txt
|
||||
cspell:cpp/src/compiler-clang-attributes.txt
|
||||
cspell:cpp/src/compiler-msvc.txt
|
||||
cspell:cpp/src/lang-keywords.txt
|
||||
cspell:cpp/src/stdlib-c.txt
|
||||
cspell:cpp/src/stdlib-cmath.txt
|
||||
cspell:cpp/src/stdlib-cpp.txt
|
||||
cspell:csharp/csharp.txt
|
||||
cspell:css/dict/css.txt
|
||||
cspell:django/dict/django.txt
|
||||
cspell:dotnet/dict/dotnet.txt
|
||||
cspell:filetypes/filetypes.txt
|
||||
cspell:fullstack/dict/fullstack.txt
|
||||
cspell:golang/dict/go.txt
|
||||
cspell:html/dict/html.txt
|
||||
cspell:java/src/java.txt
|
||||
cspell:java/src/java-terms.txt
|
||||
cspell:k8s/dict/k8s.txt
|
||||
cspell:lorem-ipsum/dictionary.txt
|
||||
cspell:monkeyc/src/monkeyc_keywords.txt
|
||||
cspell:node/dict/node.txt
|
||||
cspell:php/dict/php.txt
|
||||
cspell:powershell/dict/powershell.txt
|
||||
cspell:python/src/common/extra.txt
|
||||
cspell:python/src/python/python.txt
|
||||
cspell:python/src/python/python-lib.txt
|
||||
cspell:scala/dict/scala.txt
|
||||
cspell:software-terms/dict/softwareTerms.txt
|
||||
cspell:swift/src/swift.txt
|
||||
cspell:typescript/dict/typescript.txt
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
||||
checkout: true
|
||||
check_file_names: 1
|
||||
spell_check_this: microsoft/PowerToys@main
|
||||
post_comment: 0
|
||||
use_magic_file: 1
|
||||
report-timing: 1
|
||||
warnings: bad-regex,binary-file,deprecated-feature,ignored-expect-variant,large-file,limited-references,no-newline-at-eof,noisy-file,non-alpha-in-dictionary,token-is-substring,unexpected-line-ending,whitespace-in-dictionary,minified-file,unsupported-configuration,no-files-to-check,unclosed-block-ignore-begin,unclosed-block-ignore-end
|
||||
experimental_apply_changes_via_bot: 1
|
||||
use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }}
|
||||
check_extra_dictionaries: ""
|
||||
dictionary_source_prefixes: >
|
||||
{
|
||||
"cspell": "https://raw.githubusercontent.com/check-spelling/cspell-dicts/v20241114/dictionaries/"
|
||||
}
|
||||
extra_dictionaries: |
|
||||
cspell:software-terms/softwareTerms.txt
|
||||
cspell:cpp/stdlib-cpp.txt
|
||||
cspell:filetypes/filetypes.txt
|
||||
cspell:cpp/stdlib-c.txt
|
||||
cspell:lorem-ipsum/dictionary.txt
|
||||
cspell:python/python/python-lib.txt
|
||||
cspell:php/php.txt
|
||||
cspell:fullstack/fullstack.txt
|
||||
cspell:dotnet/dotnet.txt
|
||||
cspell:swift/swift.txt
|
||||
cspell:node/node.txt
|
||||
cspell:dart/dart.txt
|
||||
cspell:django/django.txt
|
||||
cspell:python/python/python.txt
|
||||
cspell:powershell/powershell.txt
|
||||
cspell:npm/npm.txt
|
||||
cspell:golang/go.txt
|
||||
cspell:cpp/compiler-msvc.txt
|
||||
cspell:csharp/csharp.txt
|
||||
cspell:html/html.txt
|
||||
cspell:java/java.txt
|
||||
cspell:aws/aws.txt
|
||||
cspell:typescript/typescript.txt
|
||||
cspell:cpp/lang-keywords.txt
|
||||
cspell:python/common/extra.txt
|
||||
cspell:scala/scala.txt
|
||||
cspell:shell/shell-all-words.txt
|
||||
cspell:css/css.txt
|
||||
cspell:r/r.txt
|
||||
cspell:java/java-terms.txt
|
||||
cspell:cpp/stdlib-cerrno.txt
|
||||
cspell:k8s/k8s.txt
|
||||
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
@@ -144,16 +151,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
actions: read
|
||||
contents: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.22
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
spell_check_this: microsoft/PowerToys@main
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
spell_check_this: microsoft/PowerToys@main
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
comment-pr:
|
||||
name: Report (PR)
|
||||
@@ -161,18 +169,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.22
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
with:
|
||||
config: .github/actions/spell-check
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
|
||||
update:
|
||||
name: Update PR
|
||||
@@ -182,18 +191,19 @@ jobs:
|
||||
actions: read
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{
|
||||
github.repository_owner != 'microsoft' &&
|
||||
github.event_name == 'issue_comment' &&
|
||||
github.event.issue.pull_request &&
|
||||
contains(github.event.comment.body, '@check-spelling-bot apply')
|
||||
github.repository_owner != 'microsoft' &&
|
||||
github.event_name == 'issue_comment' &&
|
||||
github.event.issue.pull_request &&
|
||||
contains(github.event.comment.body, '@check-spelling-bot apply') &&
|
||||
contains(github.event.comment.body, 'https://')
|
||||
}}
|
||||
concurrency:
|
||||
group: spelling-update-${{ github.event.issue.number }}
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: apply spelling updates
|
||||
uses: check-spelling/check-spelling@v0.0.22
|
||||
with:
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
checkout: true
|
||||
ssh_key: "${{ secrets.CHECK_SPELLING }}"
|
||||
- name: apply spelling updates
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
with:
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
checkout: true
|
||||
ssh_key: "${{ secrets.CHECK_SPELLING }}"
|
||||
|
||||
@@ -46,8 +46,14 @@ $totalList = $projFiles | ForEach-Object -Parallel {
|
||||
|
||||
foreach($p in $temp)
|
||||
{
|
||||
# ignore "Auto-referenced" string in the output
|
||||
if ($p -match "Auto-referenced") {
|
||||
continue
|
||||
}
|
||||
|
||||
# breaking item down to usable array and getting 1 and 2, see below of a sample output
|
||||
# > PACKAGE VERSION VERSION
|
||||
# if a package is Auto-referenced, "(A)" will appear in position 1 instead of a version number.
|
||||
|
||||
$p = -split $p
|
||||
$p = $p[1, 2]
|
||||
|
||||
22
COMMUNITY.md
22
COMMUNITY.md
@@ -9,12 +9,18 @@ Names are in alphabetical order based on first name.
|
||||
### [@Aaron-Junker](https://github.com/Aaron-Junker) - [Aaron Junker](https://aaron-junker.github.io)
|
||||
Aaron has helped triaging, discussing, and creating a substantial number of issues and contributed features/fixes. Aaron was the primary person for helping build the File Explorer preview pane handler for developer files.
|
||||
|
||||
### [@cgaarden](https://github.com/cgaarden) - [Christian Gaarden Gaardmark](https://www.onegreatworld.com)
|
||||
Christian contributed New+ utility
|
||||
|
||||
### [@CleanCodeDeveloper](https://github.com/CleanCodeDeveloper)
|
||||
CleanCodeDeveloper helped do massive amounts of code stability and image resizer work.
|
||||
|
||||
### [@damienleroy](https://github.com/damienleroy) - [Damien Leroy](https://www.linkedin.com/in/Damien-Leroy-b2734416a/)
|
||||
Damien has helped out by developing and contributing the Quick Accent utility.
|
||||
|
||||
### [@daverayment ](https://github.com/daverayment ) - [David Rayment](https://www.linkedin.com/in/david-rayment-168b5251/)
|
||||
Dave has helped improve the experience inside of Peek by adding in new features and fixing bugs.
|
||||
|
||||
### [@davidegiacometti](https://github.com/davidegiacometti) - [Davide Giacometti](https://www.linkedin.com/in/davidegiacometti/)
|
||||
Davide has helped fix multiple bugs, added new utilities, features, as well as help us with the ARM64 effort by porting applications to .NET Core.
|
||||
|
||||
@@ -42,6 +48,9 @@ Color Picker is from Martin.
|
||||
### [@mikeclayton](https://github.com/mikeclayton) - [Michael Clayton](https://michael-clayton.com)
|
||||
Michael contributed the [initial version](https://github.com/microsoft/PowerToys/issues/23216) of the Mouse Jump tool and [a number of updates](https://github.com/microsoft/PowerToys/pulls?q=is%3Apr+author%3Amikeclayton) based on his FancyMouse utility.
|
||||
|
||||
### [@PesBandi](https://github.com/PesBandi/) - PesBandi
|
||||
PesBandi has helped do massive amounts of Quick Accent and bug fixes.
|
||||
|
||||
### [@riverar](https://github.com/riverar) - [Rafael Rivera](https://withinrafael.com/)
|
||||
Rafael has helped do the [upgrade from CppWinRT 1.x to 2.0](https://github.com/microsoft/PowerToys/issues/1907). He directly provided feedback to the CppWinRT team for bugs from this migration as well.
|
||||
|
||||
@@ -154,18 +163,24 @@ Other contributors:
|
||||
## PowerToys core team
|
||||
|
||||
- [@crutkas](https://github.com/crutkas/) - Clint Rutkas - Lead
|
||||
- [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang - Lead
|
||||
- [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Product Manager
|
||||
- [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Lead
|
||||
- [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang - Product Manager
|
||||
- [@plante-msft](https://github.com/plante-msft) - Connor Plante - Product Manager
|
||||
- [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager
|
||||
- [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie - Product Manager
|
||||
- [@jaimecbernardo](https://github.com/jaimecbernardo) - Jaime Bernardo - Dev lead
|
||||
- [@dhowett](https://github.com/dhowett) - Dustin Howett - Dev lead
|
||||
- [@yeelam-gordon](https://github.com/yeelam-gordon) - Gordon Lam - Dev lead
|
||||
- [@jamrobot](https://github.com/jamrobot) - Jerry Xu - Dev lead
|
||||
- [@drawbyperpetual](https://github.com/drawbyperpetual) - Anirudha Shankar - Dev
|
||||
- [@mantaionut](https://github.com/mantaionut) - Ionut Manta - Dev
|
||||
- [@donlaci](https://github.com/donlaci) - Laszlo Nemeth - Dev
|
||||
- [@gokcekantarci](https://github.com/gokcekantarci) - Gokce Kantarci - Dev
|
||||
- [@SeraphimaZykova](https://github.com/SeraphimaZykova) - Seraphima Zykova - Dev
|
||||
- [@stefansjfw](https://github.com/stefansjfw) - Stefan Markovic - Dev
|
||||
- [@lei9444](https://github.com/lei9444) - Leilei Zhang - Dev
|
||||
- [@shuaiyuanxx](https://github.com/shuaiyuanxx) - Shawn Yuan - Dev
|
||||
- [@moooyo](https://github.com/moooyo) - Yu Leng - Dev
|
||||
- [@haoliuu](https://github.com/haoliuu) - Hao Liu - Dev
|
||||
|
||||
# Former PowerToys core team members
|
||||
|
||||
@@ -176,3 +191,4 @@ Other contributors:
|
||||
- [@mykhailopylyp](https://github.com/mykhailopylyp) - Mykhailo Pylyp - Dev
|
||||
- [@taras-janea](https://github.com/taras-janea) - Taras Sich - Dev
|
||||
- [@yuyoyuppe](https://github.com/yuyoyuppe) - Andrey Nekrasov - Dev
|
||||
- [@gokcekantarci](https://github.com/gokcekantarci) - Gokce Kantarci - Dev
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<PackageVersion Include="Markdig.Signed" Version="0.34.0" />
|
||||
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
||||
<PackageVersion Include="MessagePack" Version="2.5.187" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0-preview.24508.2" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="9.0.0" />
|
||||
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
@@ -53,7 +53,7 @@
|
||||
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
|
||||
<!-- Moq to stay below v4.20 due to behavior change. need to be sure fixed -->
|
||||
<PackageVersion Include="Moq" Version="4.18.4" />
|
||||
<PackageVersion Include="MSTest" Version="3.5.0" />
|
||||
<PackageVersion Include="MSTest" Version="3.6.3" />
|
||||
<PackageVersion Include="NLog" Version="5.0.4" />
|
||||
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
||||
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
|
||||
@@ -94,4 +94,4 @@
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Client" Version="2.4.17140001" />
|
||||
<PackageVersion Include="Microsoft.VariantAssignment.Contract" Version="3.0.16990001" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1318,7 +1318,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Mages 2.0.2
|
||||
- Markdig.Signed 0.34.0
|
||||
- MessagePack 2.5.187
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0-preview.24508.2
|
||||
- Microsoft.CodeAnalysis.NetAnalyzers 9.0.0
|
||||
- Microsoft.Data.Sqlite 9.0.0
|
||||
- Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16
|
||||
- Microsoft.Extensions.DependencyInjection 9.0.0
|
||||
@@ -1326,6 +1326,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Microsoft.Extensions.Hosting.WindowsServices 9.0.0
|
||||
- Microsoft.Extensions.Logging 9.0.0
|
||||
- Microsoft.Extensions.Logging.Abstractions 9.0.0
|
||||
- Microsoft.NET.ILLink.Tasks (A)
|
||||
- Microsoft.Toolkit.Uwp.Notifications 7.1.2
|
||||
- Microsoft.Web.WebView2 1.0.2739.15
|
||||
- Microsoft.Win32.SystemEvents 9.0.0
|
||||
@@ -1338,7 +1339,7 @@ EXHIBIT A -Mozilla Public License.
|
||||
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
|
||||
- ModernWpfUI 0.9.4
|
||||
- Moq 4.18.4
|
||||
- MSTest 3.5.0
|
||||
- MSTest 3.6.3
|
||||
- NLog.Extensions.Logging 5.3.8
|
||||
- NLog.Schema 5.2.8
|
||||
- ReverseMarkdown 4.1.0
|
||||
|
||||
@@ -171,6 +171,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\.editorconfig = src\.editorconfig
|
||||
.vsconfig = .vsconfig
|
||||
src\Common.Dotnet.AotCompatibility.props = src\Common.Dotnet.AotCompatibility.props
|
||||
src\Common.Dotnet.CsWinRT.props = src\Common.Dotnet.CsWinRT.props
|
||||
src\Common.SelfContained.props = src\Common.SelfContained.props
|
||||
Cpp.Build.props = Cpp.Build.props
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Microsoft PowerToys
|
||||
|
||||

|
||||

|
||||
|
||||
[How to use PowerToys][usingPowerToys-docs-link] | [Downloads & Release notes][github-release-link] | [Contributing to PowerToys](#contributing) | [What's Happening](#whats-happening) | [Roadmap](#powertoys-roadmap)
|
||||
|
||||
@@ -20,6 +20,12 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
| [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
|
||||
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) |
|
||||
|
||||
## 🎁⭐ PowerToys Advent calendar ⭐🎁
|
||||
|
||||
We will be highlighting a cool utility each day for 24 days in December! To follow along, check out these threads:
|
||||
- https://bsky.app/profile/kaylacinnamon.bsky.social/post/3lcb7iljxck2o
|
||||
- https://x.com/cinnamon_msft/status/1863284610773246257
|
||||
|
||||
## Installing and running Microsoft PowerToys
|
||||
|
||||
### Requirements
|
||||
|
||||
@@ -47,7 +47,7 @@ registerAdditionalNewLanguage("id", [".fileExtension"], idDefinition(), monaco)
|
||||
|
||||
* The id can be anything. Recommended is one of the file extensions. For example "php" or "reg".
|
||||
|
||||
4. In case you wish to add a custom color for a token, you can do so by adding the following line to [`customTokenColors.js`](/src/Monaco/customTokenColors.js):
|
||||
4. In case you wish to add a custom color for a token, you can do so by adding the following line to [`customTokenThemeRules.js`](/src/Monaco/customTokenThemeRules.js):
|
||||
```javascript
|
||||
{token: 'token-name', foreground: 'ff0000'}
|
||||
```
|
||||
|
||||
@@ -97,6 +97,6 @@ namespace
|
||||
|
||||
```
|
||||
|
||||
Note: since _background activation_ implies that your toast handler will be invoked in a separate process, you can't share data directly from within a handler and your PT process. Also, since PT is currently a Desktop Bridge app, _foreground activation_ is [handled the same as background](https://learn.microsoft.com/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop-cpp-wrl#foreground-vs-background-activation), therefore we don't make a dedicated API for it. You can read more on the rationale of the current design [here](https://github.com/microsoft/PowerToys/pull/1178#issue-368768337).
|
||||
Note: since _background activation_ implies that your toast handler will be invoked in a separate process, you can't share data directly from within a handler and your PT process. Also, since PT is currently a Desktop Bridge app, _foreground activation_ is [handled the same as background](https://learn.microsoft.com/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop-cpp-wrl#foreground-vs-background-activation), therefore we don't make a dedicated API for it. You can read more on the [rationale of the current design](https://github.com/microsoft/PowerToys/pull/1178#issue-368768337).
|
||||
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
## Localization on the pipeline (CDPX)
|
||||
[The localization step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L45-L52) is run on the pipeline before the solution is built. This step runs the [build-localization](https://github.com/microsoft/PowerToys/blob/main/.pipelines/build-localization.cmd) script, which generates resx files for all the projects with localization enabled using the `Localization.XLoc` package.
|
||||
|
||||
The [`Localization.XLoc`](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L24-L25) tool is run on the repo root, and it checks for all occurrences of `LocProject.json`. Each localized project has a `LocProject.json` file in the project root, which contains the location of the English resx file, list of languages for localization, and the output path where the localized resx files are to be copied to. In addition to this, some other parameters can be set, such as whether the language ID should be added as a folder in the file path or in the file name. When the CDPX pipeline is run, the localization team is notified of changes in the English resx files. For each project with localization enabled, a `loc` folder (see [this](https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Microsoft.Launcher/loc) for example) is created in the same directory as the `LocProject.json` file. The folder contains language specific folders which in turn have a nested folder path equivalent to `OutputPath` in the `LocProject.json`. Each of these folders contain one `lcl` file. The `lcl` files contain the English resources along with their translation for that language. These are described in more detail [here](#lcl-files). Once the `.resx` files are generated, they will be used during the `Build PowerToys` step for localized versions of the modules.
|
||||
The [`Localization.XLoc`](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/build-localization.cmd#L24-L25) tool is run on the repo root, and it checks for all occurrences of `LocProject.json`. Each localized project has a `LocProject.json` file in the project root, which contains the location of the English resx file, list of languages for localization, and the output path where the localized resx files are to be copied to. In addition to this, some other parameters can be set, such as whether the language ID should be added as a folder in the file path or in the file name. When the CDPX pipeline is run, the localization team is notified of changes in the English resx files. For each project with localization enabled, a `loc` folder (see [this](https://github.com/microsoft/PowerToys/tree/main/src/modules/launcher/Microsoft.Launcher/loc) for example) is created in the same directory as the `LocProject.json` file. The folder contains language specific folders which in turn have a nested folder path equivalent to `OutputPath` in the `LocProject.json`. Each of these folders contain one `lcl` file. The `lcl` files contain the English resources along with their translation for that language. These are described in more detail in the [Lcl files section](#lcl-files). Once the `.resx` files are generated, they will be used during the `Build PowerToys` step for localized versions of the modules.
|
||||
|
||||
Since the localization script requires certain nuget packages, the [`restore-localization`](https://github.com/microsoft/PowerToys/blob/main/.pipelines/restore-localization.cmd) script is run before running `build-localization` to install all the required packages. This script must [run in the `restore` step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L37-L39) of pipeline because [the host is network isolated](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipelinhttps://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipeline?anchor=overview) at the `build` step. The [Toolset package source](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L23) is used for this.
|
||||
Since the localization script requires certain nuget packages, the [`restore-localization`](https://github.com/microsoft/PowerToys/blob/main/.pipelines/restore-localization.cmd) script is run before running `build-localization` to install all the required packages. This script must [run in the `restore` step](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L37-L39) of pipeline because [the host is network isolated](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/2066/Consuming-Packages-in-a-CDPx-Pipeline?anchor=overview) at the `build` step. The [Toolset package source](https://github.com/microsoft/PowerToys/blob/86d77103e9c69686c297490acb04775d43ef8b76/.pipelines/pipeline.user.windows.yml#L23) is used for this.
|
||||
|
||||
The process and variables that can be tweaked on the pipeline are described in more detail [here](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/290/Localization).
|
||||
The process and variables that can be tweaked on the pipeline are described in more detail on [onebranch (account required) under Localization](https://onebranch.visualstudio.com/Pipeline/_wiki/wikis/Pipeline.wiki/290/Localization).
|
||||
|
||||
The localized resource dlls for C# projects are added to the MSI only for build on the pipeline. This is done by checking if the [`IsPipeline` variable is defined](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L804-L805), which gets defined before building the installer on the pipeline [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/build-installer.cmd#L4). This is done because the localized resx files are only present on the pipeline, and not having this check would result in the installer project failing to build locally.
|
||||
The localized resource dlls for C# projects are added to the MSI only for build on the pipeline. This is done by checking if the [`IsPipeline` variable is defined](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L804-L805), which gets defined before [building the installer on the pipeline](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/.pipelines/build-installer.cmd#L4). This is done because the localized resx files are only present on the pipeline, and not having this check would result in the installer project failing to build locally.
|
||||
|
||||
## Enabling localization on a new project
|
||||
To enable localization on a new project, the first step is to create a file `LocProject.json` in the project root.
|
||||
@@ -45,7 +45,7 @@ For example, for a project in the folder `src\path` where the resx file is prese
|
||||
]
|
||||
}
|
||||
```
|
||||
The rest of the steps depend on the project type and are covered in the sections below. The steps to add the localized files to the MSI can be found [here](#Enabling-localized-MSI-for-a-new-project).
|
||||
The rest of the steps depend on the project type and are covered in the sections below. The steps to add the localized files to the MSI can be found in [Enabling localized MSI for a new project](#Enabling-localized-MSI-for-a-new-project).
|
||||
|
||||
### C++
|
||||
C++ projects do not support `resx` files, and instead use `rc` files along with `resource.h` files. The CDPX pipeline however doesn't support localizing `rc` files and the other alternative they support is directly translating the resources from the binary which makes it harder to maintain resources. To avoid this, a custom script has been added which expects a resx file and converts the entries to an rc file with a string table and adds resource declarations to a resource.h file so that the resources can be compiled with the C++ project.
|
||||
@@ -59,7 +59,7 @@ After generating the resx file, rename the existing rc and h files to ProjName.b
|
||||
</Target>
|
||||
```
|
||||
|
||||
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script can be found [here](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in upper case (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
|
||||
This event runs a script which generates a resource.h and ProjName.rc in the `Generated Files` folder using the strings in all the resx files along with the existing information in resource.base.h and ProjName.base.rc. The script is [convert-resx-to-rc.ps1](https://github.com/microsoft/PowerToys/blob/main/tools/build/convert-resx-to-rc.ps1). The script uses [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) to convert the resx file to a string table expected in the .rc file format. When the resources are added to the rc file the `IDS_` prefix is added and resource names are in upper case (as it was originally). Any occurrences of `"` in the string resource is escaped as `""` to prevent build errors. The string tables are added to the rc file in the following format:
|
||||
```
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
@@ -71,7 +71,7 @@ END
|
||||
|
||||
#endif
|
||||
```
|
||||
Since there is no API to identify the `AFX_TARG_*`, `LANG_*` or `SUBLANG_*` values from each langId from the pipeline, these are hardcoded in the script (for each language) as done [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/tools/build/convert-resx-to-rc.ps1#L50-L77). **If any other languages are added in the future, this script will have to be updated.** In order to determine what are the language codes, you can open the rc file in Resource View, right click the string table and press `Insert Copy` and choose the corresponding language. This autogenerates the required code and can be used to figure out the language codes. The files also add the resource declarations to a resource.h file, starting from 101 by default(this can be changed by an optional argument). Since the output files will be generated in `Generated Files`, any includes in these two files will require an additional `..\` and wherever resource.h is used, it will have to be included as `Generated Files\resource.h`. While adding `resource.base.h` and `ProjName.base.rc` to the vcxproj, these should be modified to not participate in the build to avoid build errors:
|
||||
Since there is no API to identify the `AFX_TARG_*`, `LANG_*` or `SUBLANG_*` values from each langId from the pipeline, these are hardcoded in the script (for each language) as done in [lines 50-77 of `convert-resx-to-rc.ps1`](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/tools/build/convert-resx-to-rc.ps1#L50-L77). **If any other languages are added in the future, this script will have to be updated.** In order to determine what are the language codes, you can open the rc file in Resource View, right click the string table and press `Insert Copy` and choose the corresponding language. This autogenerates the required code and can be used to figure out the language codes. The files also add the resource declarations to a resource.h file, starting from 101 by default(this can be changed by an optional argument). Since the output files will be generated in `Generated Files`, any includes in these two files will require an additional `..\` and wherever resource.h is used, it will have to be included as `Generated Files\resource.h`. While adding `resource.base.h` and `ProjName.base.rc` to the vcxproj, these should be modified to not participate in the build to avoid build errors:
|
||||
```
|
||||
<None Include="Resources.resx" />
|
||||
```
|
||||
@@ -86,7 +86,7 @@ Since C# projects natively support `resx` files, the only step required here is
|
||||
<EmbeddedResource Include="Properties\Resources.*.resx" />
|
||||
```
|
||||
|
||||
**Note:** Building with localized resources may cause a build warning `Referenced assembly 'mscorlib.dll' targets a different processor` which is a VS bug. More details can be found [here](https://github.com/microsoft/PowerToys/issues/7269).
|
||||
**Note:** Building with localized resources may cause a build warning `Referenced assembly 'mscorlib.dll' targets a different processor` which is a VS bug. More details can be found in [PowerToys issue #7269](https://github.com/microsoft/PowerToys/issues/7269).
|
||||
|
||||
**Note:** If a project needs to be migrated from XAML resources to resx, the easiest way to convert the resources would be to change to format to `=` separates resources by either manually (by Ctrl+H on a text editor), or by a script, and then running [`resgen`](https://learn.microsoft.com/dotnet/framework/tools/resgen-exe-resource-file-generator#Convert) on `Developer Command Prompt for VS` to convert it to resx format.
|
||||
```
|
||||
@@ -153,7 +153,7 @@ For C++ and UWP projects no additional files are generated with localization tha
|
||||
```
|
||||
|
||||
For C# projects, satellite dlls are generated when the project is built. For a project named `ProjName`, files are created in the format `langId\ProjName.resources.dll` where `langId` is in the same format as the lcl files. The satellite dlls need to be included with the MSI, but they must be added only if the solution is built from the build farm, as the localized resx files will not be present on local machines (and that could cause local builds of the installer to fail).
|
||||
This can be done by adding the directory name of the project [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L806) and a resource component for the project can be created [here](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L845-L847) in this format:
|
||||
This can be done by adding the directory name of the project to [Product.wxs near line 806](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L806) and a resource component for the project can be created in [Product.wxs near lines 845-847](https://github.com/microsoft/PowerToys/blob/f92bd6ffd38014c228544bb8d68d0937ce4c2b6d/installer/PowerToysSetup/Product.wxs#L845-L847) in this format:
|
||||
```
|
||||
<Component Id="ProjName_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)ProjNameInstallFolder">
|
||||
<File Id="ProjName_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\ProjName\$(var.Language)\ProjName.resources.dll" />
|
||||
|
||||
@@ -25,13 +25,13 @@ This file contains documentation for all the methods involved in key/shortcut re
|
||||
- Check if any shortcut remap is currently invoked. This is required to ensure that two remaps don't occur simultaneously at a time, and we send key up events for the shortcuts only if they are actually invoked and not for artificial key up events. In addition to that, while a remap is in the middle of execution, the keyboard state will not match the physical keys, so we do not want a remap <kbd>Ctrl+A</kbd> to <kbd>Ctrl+V</kbd> to also trigger the remap from <kbd>Ctrl+V</kbd> to <kbd>Alt+V</kbd> on pressing <kbd>Ctrl+A</kbd> on the keyboard.
|
||||
- Get the remap table as per the `activatedApp` argument (i.e. if it is empty, we get the global shortcut remap table and otherwise we get the corresponding app-specific shortcut remap table).
|
||||
- Iterate over the list of remaps in descending order of number of keys in the shortcut. This is required **for shortcut to key remaps** to ensure that if a user has both <kbd>Ctrl+A</kbd> and <kbd>Ctrl+Shift+A</kbd> remapped to some keys, and the user presses <kbd>Ctrl+Shift+A</kbd>, then we prefer the <kbd>Ctrl+Shift+A</kbd> remap. This logic would not be required if there were only shortcut to shortcut remaps, as they are invoked only on exact match.
|
||||
- If any shortcut was found to be invoked (from the first step), then we skip till we find the matching shortcut remap. If not we check if the modifiers of the original shortcut are pressed down. If they are, we check if the current key event is a key down event and it matches the action key of the original shortcut. For shortcut to shortcut and for disabling a shortcut [we have an additional step](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L208-L212) where we check if any other key is pressed apart from the original shortcut. This is required because for these two features we allow the remaps only if those exact keys are pressed. The method used for this is described in detail [here](keyboardmanagercommon.md#IsKeyboardStateClearExceptShortcut). If a win key was pressed, we store whether it was the left or the right one, in order to determine which key to set for remaps from/to the common Win key code which we added. This is so that pressing and releasing Left Win key results in that Win key getting modified and not the Right Win key.
|
||||
- If any shortcut was found to be invoked (from the first step), then we skip till we find the matching shortcut remap. If not we check if the modifiers of the original shortcut are pressed down. If they are, we check if the current key event is a key down event and it matches the action key of the original shortcut. For shortcut to shortcut and for disabling a shortcut [we have an additional step](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L208-L212) where we check if any other key is pressed apart from the original shortcut. This is required because for these two features we allow the remaps only if those exact keys are pressed. The method used for this is [described in detail](keyboardmanagercommon.md#IsKeyboardStateClearExceptShortcut). If a win key was pressed, we store whether it was the left or the right one, in order to determine which key to set for remaps from/to the common Win key code which we added. This is so that pressing and releasing Left Win key results in that Win key getting modified and not the Right Win key.
|
||||
- If the remap is to a key, we send a dummy key event followed by releasing the original shortcut's modifiers and setting the target key (or doing nothing if it is remapped to disable) and we suppress the event.
|
||||
- If the remap is to a shortcut, if the modifiers in the original shortcut are present in the target, we only set the additional modifiers and the action key of the target. If it isn't, we send a dummy key event followed by releasing the modifiers which are not common, and setting the remaining ones in the target along with the action key.
|
||||
- For both cases, we set the `isShortcutInvoked` flag to true, and set the `KeyboardManagerState.activatedApp` if it is an app-specific shortcut remap.
|
||||
- For the `isShortcutInvoked` is true scenario (i.e. the initial remap keydown section is done) there are several cases depending on the key pressed or released:
|
||||
- [**Case 1:**](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L339-L430) If a modifier in the original shortcut is released, we need to reset back to the physical keys pressed.
|
||||
- For remap to shortcut, we release the target action key if it is currently pressed, and depending on whether all the modifiers of the original shortcut are present in the target, we release the target modifiers that are not common, and set the remaining original shortcut modifiers except the one that was released. We do not need to send the original action key as that will get generate it's own key event if it is held down.
|
||||
- For remap to shortcut, we release the target action key if it is currently pressed, and depending on whether all the modifiers of the original shortcut are present in the target, we release the target modifiers that are not common, and set the remaining original shortcut modifiers except the one that was released. We do not need to send the original action key as that will get generate its own key event if it is held down.
|
||||
- For remap to key, we release the target key if it is pressed (and it is not remapped to Disable), and we set the original shortcut modifiers.
|
||||
- For both the cases we send a dummy key event at the end, since we are setting modifiers without any other key after that, and we reset all the remap variables.
|
||||
- [**Case 2:**](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L435-L461) If the original shortcut's action key is pressed again, we send the target shortcut's action key or the target key again (or for disable we just suppress the event).
|
||||
@@ -57,9 +57,9 @@ This file contains documentation for all the methods involved in key/shortcut re
|
||||
## HandleAppSpecificShortcutRemapEvent
|
||||
[This method](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L754-L809) is used for handling app-specific shortcut to shortcut and shortcut to key remaps. The general logic is as follows:
|
||||
- Check if the `dwExtraInfo` field is set to `KEYBOARDMANAGER_SHORTCUT_FLAG`. This indicates that the key event was generated by the KBM shortcut remap method using `SendInput`. This ensures that we don't read events generated by the shortcut remap method, but we still read events which are generated by the key remap method.
|
||||
- Get the name of the process in the foreground. This is done using `GetCurrentApplication` which uses `GetForegroundWindow` to get the window handle and `get_process_path` from the common lib. This approach can fail for UWP apps in full screen, so for that scenario we use the `GetGUIThreadInfo` approach to find the correct window handle, and hence the correct process name. This method is described in more detail [here](keyboardmanagercommon.md#Foreground-app-detection)
|
||||
- Get the name of the process in the foreground. This is done using `GetCurrentApplication` which uses `GetForegroundWindow` to get the window handle and `get_process_path` from the common lib. This approach can fail for UWP apps in full screen, so for that scenario we use the `GetGUIThreadInfo` approach to find the correct window handle, and hence the correct process name. This method is [described in more detail](keyboardmanagercommon.md#Foreground-app-detection)
|
||||
- By checking `KeyboardManagerState.GetActivatedApp` we check if an app-specific shortcut is currently invoked. If so, we consider this application to be the activated app. This is required because some shortcut remaps could cause the current app to lose focus and hence until the shortcut is completely released we should allow that remap to continue, otherwise the user could end up in a state where some keys do not get released. For example: remap <kbd>Ctrl+A</kbd> to <kbd>Alt+Tab</kbd> for Edge, when a user presses <kbd>Ctrl+A</kbd> the window loses focus as <kbd>Alt+Tab</kbd> gets executed.
|
||||
- If there is no app-specific shortcut currently invoked, we check if the foreground process is present in the list of app-specific remaps, either with or without the file extension and case insensitive. If it is, this is considered to be the activated app.
|
||||
- If there is no app-specific shortcut currently invoked, we check if the foreground process is present in the list of app-specific remaps, either with or without the file extension and case-insensitive. If it is, this is considered to be the activated app.
|
||||
- Call `HandleShortcutRemapEvent` with the `activatedApp` argument so that app-specific shortcut remapping takes place if it applies for the current key event.
|
||||
|
||||
## HandleSingleKeyToggleToModEvent (Obsolete - Code from PoC which is commented out)
|
||||
@@ -81,4 +81,4 @@ The [`MockedInput`](https://github.com/microsoft/PowerToys/blob/main/src/modules
|
||||
- For modifiers the behavior is slightly different as if the key state of the L/R version is modified, it should also modify the common version, and if a common version is released, it should release both the L and R versions.
|
||||
|
||||
### Tests for single key remaps and shortcut remaps
|
||||
Using the MockedInput handler, all the expected (and known) key scenarios that can occur for while pressing a [remapped key](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/SingleKeyRemappingTests.cpp) or [remapped shortcut](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/OSLevelShortcutRemappingTests.cpp) are tested. The foreground app behavior which is specific to app-specific shortcuts is tested [here](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/AppSpecificShortcutRemappingTests.cpp).
|
||||
Using the MockedInput handler, all the expected (and known) key scenarios that can occur for while pressing a [remapped key](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/SingleKeyRemappingTests.cpp) or [remapped shortcut](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/OSLevelShortcutRemappingTests.cpp) are tested. The foreground app behavior which is specific to app-specific shortcuts is tested in [AppSpecificShortcutRemappingTests.cpp](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/AppSpecificShortcutRemappingTests.cpp).
|
||||
|
||||
@@ -27,14 +27,14 @@ This file contains the documentation for the KeyboardManager PowerToy module whi
|
||||
The `KeyboardManager` module has [3 main class members](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L54-L61):
|
||||
- A static pointer to the current object of `KeyboardManager`. This is required for using the `KeyboardManager` object in the low level keyboard hook handler as that method must be static. This is described in more detail in [this section](#Low-level-keyboard-hook-handler).
|
||||
- An object of type `Input`, which is used for all the operations that involving getting or setting keyboard states. This is wrapped in an object to allow testing the remapping methods.
|
||||
- An object of type `KeyboardManagerState`. This object contains all the data related to remappings and is also used in the sense of a View Model as it used to communicate common data that is shared between the KBM UI and the backend. This class is described in more detail [here](keyboardmanagercommon.md#keyboardmanagerstate).
|
||||
- An object of type `KeyboardManagerState`. This object contains all the data related to remappings and is also used in the sense of a [View Model as it used to communicate common data that is shared between the KBM UI and the backend](keyboardmanagercommon.md#keyboardmanagerstate).
|
||||
|
||||
## Enable/Disable
|
||||
On enabling KBM, the low level keyboard hook is started, and it is unhooked on disable. This is done to allow users to manually restart KBM if some other application which registers a keyboard hook was launched after PowerToys, so that it can be brought back to the highest priority hook (as the last hook to be registered receives the input first as mentioned [here](https://learn.microsoft.com/windows/win32/winmsg/about-hooks#hook-procedures)).
|
||||
On enabling KBM, the low level keyboard hook is started, and it is unhooked on disable. This is done to allow users to manually restart KBM if some other application which registers a keyboard hook was launched after PowerToys, so that it can be brought back to the highest priority hook (as the [last hook to be registered receives the input first](https://learn.microsoft.com/windows/win32/winmsg/about-hooks#hook-procedures)).
|
||||
|
||||
In addition to stopping the hook, any active KBM UI windows are also closed on disabling. This is done because the KBM UI uses the same keyboard hook for the Type button where you can type a key/shortcut, so if KBM is disabled the windows would not be completely functional.
|
||||
|
||||
The enable/disable code can be found [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L301-L322)
|
||||
The [enable/disable code can be found in dllmain.cpp](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L301-L322)
|
||||
|
||||
## Settings format
|
||||
KBM uses two sets of settings files.
|
||||
@@ -101,10 +101,10 @@ KBM uses two sets of settings files.
|
||||
- `originalKeys` stores the key/shortcut which is to be pressed for the remap, and `newKeys` stores the key/shortcut which is to be executed.
|
||||
- Both contain semi-colon separated virtual key codes. For `remapKeys`, `originalKeys` must have only one key code, whereas for `remapShortcuts` it must have at least two key codes.
|
||||
- `inProcess` sub-key was added in `remapKeys` because there was a possibility of adding the registry based remapping approach (used by [SharpKeys](https://github.com/randyrants/sharpkeys)), so that would be under a separate sub-key while `inProcess` would be for keyboard hook based remaps. This was deprioritized as there weren't enough requests for it.
|
||||
- `remapShortcuts` is split into `global` and `appSpecific`, where `global` remaps would apply to all applications, whereas `appSpecific` would apply on when the `targetApp` is in focus. `targetApp` must be the process name of the app (with or without it's extension), e.g. `msedge` or `msedge.exe` for Microsoft Edge.
|
||||
- `remapShortcuts` is split into `global` and `appSpecific`, where `global` remaps would apply to all applications, whereas `appSpecific` would apply on when the `targetApp` is in focus. `targetApp` must be the process name of the app (with or without its extension), e.g. `msedge` or `msedge.exe` for Microsoft Edge.
|
||||
|
||||
## Loading settings
|
||||
KBM settings are loaded only on the C++ side only at start up, in the [constructor](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L67-L68). The settings file may get modified from the KBM UI on applying new remappings, but the file is not read again. The files are read from the PowerToys Settings process whenever a change is made to the file (using a FileWatcher) or whenever the KBM page is opened. The settings are updated only when the user presses the OK button from either of the Remap Keys or Remap Shortcuts windows. This is described in more detail [here](keyboardmanagerui.md#ok-and-cancel-button).
|
||||
KBM settings are loaded only on the C++ side only at start up, in the [constructor](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L67-L68). The settings file may get modified from the KBM UI on applying new remappings, but the file is not read again. The files are read from the PowerToys Settings process whenever a change is made to the file (using a FileWatcher) or whenever the KBM page is opened. The settings are updated only when the user presses the OK button from either of the Remap Keys or Remap Shortcuts windows. This is described in more detail [keyboardmanagerui: OK and Cancel button](keyboardmanagerui.md#ok-and-cancel-button).
|
||||
|
||||
## Low level keyboard hook handler
|
||||
Since the [`hook_proc`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L330-L349) cannot be a member function in the class, this is declared `static` and a `static pointer` to the `KeyboardManager` project is used ([`keyboardmanager_object_ptr`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L54-L55)).
|
||||
@@ -117,22 +117,23 @@ As seen in the code for `hook_proc`, similar to other keyboard hooks in PowerToy
|
||||
The [`HandleKeyboardHookEvent`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L384-L458) is the method which calls the corresponding remapping methods in the required order. The following checks are executed in order:
|
||||
- **`KeyboardManagerState.AreRemappingsEnabled`:** This returns false while the KBM remap tables are getting updated. If it is in this state, `HandleKeyboardHookEvent` returns `0`, i.e. the key event is not suppressed and is forwarded normally.
|
||||
- **Check for `KEYBOARDMANAGER_SUPPRESS_FLAG`:** If the key event has the suppress flag, the method returns 1 to suppress the key event.
|
||||
- **[`KeyboardManagerState.DetectSingleRemapKeyUIBackend`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L399-L408):** This method is used for handling hook operations for the single key Type UI in the Remap keys window. If the Remap keys window is open, then `HandleKeyboardHookEvent` returns `0` and the key event is forwarded normally. If the left column Type button is clicked on the Remap keys window and the window is in focus, then the key event is suppressed and the UI is updated with the latest key from the recent key events. This method is described in more detail [here](keyboardmanagercommon.md#DetectSingleRemapKeyUIBackend-and-DetectShortcutUIBackend).
|
||||
- **[`KeyboardManagerState.DetectShortcutUIBackend(data, true)`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L410-L419):** This method is used for handling hook operations for the shortcut Type UI in the Remap keys window (when `isRemapKey` arg is `true`). If the Remap keys window is open, then `HandleKeyboardHookEvent` returns `0` and the key event is forwarded normally. If the right column Type button is clicked on the Remap keys window and the window is in focus, then the key event is suppressed and the UI is updated with the shortcut from the recent key events. This method is described in more detail [here](keyboardmanagercommon.md#DetectSingleRemapKeyUIBackend-and-DetectShortcutUIBackend).
|
||||
- **`HandleSingleKeyRemapEvent`:** This method handles the single key remap logic. If a remapping takes place, the key event is suppressed. This method is described in more detail [here](keyboardeventhandlers.md#HandleSingleKeyRemapEvent).
|
||||
- **[`KeyboardManagerState.DetectSingleRemapKeyUIBackend`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L399-L408):** This method is used for handling hook operations for the single key Type UI in the Remap keys window. If the Remap keys window is open, then `HandleKeyboardHookEvent` returns `0` and the key event is forwarded normally. If the left column Type button is clicked on the Remap keys window and the window is in focus, then the key event is suppressed and the UI is updated with the latest key from the recent key events. This method is described in more detail in [DetectSingleRemapKeyUIBackend and DetectShortcutUIBackend](keyboardmanagercommon.md#DetectSingleRemapKeyUIBackend-and-DetectShortcutUIBackend).
|
||||
- **[`KeyboardManagerState.DetectShortcutUIBackend(data, true)`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L410-L419):** This method is used for handling hook operations for the shortcut Type UI in the Remap keys window (when `isRemapKey` arg is `true`). If the Remap keys window is open, then `HandleKeyboardHookEvent` returns `0` and the key event is forwarded normally. If the right column Type button is clicked on the Remap keys window and the window is in focus, then the key event is suppressed and the UI is updated with the shortcut from the recent key events. This method is also described in more detail in [DetectSingleRemapKeyUIBackend and DetectShortcutUIBackend](keyboardmanagercommon.md#DetectSingleRemapKeyUIBackend-and-DetectShortcutUIBackend).
|
||||
- **`HandleSingleKeyRemapEvent`:** This method handles the single key remap logic. If a remapping takes place, the key event is suppressed. This method is described in more detail in [HandleSingleKeyRemapEvent](keyboardeventhandlers.md#HandleSingleKeyRemapEvent).
|
||||
- **[`KeyboardManagerState.DetectShortcutUIBackend(data, false)`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L430-L439):** This method is used for handling hook operations for the shortcut Type UI in the Remap shortcuts window (when `isRemapKey` arg is `false`). If the Remap shortcuts window is open, then `HandleKeyboardHookEvent` returns `0` and the key event is forwarded normally. If the Type button is clicked on the Remap shortcuts window and the window is in focus, then the key event is suppressed and the UI is updated with the shortcut from the recent key events. **Since this is executed after the single key remap method, all single key remappings are applied when the user is on the Remap shortcuts window.**
|
||||
- **`HandleAppSpecificShortcutRemapEvent`:** This method handles the app-specific shortcut remap logic. If a remapping takes place, the key event is suppressed. This method is described in more detail [here](keyboardeventhandlers.md#HandleAppSpecificShortcutRemapEvent). **Since this is executed after the single key remap method, single key remappings have precedence over shortcut remaps and are correspondingly reflected in shortcut remaps.**
|
||||
- **`HandleOSLevelShortcutRemapEvent`:** This method handles the global shortcut remap logic. If a remapping takes place, the key event is suppressed. This method is described in more detail [here](keyboardeventhandlers.md#HandleOSLevelShortcutRemapEvent). The app-specific remap method is executed before this because if a shortcut is remapped to different keys/shortcuts for a particular app and globally, the app-specific variant should be preferred if that app is in focus. **Since this is executed after the single key remap method, single key remappings have precedence over shortcut remaps and are correspondingly reflected in shortcut remaps.**
|
||||
- **`HandleAppSpecificShortcutRemapEvent`:** This method handles the app-specific shortcut remap logic. If a remapping takes place, the key event is suppressed. This method is described in more detail in [HandleAppSpecificShortcutRemapEvent](keyboardeventhandlers.md#HandleAppSpecificShortcutRemapEvent). **Since this is executed after the single key remap method, single key remappings have precedence over shortcut remaps and are correspondingly reflected in shortcut remaps.**
|
||||
- **`HandleOSLevelShortcutRemapEvent`:** This method handles the global shortcut remap logic. If a remapping takes place, the key event is suppressed. This method is described in more detail under [HandleOSLevelShortcutRemapEvent](keyboardeventhandlers.md#HandleOSLevelShortcutRemapEvent). The app-specific remap method is executed before this because if a shortcut is remapped to different keys/shortcuts for a particular app and globally, the app-specific variant should be preferred if that app is in focus. **Since this is executed after the single key remap method, single key remappings have precedence over shortcut remaps and are correspondingly reflected in shortcut remaps.**
|
||||
|
||||
**Note:** Single key remaps need to be executed before shortcut remaps, because otherwise there can be several logical issues. For example if a user has Ctrl remapped to X and Ctrl+A remapped to Y, we can't detect Ctrl+A because the moment Ctrl is pressed it would be remapped to X before the system ever sees Ctrl+A. This is why the design decision was made to separate Remap keys and Remap shortcuts, and all key remaps are reflected in the shortcut remaps.
|
||||
|
||||
## Custom Action to launch KBM UI
|
||||
KBM uses the [`call_custom_action`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L249-L280) method from the `PowertoyModuleIface` in order to launch the KBM UI when the user clicks the Remap a key or Remap a shortcut button from the KBM settings page. On clicking the button, we check if there is already any active KBM UI window, and if there is it is brought to the foreground. If not, the corresponding KBM UI window is launched on a separate detached thread. The UI is described in more detail [here](keyboardmanagerui.md).
|
||||
KBM uses the [`call_custom_action`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L249-L280) method from the `PowertoyModuleIface` in order to launch the KBM UI when the user clicks the Remap a key or Remap a shortcut button from the KBM settings page. On clicking the button, we check if there is already any active KBM UI window, and if there is it is brought to the foreground. If not, the corresponding KBM UI window is launched on a separate detached thread. The UI is described in more detail in [Keyboard Manager UI](keyboardmanagerui.md).
|
||||
|
||||
## SendInput Special Scenarios
|
||||
|
||||
### Extended keys
|
||||
Certain keys such as the arrow keys, <kbd>right Ctrl/Alt</kbd>, and <kbd>Del/Home/Ins</kbd>, etc need to be sent with the `KEYEVENTF_EXTENDEDKEY` flag because otherwise the NumPad versions get sent, which can cause weird behavior when NumLock is on. The code can be found [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L190-L194) and the list of extended keys in code can be found [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L73-L98). Docs about extended keys can be found [here](https://learn.microsoft.com/windows/win32/inputdev/about-keyboard-input#extended-key-flag).
|
||||
Certain keys such as the arrow keys, <kbd>right Ctrl/Alt</kbd>, and <kbd>Del/Home/Ins</kbd>, etc need to be sent with the `KEYEVENTF_EXTENDEDKEY` flag because otherwise the NumPad versions get sent, which can cause weird behavior when NumLock is on. The code can be found where [`SetKeyEvent` checks `IsExtendedKey(keyCode)`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L190-L194) and the list of extended keys in code can be found in [`IsExtendedKey`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L73-L98). Docs about extended keys can be found in [Keyboard Input Overview: Extended-Key Flag
|
||||
](https://learn.microsoft.com/windows/win32/inputdev/about-keyboard-input#extended-key-flag).
|
||||
|
||||
The weird behavior that is caused by this can be found at these issues:
|
||||
- https://github.com/microsoft/PowerToys/issues/3478
|
||||
@@ -140,7 +141,7 @@ The weird behavior that is caused by this can be found at these issues:
|
||||
- https://github.com/microsoft/PowerToys/issues/3981
|
||||
|
||||
### Scan code
|
||||
Certain applications (such as Windows Terminal) may filter out key events which are set to scan code 0. Even though the `KEYEVENTF_SCANCODE` flag is not set, the `wScan` field is still sent, which defaults to 0. To avoid this issue we use the `MapVirtualKey` API to find the scan code from the virtual key code. Code can be found [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L196-L198).
|
||||
Certain applications (such as Windows Terminal) may filter out key events which are set to scan code 0. Even though the `KEYEVENTF_SCANCODE` flag is not set, the `wScan` field is still sent, which defaults to 0. To avoid this issue we use the `MapVirtualKey` API to find the scan code from the virtual key code. Code can be found in [`SetKeyEvent`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L196-L198).
|
||||
|
||||
## Special Scenarios
|
||||
Since we are using low level keyboard hooks and not actual OS level input handling certain scenarios with input require workarounds as do they not interact well with the OS input logic directly. These are covered in the sub-sections below.
|
||||
@@ -156,7 +157,7 @@ The dummy key event is currently used in the following places (the linked code s
|
||||
- https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L509-L510
|
||||
|
||||
### Suppressing Num Lock in a keyboard hook
|
||||
The <kbd>Num Lock</kbd> key state is updated by the OS before it is intercepted by low level hooks. This causes the issue that even if you suppress a <kbd>Num Lock</kbd> key event, <kbd>Num Lock</kbd> will still get toggled. In order to work around this, in the [`hook_proc`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L340-L344) whenever we suppress a <kbd>Num Lock</kbd> key down event, we send an additional <kbd>Num Lock</kbd> key up followed by key down so that the <kbd>Num Lock</kbd> state is reverted to it's previous value before the suppressed event. These are sent with a `KEYBOARDMANAGER_SUPPRESS_FLAG` in the `dwExtraInfo` field, so that we suppress them at the start of the hook (see code [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L811-L825)). Since these events will update the <kbd>Num Lock</kbd> state before the low level hooks, by suppressing them we ensure that these are not sent to any other hooks/applications and hence are only processed by the OS.
|
||||
The <kbd>Num Lock</kbd> key state is updated by the OS before it is intercepted by low level hooks. This causes the issue that even if you suppress a <kbd>Num Lock</kbd> key event, <kbd>Num Lock</kbd> will still get toggled. In order to work around this, in the [`hook_proc`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L340-L344) whenever we suppress a <kbd>Num Lock</kbd> key down event, we send an additional <kbd>Num Lock</kbd> key up followed by key down so that the <kbd>Num Lock</kbd> state is reverted to its previous value before the suppressed event. These are sent with a `KEYBOARDMANAGER_SUPPRESS_FLAG` in the `dwExtraInfo` field, so that we suppress them at the start of the hook (see code in [`SetNumLockToPreviousState`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L811-L825)). Since these events will update the <kbd>Num Lock</kbd> state before the low level hooks, by suppressing them we ensure that these are not sent to any other hooks/applications and hence are only processed by the OS.
|
||||
|
||||
This assumes that KBM is the last hook to be registered (since another hook-based app like AutoHotkey could remap NumLock to some other key which could mess up this logic).
|
||||
|
||||
@@ -167,7 +168,7 @@ While using Japanese IME on Windows, shortcuts like <kbd>Shift/Alt/Ctrl</kbd> +
|
||||
|
||||
These shortcuts are detected before low level hooks, and hence cause issues while remapping <kbd>Caps Lock</kbd> to <kbd>Shift/Alt/Ctrl</kbd> or vice-versa, as there could be an intermediate state where the system detects both the keys as being pressed. This results in a state where the modifier key does not get released since the OS suppresses the key up messages before they reach the low level hooks.
|
||||
|
||||
In order to work around this when a key down for the modifier is being processed, we send a key up for the modifier key with the `KEYBOARDMANAGER_SUPPRESS_FLAG` in the `dwExtraInfo` field, so that we suppress them at the start of the hook, and this key event would only be processed by the OS, without getting forwarded to other hooks/apps. The approach is described in more detail at [this comment](https://github.com/microsoft/PowerToys/issues/3397#issuecomment-640136416), as discussed with the AutoHotkey team. The code for the workaround can be found [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L827-L846). Tests for these scenarios have also been added at:
|
||||
In order to work around this when a key down for the modifier is being processed, we send a key up for the modifier key with the `KEYBOARDMANAGER_SUPPRESS_FLAG` in the `dwExtraInfo` field, so that we suppress them at the start of the hook, and this key event would only be processed by the OS, without getting forwarded to other hooks/apps. The approach is described in more detail at [this comment](https://github.com/microsoft/PowerToys/issues/3397#issuecomment-640136416), as discussed with the AutoHotkey team. The code for the workaround can be found in [`ResetIfModifierKeyForLowerLevelKeyHandlers`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L827-L846). Tests for these scenarios have also been added at:
|
||||
- [Tests for workaround on single key remaps](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/test/SingleKeyRemappingTests.cpp#L110-L219)
|
||||
- [Tests for workaround on shortcut remaps](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/test/OSLevelShortcutRemappingTests.cpp#L1935-L2144)
|
||||
|
||||
@@ -189,8 +190,8 @@ Using a driver approach has the benefit of not depending on precedence orders as
|
||||
|
||||
## Telemetry
|
||||
Keyboard Manager emits the following telemetry events (implemented in [trace.h](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/common/trace.h) and [trace.cpp](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/common/trace.cpp)):
|
||||
- **`KeyboardManager_EnableKeyboardManager`:** Logs a `boolean` value storing the KBM toggle state. It is logged whenever KBM is enabled or disabled (emitted [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L305-L316)).
|
||||
- **`KeyboardManager_KeyRemapCount`:** Logs the number of key to key and key to shortcut remaps (i.e. all the remaps on the Remap a key window). This gets logged on saving new settings in the Remap a key window (emitted [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L159-L163)).
|
||||
- **`KeyboardManager_OSLevelShortcutRemapCount`:** Logs the number of global shortcut to shortcut and shortcut to key remaps. This gets logged on saving new settings in the Remap a shortcut window (emitted [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L220)).
|
||||
- **`KeyboardManager_AppSpecificShortcutRemapCount`:** Logs the number of app-specific shortcut to shortcut and shortcut to key remaps. This gets logged on saving new settings in the Remap a shortcut window (emitted [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L221)).
|
||||
- **`KeyboardManager_Error`:** Logs the occurrence of an error in KBM with the name of the method, error code and the corresponding error message. This is currently used only for logging `SetWindowsHookEx` failures (emitted [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L364-L369)).
|
||||
- **`KeyboardManager_EnableKeyboardManager`:** Logs a `boolean` value storing the KBM toggle state. It is logged whenever KBM is enabled or disabled (emitted in [`enable`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L305-L306) and [`disable`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L315-L316)).
|
||||
- **`KeyboardManager_KeyRemapCount`:** Logs the number of key to key and key to shortcut remaps (i.e. all the remaps on the Remap a key window). This gets logged on saving new settings in the Remap a key window (emitted at [the end of `ApplySingleKeyRemappings`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L159-L163)).
|
||||
- **`KeyboardManager_OSLevelShortcutRemapCount`:** Logs the number of global shortcut to shortcut and shortcut to key remaps. This gets logged on saving new settings in the Remap a shortcut window (emitted at [the end of `ApplyShortcutRemappings`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L220)).
|
||||
- **`KeyboardManager_AppSpecificShortcutRemapCount`:** Logs the number of app-specific shortcut to shortcut and shortcut to key remaps. This gets logged on saving new settings in the Remap a shortcut window (emitted [after calling `OSLevelShortcutRemapCount` in `ApplyShortcutRemappings`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L221)).
|
||||
- **`KeyboardManager_Error`:** Logs the occurrence of an error in KBM with the name of the method, error code and the corresponding error message. This is currently used only for logging `SetWindowsHookEx` failures (emitted [at the end of `start_lowlevel_keyboard_hook`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L364-L369)).
|
||||
|
||||
@@ -37,7 +37,7 @@ The [`SaveConfigToFile`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a
|
||||
To prevent the UI thread and low level hook thread from concurrently accessing the remap tables we use an [`atomic bool` variable](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyboardManagerState.h#L91-L92), which is set to `true` while the tables are getting updated. When this is `true` the hook will skip all remappings. Use of mutexes in the hook were removed to prevent reentrant mutex bugs.
|
||||
|
||||
## KeyDelay
|
||||
[This class](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/common/KeyDelay.cpp) implements a queue based approach for processing key events and based on the time difference between key down and key up events [executes separate methods for `ShortPress`, `LongPress` or `LongPressReleased`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyDelay.h#L69-L72). The class is used for the hold Enter/Esc functionality required for making the Type window accessible and prevent keyboard traps (see [this](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/SingleKeyRemapControl.cpp#L273-L292) for an example of it's usage). The `KeyEvents` are added to the queue from the hook thread of KBM, and a separate [`DelayThread`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyDelay.cpp#L142-L166) is used to process the key events by checking the `time` member in the key event. The thresholds for short vs long press and hold wait timeouts are `static` constants, but if the module is extended for other purposes these could be made into arguments.
|
||||
The [KeyDelay class](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyDelay.cpp) implements a queue based approach for processing key events and based on the time difference between key down and key up events [executes separate methods for `ShortPress`, `LongPress` or `LongPressReleased`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyDelay.h#L69-L72). The class is used for the hold Enter/Esc functionality required for making the Type window accessible and prevent keyboard traps (see [this call to `keyboardManagerState.RegisterKeyDelay`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/SingleKeyRemapControl.cpp#L273-L292) for an example of its usage). The `KeyEvents` are added to the queue from the hook thread of KBM, and a separate [`DelayThread`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyDelay.cpp#L142-L166) is used to process the key events by checking the `time` member in the key event. The thresholds for short vs long press and hold wait timeouts are `static` constants, but if the module is extended for other purposes these could be made into arguments.
|
||||
|
||||
**Note:** [Deletion of the `KeyDelay`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyDelay.cpp#L4-L12) object should never be called from the `DelayThread` i.e. from within one of the 3 handlers, as it can re-enter the mutex and would lead to a deadlock. This can be avoided by either deleting it on a separate thread or as done in the KBM UI, on the dispatcher thread. See [this PR](https://github.com/microsoft/PowerToys/pull/6959#issue-496583547) for more details on this issue.
|
||||
|
||||
@@ -45,16 +45,16 @@ To prevent the UI thread and low level hook thread from concurrently accessing t
|
||||
The [`Shortcut` class](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/common/Shortcut.h) is a data structure for storing key combinations which are valid shortcuts and it contains several methods which are used for shortcut specific operations. [`RemapShortcut`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/common/RemapShortcut.h) consists of a shortcut/key union (`std::variant`), along with other boolean flags which are required on the hook side for storing any relevant keyboard states mid-execution.
|
||||
|
||||
### IsKeyboardStateClearExceptShortcut
|
||||
[This method](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Shortcut.cpp#L665-L813) is used by the `HandleShortcutRemapEvent` to check if any other keys on the keyboard have been pressed apart from the keys in the shortcut. This is required because shortcut to shortcut remaps should not be applied if the shortcut is pressed with other keys. The method iterates over all the possible key codes, except any keys that are considered reserved, unassigned, OEM-specific or undefined, as well as mouse buttons (see list [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Shortcut.cpp#L628-L663)).
|
||||
[This method](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Shortcut.cpp#L665-L813) is used by the `HandleShortcutRemapEvent` to check if any other keys on the keyboard have been pressed apart from the keys in the shortcut. This is required because shortcut to shortcut remaps should not be applied if the shortcut is pressed with other keys. The method iterates over all the possible key codes, except any keys that are considered reserved, unassigned, OEM-specific or undefined, as well as mouse buttons (see [list in `IgnoreKeyCode`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Shortcut.cpp#L628-L663)).
|
||||
|
||||
### CheckModifiersKeyboardState
|
||||
[This method](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Shortcut.cpp#L517-L614) uses `GetVirtualKeyState` (internally calls `GetAsyncKeyState` in production code), to check if all the modifiers of the current shortcut are being pressed. Since Win doesn't have a non-L/R key code we check this by checking both LWIN and RWIN.
|
||||
|
||||
### Tests
|
||||
Tests for some methods in the `Shortcut` class can be found [here](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/ShortcutTests.cpp).
|
||||
Tests for some methods in the `Shortcut` class can be found in [`OSLevelShortcutRemappingTests.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/KeyboardManagerEngineTest/OSLevelShortcutRemappingTests.cpp) and [`AppSpecificShortcutRemappingTests.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/KeyboardManagerEngineTest/AppSpecificShortcutRemappingTests.cpp).
|
||||
|
||||
## Helpers
|
||||
[This namespace](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/common/Helpers.cpp) has any methods which are used across either UI or the backend which aren't specific to either. Some of these methods have tests [here](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/test/SetKeyEventTests.cpp).
|
||||
[This namespace](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/common/Helpers.cpp) has any methods which are used across either UI or the backend which aren't specific to either. Some of these methods have tests in [`SetKeyEventTests.cpp`](https://github.com/microsoft/PowerToys/blob/main/src/modules/keyboardmanager/KeyboardManagerEngineTest/SetKeyEventTests.cpp).
|
||||
|
||||
### Foreground App Detection
|
||||
[`GetCurrentApplication`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L226-L268) is used for detecting the foreground process for App-specific shortcuts. The logic is very similar to that used for FZ's app exception feature, involving `GetForegroundWindow` and `get_process_path`. The one additional case which has been added is for full-screen UWP apps, where the above method fails and returns `ApplicationFrameHost.exe`. The [`GetFullscreenUWPWindowHandle`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/Helpers.cpp#L210-L224) uses `GetGUIThreadInfo` API to find the window linked to the GUI thread. This logic is based on [this stackoverflow answer](https://stackoverflow.com/questions/39702704/connecting-uwp-apps-hosted-by-applicationframehost-to-their-real-processes/55353165#55353165).
|
||||
|
||||
@@ -23,7 +23,7 @@ The KBM UI was originally implemented as a XAML Island, but in order to easily s
|
||||
|
||||
Mica is then achieved by calling [`BackdropMaterial::SetApplyToRootOrPageBackground()`](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditKeyboardWindow.cpp#L388-L400) in both of the editor windows, or falls back to the `ApplicationPageBackgroundThemeBrush` background if Mica isn't available.
|
||||
|
||||
The UI was also updated to use WinUI 2.8 to match the look and feel of the Fluent design language of Windows 11 and the rest of PowerToys. There has been talk about [migrating the implementation to XAML files instead of code-behind](https://github.com/microsoft/PowerToys/issues/2027) and [utilizing WinUI 3 going forward](https://github.com/microsoft/PowerToys/issues/15870). More about the update can be read in [here](https://github.com/microsoft/PowerToys/pull/28473).
|
||||
The UI was also updated to use WinUI 2.8 to match the look and feel of the Fluent design language of Windows 11 and the rest of PowerToys. There has been talk about [migrating the implementation to XAML files instead of code-behind](https://github.com/microsoft/PowerToys/issues/2027) and [utilizing WinUI 3 going forward](https://github.com/microsoft/PowerToys/issues/15870). More about the update can be read in [[Keyboard Manager] Modernize the editor UI - PR#28473](https://github.com/microsoft/PowerToys/pull/28473).
|
||||
|
||||
[**Link to the original documentation**](https://github.com/microsoft/PowerToys/blob/b3f27057d43445abc59aa04405f7c24bb895a61c/doc/devdocs/modules/keyboardmanager/keyboardmanagerui.md#c-xaml-islands)
|
||||
|
||||
@@ -43,7 +43,7 @@ When the `EditKeyboardWindow`/`EditShortcutsWindow` is created, [we iterate thro
|
||||
### OK and Cancel button
|
||||
[On pressing the OK button](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp#L66-L89) in `EditKeyboardWindow`, first the [`CheckIfRemappingsAreValid` method](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L10-L44) is executed which performs basic validity checks on the current remappings in the remap buffer (`static SingleKeyRemapControl::singleKeyRemapBuffer`), such as if there are no NULL columns and none of the source keys are repeated. All other validity checks are assumed to happen while the user adds the remapping. If this is found to be invalid a ContentDialog is displayed which shows that some remappings are invalid and if the user proceeds only the valid ones will be applied. If it is valid [`GetOrphanedKeys`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L46-L75) is executed which checks if any keys are orphaned (i.e. the key has been remapped and no other key has been remapped to it, so there is no way to send that key code), and a dialog is shown for notifying the user with a list of orphaned keys. After this the settings are [applied by adding it to the `KeyboardManagerState.singleKeyReMap` member](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L102-L164) and they are saved to the JSON file. `EditShortcutsWindow` differs slightly from this, as there is no orphaned keys check, and [on pressing OK](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp#L32-L47) both the global and app-specific shortcuts are validated and [updated](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L166-L223).
|
||||
|
||||
The code used for updating the remapping tables in `KeyboardManagerState` can be found [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyboardManagerState.cpp#L104-L183). For shortcut remaps, the `sortedKeys` vectors are updated and re-sorted whenever an element is added to them (like [this](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyboardManagerState.cpp#L135-L136)).
|
||||
The code used for updating the remapping tables in `KeyboardManagerState` can be found in [KeyboardManagerState.cpp lines 104-183](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyboardManagerState.cpp#L104-L183). For shortcut remaps, the `sortedKeys` vectors are updated and re-sorted whenever an element is added to them (like [this code in `KeyboardManagerState::AddOSLevelShortcut`](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/common/KeyboardManagerState.cpp#L135-L136)).
|
||||
|
||||
On pressing OK (after confirmation dialogs) or Cancel, the window is closed and UI states are reset.
|
||||
|
||||
@@ -106,4 +106,9 @@ Unlike the Single Key handler, there is a different set of errors that can occur
|
||||
|
||||
**Note:** After updating the buffer we have [code to handle a special case](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp#L269-L279), which was required to prevent scenarios where a drop down can get deleted but the corresponding `KeyDropDownControl` object isn't deleted. The code checks if the drop down is still linked to the parent and accordingly deletes the `KeyDropDownControl` object from the vector.
|
||||
|
||||
**IgnoreKeyToShortcutWarning special case:** [An additional](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp#L177-L181) check was added to ignore the Map to Same key error when an existing remapping is loaded. This was because a remapping like Ctrl->Ctrl+A has an intermediate step of Ctrl->Ctrl, which could lead to an error of invalid input, even though Ctrl+A is valid. The only way to actually add this is from the Type button or by adding them in a different order (like typing Shift+A and then changing Shift to Ctrl). Since the intermediate check could fail, this was causing the app to crash since the Xaml Island wouldn't be completely loaded at that point and the Flyout can't be displayed. [This](https://github.com/microsoft/PowerToys/issues/6695) is the linked issue which describes the repro scenario.
|
||||
**IgnoreKeyToShortcutWarning special case:**
|
||||
[An additional](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp#L177-L181) check was added to ignore the Map to Same key error when an existing remapping is loaded.
|
||||
This was because a remapping like Ctrl->Ctrl+A has an intermediate step of Ctrl->Ctrl, which could lead to an error of invalid input, even though Ctrl+A is valid.
|
||||
The only way to actually add this is from the Type button or by adding them in a different order (like typing Shift+A and then changing Shift to Ctrl).
|
||||
Since the intermediate check could fail, this was causing the app to crash since the Xaml Island wouldn't be completely loaded at that point and the Flyout can't be displayed.
|
||||
[Issue #6695](https://github.com/microsoft/PowerToys/issues/6695) is the linked issue which describes the repro scenario.
|
||||
|
||||
@@ -16,7 +16,7 @@ PowerToys Run UI is written in the WPF framework. The UI code is present in the
|
||||
3. **[`ResultList.xaml`](/src/modules/launcher/PowerLauncher/LauncherControl.xaml)**: This control implements the UI component for displaying results (marked in green in Fig 1). It consists of a `ListView` WPF control with a custom `ItemTemplate` to display application logo, name, tooltip text, and context menu.
|
||||
|
||||
## Data flow
|
||||
The backend code is written using the `Model-View-ViewModel (MVVM)` structural design pattern. Plugins act as `Model` in this project. A detailed overview of the project's structure is given [here](/doc/devdocs/modules/launcher/project_structure.md).
|
||||
The backend code is written using the `Model-View-ViewModel (MVVM)` structural design pattern. Plugins act as `Model` in this project. A detailed overview of the project's structure is given in [Project Structure](/doc/devdocs/modules/launcher/project_structure.md).
|
||||
|
||||
#### Flow of data between UI(view) and ViewModels
|
||||
Data flow between View and ViewModel follows typical `MVVM` scheme. Properties in viewModels are bound to WPF controls and when these properties are updated, `INotifyPropertyChanged` handler is invoked, which in turn updates UI. The diagram below provides a rough sketch of the components involved.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Value Generator Plugin
|
||||
|
||||
The Value Generator plugin is used to generate hashes for strings, to calculate base64 encodings, escape and encode URLs/URIs and to generate GUIDs versions 1, 3, 4 and 5.
|
||||
The Value Generator plugin is used to generate hashes for strings, to calculate base64 encodings, escape and encode URLs/URIs and to generate GUIDs of version 1, 3, 4, 5, and 7.
|
||||
|
||||

|
||||
|
||||
@@ -34,7 +34,10 @@ The Value Generator plugin is used to generate hashes for strings, to calculate
|
||||
|
||||
### [`GUIDGenerator`](/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.ValueGenerator/Generators/GUID/GUIDGenerator.cs)
|
||||
- Utility class for generating or calculating GUIDs
|
||||
- Generating GUID versions 1 and 4 is done using builtin APIs. [`UuidCreateSequential`](https://learn.microsoft.com/en-us/windows/win32/api/rpcdce/nf-rpcdce-uuidcreatesequential) for version 1 and `System.Guid.NewGuid()` for version 4
|
||||
- Generating GUID versions 1, 4, and 7 is done using builtin APIs:
|
||||
- [`UuidCreateSequential`](https://learn.microsoft.com/en-us/windows/win32/api/rpcdce/nf-rpcdce-uuidcreatesequential) for version 1
|
||||
- `System.Guid.NewGuid()` for version 4
|
||||
- `System.Guid.CreateVersion7()` for version 7
|
||||
- Versions 3 and 5 take two parameters, a namespace and a name
|
||||
- The namespace must be a valid GUID or one of the [predefined ones](https://datatracker.ietf.org/doc/html/rfc4122#appendix-C)
|
||||
- The `PredefinedNamespaces` dictionary contains aliases for the predefined namespaces
|
||||
|
||||
@@ -96,7 +96,7 @@ The plugin uses only these interfaces (all inside the `Main.cs`):
|
||||
|
||||
#### Build Dependency
|
||||
Access to PluginManager was needed to make this plugin work. Because of this a reference to PowerToys.PowerLauncher was needed.
|
||||
Since History Plugin needs a reference to PowerToys.PowerLauncher, it can not be set as a dependency reference in PowerToys.PowerLauncher project (else a circular reference would exist).
|
||||
Since History Plugin needs a reference to PowerToys.PowerLauncher, it cannot be set as a dependency reference in PowerToys.PowerLauncher project (else a circular reference would exist).
|
||||
This means that if you build PowerToys.PowerLauncher only it will not build History Plugin. You will need to manually build History Plugin at least once and again manually if you change it.
|
||||
|
||||
### Caching
|
||||
|
||||
@@ -32,7 +32,7 @@ Each plugin implements the `IPlugin` interface which comprises of the `Init()` a
|
||||
### Score
|
||||
- The user query is executed against each of the plugins and the result list view is updated with results from each of the plugins.
|
||||
- The ordering of the results is based on the `Score` of each Result.
|
||||
- Each plugin assigns a score to a result based on it's relevance. The results with higher scores are displayed higher in the list view and vice versa.
|
||||
- Each plugin assigns a score to a result based on its relevance. The results with higher scores are displayed higher in the list view and vice versa.
|
||||
|
||||
## Plugin settings
|
||||
Plugin settings that are editable from the settings are stored in `PowerToys Run\settings.json`. In the very first run, those settings are populated from plugin' `plugin.json` file. Unlike Wox we do not support multiple action keywords. Instead, we have `ActionKeyword` and `IsGlobal` options.
|
||||
|
||||
@@ -23,7 +23,7 @@ There are broadly two different categories of applications:
|
||||
5. Common start menu (Applications which are common to all users)
|
||||
8. Locations pointed to by the PATH environment variable.
|
||||
- To prevent applications and shortcuts present in multiple locations from showing up as duplicate results, we consider apps with the same name, executable name and full path to be the same.
|
||||
- The subtitle of the application result is set based on it's application type. It could be one of the following:
|
||||
- The subtitle of the application result is set based on its application type. It could be one of the following:
|
||||
1. Lnk Shortcuts
|
||||
2. Appref files
|
||||
3. Internet shortcut - steam and epic games
|
||||
|
||||
@@ -36,7 +36,7 @@ The user can switch to the found windows, close them or kill their process.
|
||||
| `SubtitleShowPid` | `false` | Show process id in subtitle |
|
||||
| `SubtitleShowDesktopName` | `true` | Show desktop name in subtitle (If two or more desktops exist) |
|
||||
| `ConfirmKillProcess` | `true` | Request confirmation when killing a process |
|
||||
| `KillProcessTree` | `false` | Kill process and it's child processes |
|
||||
| `KillProcessTree` | `false` | Kill process and its child processes |
|
||||
| `OpenAfterKillAndClose` | `false` | Stay open after closing windows and killing processes (Not working with kill process confirmation) |
|
||||
| `HideKillProcessOnElevatedProcesses` | `false` | Hide "kill process" button if additional permissions required |
|
||||
| `HideExplorerSettingInfo` | `false` | Hide Explorer process information |
|
||||
|
||||
@@ -10,7 +10,7 @@ Fig 1. Project along with their dependencies in `PowerToys Run` ecosystem.
|
||||
This is the startup project for the `PowerToys Run.` It is a WPF desktop application and follows the `Model-View-ViewModel (MVVM)` design pattern. Plugins play the role of `Model` and provide data to `ViewModel.`
|
||||
|
||||
#### [`PowerLauncher.Telemetry`](/src/modules/launcher/PowerLauncher.Telemetry)
|
||||
[`PowerLauncher.Telemetry`](/src/modules/launcher/PowerLauncher.Telemetry) is a .net core project that contains telemetry events generated by `PowerLauncher.` These events have been discussed in detail [here](/doc/devdocs/modules/launcher/telemetry.md).
|
||||
[`PowerLauncher.Telemetry`](/src/modules/launcher/PowerLauncher.Telemetry) is a .net core project that contains telemetry events generated by `PowerLauncher.` These events have been discussed in detail in [Launcher Telemetry](/doc/devdocs/modules/launcher/telemetry.md).
|
||||
|
||||
#### [`Wox.Core`](/src/modules/launcher/Wox.Core)
|
||||
[`Wox.Core`](/src/modules/launcher/Wox.Core) is a .net core project that contains helper classes required by the `PowerLauncher` project. Two major functionalities encapsulated in this project are [`PluginManager`](/src/modules/launcher/Wox.Core/Plugin/PluginManager.cs) and [`Query Builder.`](/src/modules/launcher/Wox.Core/Plugin/QueryBuilder.cs) [`PluginManager`](/src/modules/launcher/Wox.Core/Plugin/PluginManager.cs) provides an interface for managing C# plugins. [`Query Builder.`](/src/modules/launcher/Wox.Core/Plugin/QueryBuilder.cs) decimate user-typed query string and creates a [`Query`](/src/modules/launcher/Wox.Plugin/Query.cs) object. [`Query`](/src/modules/launcher/Wox.Plugin/Query.cs) object contains the action keyword and cleaned query, which is then sent to all plugins.
|
||||
@@ -19,6 +19,6 @@ This is the startup project for the `PowerToys Run.` It is a WPF desktop applica
|
||||
[`Wox.Infrastructure`](/src/modules/launcher/Wox.Infrastructure) is a .net core project that contains helper classes required for image manipulation and storage by the `PowerLauncher` project and the plugins. [`ImageLoader.cs`](/src/modules/launcher/Wox.Infrastructure/Image/ImageLoader.cs) class is used to load icons for `Win32` program. It also provides caching functionality to speed up image loading for frequently queried programs.
|
||||
|
||||
#### [`Wox.Plugin`](/src/modules/launcher/Wox.Plugin)
|
||||
[`Wox.Plugin`](/src/modules/launcher/Wox.Plugin) contains interfaces that facilitate communication between `PowerLauncher` and plugins. These interfaces have been discussed in detail [here](/doc/devdocs/modules/launcher/architecture.md#flow-of-data-between-viewmodels-and-pluginsmodel). It also contains a helper class for logging. [`Log.cs`](/src/modules/launcher/Wox.Plugin/Logger/Log.cs) provides an abstraction for logging error, information, and output to text files. These files are stored at `%userprofile%/appdata/local/microsoft/powertoys/powertoys run/Logs.`
|
||||
[`Wox.Plugin`](/src/modules/launcher/Wox.Plugin) contains interfaces that facilitate communication between `PowerLauncher` and plugins. These interfaces have been discussed in detail in [Flow of data between ViewModels and Plugins(Model)](/doc/devdocs/modules/launcher/architecture.md#flow-of-data-between-viewmodels-and-pluginsmodel). It also contains a helper class for logging. [`Log.cs`](/src/modules/launcher/Wox.Plugin/Logger/Log.cs) provides an abstraction for logging error, information, and output to text files. These files are stored at `%userprofile%/appdata/local/microsoft/powertoys/powertoys run/Logs.`
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Contains the executable starting point, initialization code and the list of know
|
||||
Contains code for initializing and managing the PowerToy modules. `PowertoyModule` is a RAII-style holder for the `PowertoyModuleIface` pointer, which we got by [invoking module DLL's `powertoy_create` function](https://github.com/microsoft/PowerToys/blob/1760af50c8803588cb575167baae0439af38a9c1/src/runner/powertoy_module.cpp#L13-L24).
|
||||
|
||||
#### [`powertoys_events.cpp`](/src/runner/powertoys_events.cpp)
|
||||
Contains code that handles the various events listeners, and forwards those events to the PowerToys modules. You can learn more about the current event architecture [here](/doc/devdocs/shared-hooks.md).
|
||||
Contains code that handles the various events listeners, and forwards those events to the PowerToys modules. You can learn more about the current event architecture in [shared hooks](/doc/devdocs/shared-hooks.md).
|
||||
|
||||
#### [`lowlevel_keyboard_event.cpp`](/src/runner/lowlevel_keyboard_event.cpp)
|
||||
Contains code for registering the low level keyboard event hook that listens for keyboard events. Please note that `signal_event` is called from the main thread for this event.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## PT Run
|
||||
- Any changes to the UI are saved by the settings process in the `settings.json` file located within the `/Local/Microsoft/PowerToys/Launcher/` folder.
|
||||
- PT Run watches for any changes within this file and updates it's general settings or propagates the information to the plugins, depending on the type of information.
|
||||
- PT Run watches for any changes within this file and updates its general settings or propagates the information to the plugins, depending on the type of information.
|
||||
Eg: The maximum number of results drop down updates the maximum number of rows in the results list which updates the general settings of PT Run whereas the drive detection checkbox details are dispatched to the indexer plugin.
|
||||
|
||||
## Keyboard Manager
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Overview
|
||||
`Settings` is Windows App Sdk WinUI3 .Net Unpackaged desktop application. More details about Windows App Sdk can be found [here](https://github.com/microsoft/WindowsAppSDK#windows-app-sdk---calling-all-windows-developers). More details about WinUI can be found [here](https://microsoft.github.io/microsoft-ui-xaml/about.html#what-is-it).
|
||||
`Settings` is Windows App Sdk WinUI3 .Net Unpackaged desktop application. More details about Windows App Sdk can be found in [Windows App SDK - Calling all Windows developers!](https://github.com/microsoft/WindowsAppSDK#windows-app-sdk---calling-all-windows-developers). More details about WinUI can be found in [Build apps with WinUI](https://developer.microsoft.com/en-us/windows/develop/).
|
||||
|
||||
## Settings V2 Project structure
|
||||
The Settings project .Net WinUI3 based project which
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 59 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
BIN
doc/images/overview/PT_holiday_hero_image.png
Normal file
BIN
doc/images/overview/PT_holiday_hero_image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 503 KiB |
@@ -10,8 +10,9 @@ The build ID can be found in `Core\Constants.cs` in the `BuildId` variable - it
|
||||
|
||||
The build ID moniker is made up of two components - a reference to a [Halo](https://en.wikipedia.org/wiki/Halo_(franchise)) character, and the date when the work on the specific build started in the format of `MMDDYYYY`.
|
||||
|
||||
| Build ID | Build Date |
|
||||
| Build ID | Build Date |
|
||||
|:-------------------------------------------------------------------|:------------------|
|
||||
| [`TILLSON_11272024`](#TILLSON_11272024-november-27-2024) | November 27, 2024 |
|
||||
| [`PROMETHEAN_09082024`](#PROMETHEAN_09082024-september-8-2024) | September 8, 2024 |
|
||||
| [`VISEGRADRELAY_08152024`](#VISEGRADRELAY_08152024-august-15-2024) | August 15, 2024 |
|
||||
| [`DAISY023_04102024`](#DAISY023_04102024-april-10-2024) | April 10, 2024 |
|
||||
@@ -19,13 +20,28 @@ The build ID moniker is made up of two components - a reference to a [Halo](http
|
||||
| [`LIBRARIAN_03202022`](#librarian_03202022-march-20-2022) | March 20, 2022 |
|
||||
| `ARBITER_01312022` | January 31, 2022 |
|
||||
|
||||
### `TILLSON_11272024` (November 27, 2024)
|
||||
|
||||
>[!NOTE]
|
||||
>See pull request: [Awake - `TILLSON_11272024`](https://github.com/microsoft/PowerToys/pull/36049)
|
||||
|
||||
- [#35250](https://github.com/microsoft/PowerToys/issues/35250) Updates the icon retry policy, making sure that the icon consistently and correctly renders in the tray.
|
||||
- [#35848](https://github.com/microsoft/PowerToys/issues/35848) Fixed a bug where custom tray time shortcuts for longer than 24 hours would be parsed as zero hours/zero minutes.
|
||||
- [#34716](https://github.com/microsoft/PowerToys/issues/34716) Properly recover the state icon in the tray after an `explorer.exe` crash.
|
||||
- Added configuration safeguards to make sure that invalid values for timed keep-awake times do not result in exceptions.
|
||||
- Updated the tray initialization logic, making sure we wait for it to be properly created before setting icons.
|
||||
- Expanded logging capabilities to track invoking functions.
|
||||
- Added command validation logic to make sure that incorrect command line arguments display an error.
|
||||
- Display state now shown in the tray tooltip.
|
||||
- When timed mode is used, changing the display setting will no longer reset the timer.
|
||||
|
||||
### `PROMETHEAN_09082024` (September 8, 2024)
|
||||
|
||||
>[!NOTE]
|
||||
>See pull request: [Awake - `PROMETHEAN_09082024`](https://github.com/microsoft/PowerToys/pull/34717)
|
||||
|
||||
- Updating the initialization logic to make sure that settings are respected for proper group policy and single-instance detection.
|
||||
- [#34148] Fixed a bug from the previous release that incorrectly synchronized threads for shell icon creation and initialized parent PID when it was not parented.
|
||||
- [#34148](https://github.com/microsoft/PowerToys/issues/34148) Fixed a bug from the previous release that incorrectly synchronized threads for shell icon creation and initialized parent PID when it was not parented.
|
||||
|
||||
### `VISEGRADRELAY_08152024` (August 15, 2024)
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Function Generate-FileList() {
|
||||
|
||||
$fileExclusionList = @("*.pdb", "*.lastcodeanalysissucceeded", "createdump.exe", "powertoys.exe")
|
||||
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "monacoSpecialLanguages.js", "customTokenColors.js", "*.pri")
|
||||
$fileInclusionList = @("*.dll", "*.exe", "*.json", "*.msix", "*.png", "*.gif", "*.ico", "*.cur", "*.svg", "index.html", "reg.js", "gitignore.js", "srt.js", "monacoSpecialLanguages.js", "customTokenThemeRules.js", "*.pri")
|
||||
|
||||
$dllsToIgnore = @("System.CodeDom.dll", "WindowsBase.dll")
|
||||
|
||||
|
||||
@@ -46,32 +46,28 @@ dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||
|
||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types.required_modifiers =
|
||||
dotnet_naming_symbols.types.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||
@@ -96,4 +92,176 @@ end_of_line = crlf
|
||||
dotnet_diagnostic.IDE0065.severity = none
|
||||
|
||||
# IDE0009: Add this or Me qualification
|
||||
dotnet_diagnostic.IDE0009.severity = none
|
||||
dotnet_diagnostic.IDE0009.severity = none
|
||||
|
||||
# IDE-based code analysis rules
|
||||
# IDE0005: Remove unnecessary import
|
||||
dotnet_diagnostic.IDE0005.severity = suggestion
|
||||
|
||||
# IDE0008: Use explicit type instead of 'var'
|
||||
dotnet_diagnostic.IDE0008.severity = silent
|
||||
|
||||
# IDE0016: Use throw expression
|
||||
dotnet_diagnostic.IDE0016.severity = suggestion
|
||||
|
||||
# IDE0018: Inline variable declaration
|
||||
dotnet_diagnostic.IDE0018.severity = suggestion
|
||||
|
||||
# IDE0019: Use pattern matching
|
||||
dotnet_diagnostic.IDE0019.severity = suggestion
|
||||
|
||||
# IDE0021: Use expression body for constructors
|
||||
dotnet_diagnostic.IDE0021.severity = silent
|
||||
|
||||
# IDE0022: Use expression body for methods
|
||||
dotnet_diagnostic.IDE0022.severity = silent
|
||||
|
||||
# IDE0023: Use expression body for conversion operators
|
||||
dotnet_diagnostic.IDE0023.severity = silent
|
||||
|
||||
# IDE0025: Use expression body for properties
|
||||
dotnet_diagnostic.IDE0025.severity = silent
|
||||
|
||||
# IDE0027: Use expression body for accessors
|
||||
dotnet_diagnostic.IDE0027.severity = silent
|
||||
|
||||
# IDE0028: Use collection initializers
|
||||
dotnet_diagnostic.IDE0028.severity = suggestion
|
||||
|
||||
# IDE0029: Null check can be simplified
|
||||
dotnet_diagnostic.IDE0029.severity = suggestion
|
||||
|
||||
# IDE0031: Use null propagation
|
||||
dotnet_diagnostic.IDE0031.severity = suggestion
|
||||
|
||||
# IDE0032: Use auto property
|
||||
dotnet_diagnostic.IDE0032.severity = suggestion
|
||||
|
||||
# IDE0034: Simplify default expression
|
||||
dotnet_diagnostic.IDE0034.severity = suggestion
|
||||
|
||||
# IDE0036: Order modifiers
|
||||
dotnet_diagnostic.IDE0036.severity = suggestion
|
||||
|
||||
# IDE0039: Use local function instead of lambda
|
||||
dotnet_diagnostic.IDE0039.severity = suggestion
|
||||
|
||||
# IDE0042: Deconstruct variable declaration
|
||||
dotnet_diagnostic.IDE0042.severity = suggestion
|
||||
|
||||
# IDE0044: Add readonly modifier
|
||||
dotnet_diagnostic.IDE0044.severity = suggestion
|
||||
|
||||
# IDE0045: Use conditional expression for assignment
|
||||
dotnet_diagnostic.IDE0045.severity = suggestion
|
||||
|
||||
# IDE0046: Use conditional expression for return
|
||||
dotnet_diagnostic.IDE0046.severity = suggestion
|
||||
|
||||
# IDE0047: Remove unnecessary parentheses
|
||||
dotnet_diagnostic.IDE0047.severity = suggestion
|
||||
|
||||
# IDE0051: Remove unused private member
|
||||
dotnet_diagnostic.IDE0051.severity = suggestion
|
||||
|
||||
# IDE0052: Remove unread private member
|
||||
dotnet_diagnostic.IDE0052.severity = suggestion
|
||||
|
||||
# IDE0054: Use compound assignment
|
||||
dotnet_diagnostic.IDE0054.severity = suggestion
|
||||
|
||||
# IDE0055: Fix formatting
|
||||
dotnet_diagnostic.IDE0055.severity = suggestion
|
||||
|
||||
# IDE0056: Use index operator
|
||||
dotnet_diagnostic.IDE0056.severity = suggestion
|
||||
|
||||
# IDE0057: Use range operator
|
||||
dotnet_diagnostic.IDE0057.severity = suggestion
|
||||
|
||||
# IDE0059: Remove unnecessary value assignment
|
||||
dotnet_diagnostic.IDE0059.severity = suggestion
|
||||
|
||||
# IDE0060: Remove unused parameter
|
||||
dotnet_diagnostic.IDE0060.severity = suggestion
|
||||
|
||||
# IDE0061: Use expression body for local functions
|
||||
dotnet_diagnostic.IDE0061.severity = silent
|
||||
|
||||
# IDE0063: Use simple 'using' statement
|
||||
dotnet_diagnostic.IDE0063.severity = suggestion
|
||||
|
||||
# IDE0071: Simplify interpolation
|
||||
dotnet_diagnostic.IDE0071.severity = suggestion
|
||||
|
||||
# IDE0074: Use coalesce compound assignment
|
||||
dotnet_diagnostic.IDE0074.severity = suggestion
|
||||
|
||||
# IDE0075: Simplify conditional expression
|
||||
dotnet_diagnostic.IDE0075.severity = suggestion
|
||||
|
||||
# IDE0077: Avoid legacy format target in global 'SuppressMessageAttribute'
|
||||
dotnet_diagnostic.IDE0077.severity = suggestion
|
||||
|
||||
# IDE0078: Use pattern matching
|
||||
dotnet_diagnostic.IDE0078.severity = suggestion
|
||||
|
||||
# IDE0083: Use pattern matching ('not' operator)
|
||||
dotnet_diagnostic.IDE0083.severity = suggestion
|
||||
|
||||
# IDE0090: Simplify 'new' expression
|
||||
dotnet_diagnostic.IDE0090.severity = suggestion
|
||||
|
||||
# IDE0100: Remove unnecessary equality operator
|
||||
dotnet_diagnostic.IDE0100.severity = suggestion
|
||||
|
||||
# IDE0130: Namespace does not match folder structure
|
||||
dotnet_diagnostic.IDE0130.severity = suggestion
|
||||
|
||||
# IDE0160: Use block-scoped namespace
|
||||
dotnet_diagnostic.IDE0160.severity = silent
|
||||
|
||||
# IDE0180: Use tuple to swap values
|
||||
dotnet_diagnostic.IDE0180.severity = suggestion
|
||||
|
||||
# IDE0200: Remove unnecessary lambda expression
|
||||
dotnet_diagnostic.IDE0200.severity = suggestion
|
||||
|
||||
# IDE0240: Nullable directive is redundant
|
||||
dotnet_diagnostic.IDE0240.severity = suggestion
|
||||
|
||||
# IDE0250: Struct can be made 'readonly'
|
||||
dotnet_diagnostic.IDE0250.severity = suggestion
|
||||
|
||||
# IDE0251: Member can be made 'readonly''
|
||||
dotnet_diagnostic.IDE0251.severity = suggestion
|
||||
|
||||
# IDE0260: Use pattern matching
|
||||
dotnet_diagnostic.IDE0260.severity = suggestion
|
||||
|
||||
# IDE0270: Null check can be simplified
|
||||
dotnet_diagnostic.IDE0270.severity = suggestion
|
||||
|
||||
# IDE0290: Use primary constructor
|
||||
dotnet_diagnostic.IDE0290.severity = silent
|
||||
|
||||
# IDE0300: Use collection expression for array
|
||||
dotnet_diagnostic.IDE0300.severity = suggestion
|
||||
|
||||
# IDE0301: Use collection expression for empty
|
||||
dotnet_diagnostic.IDE0301.severity = suggestion
|
||||
|
||||
# IDE0305: Use collection expression for fluent
|
||||
dotnet_diagnostic.IDE0305.severity = suggestion
|
||||
|
||||
# IDE1005: Use conditional delegate call
|
||||
dotnet_diagnostic.IDE1005.severity = suggestion
|
||||
|
||||
# CA1859: Use concrete types when possible for improved performance
|
||||
dotnet_diagnostic.CA1859.severity = suggestion
|
||||
|
||||
# CA2202: Avoid inexact read with Stream.Read
|
||||
dotnet_diagnostic.CA2022.severity = suggestion
|
||||
|
||||
# CA2263: Prefer generic overload when type is known
|
||||
dotnet_diagnostic.CA2263.severity = suggestion
|
||||
|
||||
9
src/Common.Dotnet.AotCompatibility.props
Normal file
9
src/Common.Dotnet.AotCompatibility.props
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Some items may be set in Directory.Build.props in root -->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<CsWinRTAotOptimizerEnabled>true</CsWinRTAotOptimizerEnabled>
|
||||
<CsWinRTAotWarningLevel>2</CsWinRTAotWarningLevel>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -2,8 +2,8 @@
|
||||
<!-- Include Monaco Editor source code -->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<None Include="$(MSBuildThisFileDirectory)\Monaco\customTokenColors.js">
|
||||
<Link>Assets\Monaco\customTokenColors.js</Link>
|
||||
<None Include="$(MSBuildThisFileDirectory)\Monaco\customTokenThemeRules.js">
|
||||
<Link>Assets\Monaco\customTokenThemeRules.js</Link>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(MSBuildThisFileDirectory)\Monaco\monacoSpecialLanguages.js">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
root: [
|
||||
[/^#.*$/, 'comment'],
|
||||
[/.*((?<!(^|\/))\*\*.*|\*\*(?!(\/|$))).*/, 'invalid'],
|
||||
[/((?:^!\s*(?:\\\s|\S)+)?)((?:^\s*(?:\\\s|\S)+)?)((?:\s+(?:\\\s|\S)+)*)/, ['custom-gitignore.negation', 'tag', 'invalid']]
|
||||
[/((?:^!\s*(?:\\\s|\S)+)?)((?:^\s*(?:\\\s|\S)+)?)((?:\s+(?:\\\s|\S)+)*)/, ['custom-negation', 'tag', 'invalid']]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ export function regDefinition() {
|
||||
tokenPostfix: '.reg',
|
||||
tokenizer: {
|
||||
root: [
|
||||
// Header (case sensitive)
|
||||
// Header (case-sensitive)
|
||||
[/Windows Registry Editor Version 5.00/, 'comment'],
|
||||
[/REGEDIT4/, 'comment'],
|
||||
// Comments
|
||||
|
||||
29
src/Monaco/customLanguages/srt.js
Normal file
29
src/Monaco/customLanguages/srt.js
Normal file
@@ -0,0 +1,29 @@
|
||||
export function srtDefinition() {
|
||||
return {
|
||||
tokenizer: {
|
||||
root: [
|
||||
[/\s*\d+/, 'number', '@block']
|
||||
],
|
||||
|
||||
block: [
|
||||
[/^\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}/, {
|
||||
cases: {
|
||||
'@eos': {token: 'type.identifier', next: '@subtitle'},
|
||||
'@default': {token: 'type.identifier', next: '@ignore'}
|
||||
}
|
||||
}],
|
||||
[/^$/, 'string', '@pop']
|
||||
],
|
||||
|
||||
ignore: [
|
||||
[/.+$/, '', '@subtitle']
|
||||
],
|
||||
|
||||
subtitle: [
|
||||
[/^$/, 'string', '@popall'],
|
||||
[/<\/?(?:[ibu]|font(?:\s+color="[^"]+"\s*)?)>/, 'tag'],
|
||||
[/./, 'string']
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export const customTokenColors = [
|
||||
{token: 'custom-gitignore.negation', foreground: 'c00ce0'}
|
||||
];
|
||||
3
src/Monaco/customTokenThemeRules.js
Normal file
3
src/Monaco/customTokenThemeRules.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export const customTokenThemeRules = [
|
||||
{token: 'custom-negation.gitignore', foreground: 'c00ce0'}
|
||||
];
|
||||
@@ -79,7 +79,7 @@
|
||||
<script src="http://[[PT_URL]]/monacoSpecialLanguages.js" type="module"></script>
|
||||
<script type="module">
|
||||
import { registerAdditionalLanguages } from 'http://[[PT_URL]]/monacoSpecialLanguages.js';
|
||||
import { customTokenColors } from 'http://[[PT_URL]]/customTokenColors.js';
|
||||
import { customTokenThemeRules } from 'http://[[PT_URL]]/customTokenThemeRules.js';
|
||||
require.config({ paths: { vs: 'http://[[PT_URL]]/monacoSRC/min/vs' } });
|
||||
require(['vs/editor/editor.main'], async function () {
|
||||
await registerAdditionalLanguages(monaco)
|
||||
@@ -88,7 +88,7 @@
|
||||
monaco.editor.defineTheme('theme', {
|
||||
base: theme, // Sets the base theme to "vs" or "vs-dark" depending on the user's preference
|
||||
inherit: true,
|
||||
rules: customTokenColors,
|
||||
rules: customTokenThemeRules,
|
||||
colors: {} // `colors` is a required attribute
|
||||
});
|
||||
|
||||
|
||||
@@ -2,18 +2,20 @@
|
||||
|
||||
import { regDefinition } from './customLanguages/reg.js';
|
||||
import { gitignoreDefinition } from './customLanguages/gitignore.js';
|
||||
import { srtDefinition } from './customLanguages/srt.js';
|
||||
|
||||
export async function registerAdditionalLanguages(monaco){
|
||||
await languageDefinitions();
|
||||
registerAdditionalLanguage("cppExt", [".ino", ".pde"], "cpp", monaco)
|
||||
registerAdditionalLanguage("xmlExt", [".wsdl", ".csproj", ".vcxproj", ".vbproj", ".fsproj"], "xml", monaco)
|
||||
registerAdditionalLanguage("txtExt", [".sln", ".log", ".vsconfig", ".env", ".srt", ".ahk"], "txt", monaco)
|
||||
registerAdditionalLanguage("razorExt", [".razor"], "razor", monaco)
|
||||
registerAdditionalLanguage("vbExt", [".vbs"], "vb", monaco)
|
||||
registerAdditionalLanguage("iniExt", [".inf", ".gitconfig", ".gitattributes", ".editorconfig"], "ini", monaco)
|
||||
registerAdditionalLanguage("shellExt", [".ksh", ".zsh", ".bsh"], "shell", monaco)
|
||||
registerAdditionalNewLanguage("reg", [".reg"], regDefinition(), monaco)
|
||||
registerAdditionalNewLanguage("gitignore", [".gitignore"], gitignoreDefinition(), monaco)
|
||||
registerAdditionalLanguage("cppExt", [".ino", ".pde"], "cpp", monaco);
|
||||
registerAdditionalLanguage("xmlExt", [".wsdl", ".csproj", ".vcxproj", ".vbproj", ".fsproj"], "xml", monaco);
|
||||
registerAdditionalLanguage("txtExt", [".sln", ".log", ".vsconfig", ".env", ".ahk", ".ion"], "txt", monaco);
|
||||
registerAdditionalLanguage("razorExt", [".razor"], "razor", monaco);
|
||||
registerAdditionalLanguage("vbExt", [".vbs"], "vb", monaco);
|
||||
registerAdditionalLanguage("iniExt", [".inf", ".gitconfig", ".gitattributes", ".editorconfig"], "ini", monaco);
|
||||
registerAdditionalLanguage("shellExt", [".ksh", ".zsh", ".bsh"], "shell", monaco);
|
||||
registerAdditionalNewLanguage("reg", [".reg"], regDefinition(), monaco);
|
||||
registerAdditionalNewLanguage("gitignore", [".gitignore"], gitignoreDefinition(), monaco);
|
||||
registerAdditionalNewLanguage("srt", [".srt"], srtDefinition(), monaco);
|
||||
}
|
||||
|
||||
// Language definitions taken from Monaco source code
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -109,6 +109,24 @@ namespace DPIAware
|
||||
}
|
||||
}
|
||||
|
||||
void InverseConvert(HMONITOR monitor_handle, RECT& rect)
|
||||
{
|
||||
if (monitor_handle == NULL)
|
||||
{
|
||||
const POINT ptZero = { 0, 0 };
|
||||
monitor_handle = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
UINT dpi_x, dpi_y;
|
||||
if (GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y) == S_OK)
|
||||
{
|
||||
rect.left = static_cast<long>(std::round(rect.left * static_cast<float>(DEFAULT_DPI) / dpi_x));
|
||||
rect.right = static_cast<long>(std::round(rect.right * static_cast<float>(DEFAULT_DPI) / dpi_x));
|
||||
rect.top = static_cast<long>(std::round(rect.top * static_cast<float>(DEFAULT_DPI) / dpi_y));
|
||||
rect.bottom = static_cast<long>(std::round(rect.bottom * static_cast<float>(DEFAULT_DPI) / dpi_y));
|
||||
}
|
||||
}
|
||||
|
||||
void EnableDPIAwarenessForThisProcess()
|
||||
{
|
||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace DPIAware
|
||||
void Convert(HMONITOR monitor_handle, RECT& rect);
|
||||
void ConvertByCursorPosition(float& width, float& height);
|
||||
void InverseConvert(HMONITOR monitor_handle, float& width, float& height);
|
||||
void InverseConvert(HMONITOR monitor_handle, RECT& rect);
|
||||
void EnableDPIAwarenessForThisProcess();
|
||||
|
||||
enum AwarenessLevel
|
||||
|
||||
@@ -52,3 +52,55 @@ MonitorInfo MonitorInfo::GetPrimaryMonitor()
|
||||
}
|
||||
return monitors[0];
|
||||
}
|
||||
|
||||
MonitorInfo MonitorInfo::GetFromWindow(const HWND window)
|
||||
{
|
||||
auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
||||
return MonitorInfo::MonitorInfo(monitor);
|
||||
}
|
||||
|
||||
MonitorInfo MonitorInfo::GetFromPoint(int32_t x, int32_t y)
|
||||
{
|
||||
auto monitor = MonitorFromPoint(POINT{ x, y }, MONITOR_DEFAULTTONULL);
|
||||
return MonitorInfo::MonitorInfo(monitor);
|
||||
}
|
||||
|
||||
MonitorInfo::Size MonitorInfo::GetSize(const MONITORINFOEX& monitorInfoEx)
|
||||
{
|
||||
Size size = {};
|
||||
|
||||
auto device_name = PCTSTR(monitorInfoEx.szDevice);
|
||||
|
||||
auto hdc = CreateDC(device_name, nullptr, nullptr, nullptr);
|
||||
size.width_mm = static_cast<float>(GetDeviceCaps(hdc, HORZSIZE));
|
||||
size.height_mm = static_cast<float>(GetDeviceCaps(hdc, VERTSIZE));
|
||||
if (hdc != nullptr)
|
||||
{
|
||||
ReleaseDC(nullptr, hdc);
|
||||
}
|
||||
|
||||
auto monitor = &monitorInfoEx.rcMonitor;
|
||||
size.width_logical = static_cast<uint32_t>(monitor->right - monitor->left);
|
||||
size.height_logical = static_cast<uint32_t>(monitor->bottom - monitor->top);
|
||||
|
||||
DEVMODE dev_mode = { .dmSize = sizeof DEVMODE };
|
||||
if (EnumDisplaySettingsEx(device_name, ENUM_CURRENT_SETTINGS, &dev_mode, EDS_RAWMODE))
|
||||
{
|
||||
size.width_physical = dev_mode.dmPelsWidth;
|
||||
size.height_physical = dev_mode.dmPelsHeight;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
MonitorInfo::Size MonitorInfo::GetSize() const
|
||||
{
|
||||
if (this->handle)
|
||||
{
|
||||
return MonitorInfo::GetSize(this->info);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MonitorInfo::Size{};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#pragma comment(lib, "Gdi32.lib")
|
||||
#include <Windows.h>
|
||||
|
||||
#include <compare>
|
||||
@@ -42,6 +43,15 @@ struct Box
|
||||
|
||||
class MonitorInfo
|
||||
{
|
||||
public:
|
||||
typedef struct Size
|
||||
{
|
||||
uint32_t width_logical, height_logical;
|
||||
uint32_t width_physical, height_physical;
|
||||
float width_mm, height_mm;
|
||||
} Size;
|
||||
|
||||
private:
|
||||
HMONITOR handle;
|
||||
MONITORINFOEX info = {};
|
||||
|
||||
@@ -53,8 +63,14 @@ public:
|
||||
}
|
||||
Box GetScreenSize(const bool includeNonWorkingArea) const;
|
||||
bool IsPrimary() const;
|
||||
Size GetSize() const;
|
||||
|
||||
// Returns monitor rects ordered from left to right
|
||||
static std::vector<MonitorInfo> GetMonitors(bool includeNonWorkingArea);
|
||||
static MonitorInfo GetPrimaryMonitor();
|
||||
static MonitorInfo GetFromWindow(HWND);
|
||||
static MonitorInfo GetFromPoint(int32_t, int32_t);
|
||||
|
||||
private:
|
||||
static Size GetSize(const MONITORINFOEX&);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#include <unknwn.h>
|
||||
#include <Unknwn.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Microsoft.PowerToys.Telemetry
|
||||
public const EventKeywords ProjectKeywordMeasure = (EventKeywords)0x0;
|
||||
|
||||
/// <summary>
|
||||
/// Group ID for Powertoys project.
|
||||
/// Group ID for PowerToys project.
|
||||
/// </summary>
|
||||
private static readonly string[] PowerToysTelemetryTraits = { "ETW_GROUP", "{42749043-438c-46a2-82be-c6cbeb192ff2}" };
|
||||
|
||||
|
||||
@@ -241,10 +241,12 @@ void LayoutMap::LayoutMapImpl::UpdateLayout()
|
||||
keyboardLayoutMap[VK_KANA] = L"IME Kana";
|
||||
keyboardLayoutMap[VK_HANGEUL] = L"IME Hangeul";
|
||||
keyboardLayoutMap[VK_HANGUL] = L"IME Hangul";
|
||||
keyboardLayoutMap[VK_IME_ON] = L"IME On";
|
||||
keyboardLayoutMap[VK_JUNJA] = L"IME Junja";
|
||||
keyboardLayoutMap[VK_FINAL] = L"IME Final";
|
||||
keyboardLayoutMap[VK_HANJA] = L"IME Hanja";
|
||||
keyboardLayoutMap[VK_KANJI] = L"IME Kanji";
|
||||
keyboardLayoutMap[VK_IME_OFF] = L"IME Off";
|
||||
keyboardLayoutMap[VK_CONVERT] = L"IME Convert";
|
||||
keyboardLayoutMap[VK_NONCONVERT] = L"IME Non-Convert";
|
||||
keyboardLayoutMap[VK_ACCEPT] = L"IME Kana";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#pragma once
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
// add headers that you want to pre-compile here
|
||||
#include <unknwn.h>
|
||||
#include <Unknwn.h>
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
|
||||
@@ -85,7 +85,7 @@ void Logger::init(std::string loggerName, std::wstring logFilePath, std::wstring
|
||||
{
|
||||
// todo: that message should be shown from init caller and strings should be localized
|
||||
MessageBoxW(NULL,
|
||||
L"Logger can not be initialized",
|
||||
L"Logger cannot be initialized",
|
||||
L"PowerToys",
|
||||
MB_OK | MB_ICONERROR);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <unknwn.h>
|
||||
#include <Unknwn.h>
|
||||
#include <winrt/Windows.ApplicationModel.Background.h>
|
||||
#include <winrt/Windows.Data.Xml.Dom.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "utils/com_object_factory.h"
|
||||
#include "utils/window.h"
|
||||
|
||||
#include <unknwn.h>
|
||||
#include <Unknwn.h>
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Data.Xml.Dom.h>
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
EventWaiter() {}
|
||||
EventWaiter(const std::wstring& name, std::function<void(DWORD)> callback)
|
||||
{
|
||||
// Create localExitThreadEvent and localWaitingEvent for capturing. We can not capture 'this' as we implement move constructor.
|
||||
// Create localExitThreadEvent and localWaitingEvent for capturing. We cannot capture 'this' as we implement move constructor.
|
||||
auto localExitThreadEvent = exitThreadEvent = CreateEvent(nullptr, false, false, nullptr);
|
||||
HANDLE localWaitingEvent = waitingEvent = CreateEvent(nullptr, false, false, name.c_str());
|
||||
std::thread([=]() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <winrt/Windows.Foundation.Metadata.h>
|
||||
|
||||
// The following three helper functions determine if the user has a build version higher than or equal to 19h1 (aka 1903), as that is a requirement for xaml islands
|
||||
// The following three helper functions determine if the user has a build version greater than or equal to 19h1 (aka 1903), as that is a requirement for xaml islands
|
||||
// Source : Microsoft-ui-xaml github
|
||||
// Link: https://github.com/microsoft/microsoft-ui-xaml/blob/c045cde57c5c754683d674634a0baccda34d58c4/dev/dll/SharedHelpers.cpp
|
||||
template<uint16_t APIVersion>
|
||||
|
||||
@@ -157,7 +157,7 @@ private:
|
||||
}
|
||||
catch (const winrt::hresult_error& ex)
|
||||
{
|
||||
// Looks like the only way to access the PasswordVault is through the an API that throws an exception in case the resource doesn't exist.
|
||||
// Looks like the only way to access the PasswordVault is through an API that throws an exception in case the resource doesn't exist.
|
||||
// If the debugger breaks here, just continue.
|
||||
// If you want to disable breaking here in a more permanent way, just add a condition in Visual Studio's Exception Settings to not break on win::hresult_error, but that might make you not hit other exceptions you might want to catch.
|
||||
if (ex.code() == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
<value>Add variable</value>
|
||||
</data>
|
||||
<data name="ProfileNotApplicableTitle" xml:space="preserve">
|
||||
<value>Profile can not be applied.</value>
|
||||
<value>Profile cannot be applied.</value>
|
||||
</data>
|
||||
<data name="StateProfileNotApplicableMsg" xml:space="preserve">
|
||||
<value>Variables or backup variables are invalid.</value>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
Measurement GetMeasurement(const CursorDrag& currentBounds, POINT cursorPos)
|
||||
Measurement GetMeasurement(const CursorDrag& currentBounds, POINT cursorPos, float px2mmRatio)
|
||||
{
|
||||
D2D1_RECT_F rect;
|
||||
std::tie(rect.left, rect.right) =
|
||||
@@ -17,7 +17,7 @@ namespace
|
||||
std::tie(rect.top, rect.bottom) =
|
||||
std::minmax(static_cast<float>(cursorPos.y), currentBounds.startPos.y);
|
||||
|
||||
return Measurement(rect);
|
||||
return Measurement(rect, px2mmRatio);
|
||||
}
|
||||
|
||||
void CopyToClipboard(HWND window, const BoundsToolState& toolState, POINT cursorPos)
|
||||
@@ -29,7 +29,8 @@ namespace
|
||||
|
||||
if (handle == window && perScreen.currentBounds)
|
||||
{
|
||||
allMeasurements.push_back(GetMeasurement(*perScreen.currentBounds, cursorPos));
|
||||
auto px2mmRatio = toolState.commonState->GetPhysicalPx2MmRatio(window);
|
||||
allMeasurements.push_back(GetMeasurement(*perScreen.currentBounds, cursorPos, px2mmRatio));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +86,8 @@ namespace
|
||||
|
||||
if (const bool shiftPress = GetKeyState(VK_SHIFT) & 0x80000; shiftPress && perScreen.currentBounds)
|
||||
{
|
||||
perScreen.measurements.push_back(GetMeasurement(*perScreen.currentBounds, cursorPos));
|
||||
auto px2mmRatio = toolState->commonState->GetPhysicalPx2MmRatio(window);
|
||||
perScreen.measurements.push_back(GetMeasurement(*perScreen.currentBounds, cursorPos, px2mmRatio));
|
||||
}
|
||||
|
||||
perScreen.currentBounds = std::nullopt;
|
||||
@@ -274,7 +276,7 @@ namespace
|
||||
text.buffer.size(),
|
||||
true,
|
||||
true,
|
||||
commonState.units);
|
||||
commonState.units | Measurement::Unit::Pixel); // Always show pixels.
|
||||
|
||||
D2D_POINT_2F textBoxPos;
|
||||
if (textBoxCenter)
|
||||
@@ -314,6 +316,7 @@ void DrawBoundsToolTick(const CommonState& commonState,
|
||||
D2D1_RECT_F rect;
|
||||
std::tie(rect.left, rect.right) = std::minmax(perScreen.currentBounds->startPos.x, perScreen.currentBounds->currentPos.x);
|
||||
std::tie(rect.top, rect.bottom) = std::minmax(perScreen.currentBounds->startPos.y, perScreen.currentBounds->currentPos.y);
|
||||
DrawMeasurement(Measurement{ rect }, commonState, window, d2dState, perScreen.currentBounds->currentPos);
|
||||
auto px2mmRatio = toolState.commonState->GetPhysicalPx2MmRatio(window);
|
||||
DrawMeasurement(Measurement{ rect, px2mmRatio }, commonState, window, d2dState, perScreen.currentBounds->currentPos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ D2DState::D2DState(const DxgiAPI* dxgi,
|
||||
|
||||
void D2DState::DrawTextBox(const wchar_t* text,
|
||||
const size_t textLen,
|
||||
const std::optional<size_t> halfOpaqueSymbolPos,
|
||||
const size_t halfOpaqueSymbolPos[2],
|
||||
const D2D_POINT_2F center,
|
||||
const bool screenQuadrantAware,
|
||||
const HWND window) const
|
||||
@@ -80,8 +80,7 @@ void D2DState::DrawTextBox(const wchar_t* text,
|
||||
&textLayout));
|
||||
DWRITE_TEXT_METRICS textMetrics = {};
|
||||
winrt::check_hresult(textLayout->GetMetrics(&textMetrics));
|
||||
// Assumes text doesn't contain new lines
|
||||
const float lineHeight = textMetrics.height;
|
||||
const float lineHeight = textMetrics.height / (textMetrics.lineCount ? textMetrics.lineCount : 1);
|
||||
textMetrics.width += lineHeight;
|
||||
textMetrics.height += lineHeight * .5f;
|
||||
winrt::check_hresult(textLayout->SetMaxWidth(textMetrics.width));
|
||||
@@ -147,12 +146,17 @@ void D2DState::DrawTextBox(const wchar_t* text,
|
||||
// Draw text & its box
|
||||
dxgiWindowState.rt->FillRoundedRectangle(textBoxRect, solidBrushes[Brush::background].get());
|
||||
|
||||
if (halfOpaqueSymbolPos.has_value())
|
||||
if (halfOpaqueSymbolPos[0] > 0)
|
||||
{
|
||||
DWRITE_TEXT_RANGE textRange = { static_cast<uint32_t>(*halfOpaqueSymbolPos), 2 };
|
||||
auto opacityEffect = winrt::make_self<OpacityEffect>();
|
||||
opacityEffect->alpha = consts::CROSS_OPACITY;
|
||||
winrt::check_hresult(textLayout->SetDrawingEffect(opacityEffect.get(), textRange));
|
||||
if (halfOpaqueSymbolPos[1] > halfOpaqueSymbolPos[0])
|
||||
{
|
||||
textRange = { static_cast<uint32_t>(halfOpaqueSymbolPos[1]), 2 };
|
||||
winrt::check_hresult(textLayout->SetDrawingEffect(opacityEffect.get(), textRange));
|
||||
}
|
||||
}
|
||||
winrt::check_hresult(textLayout->Draw(nullptr, textRenderer.get(), textRect.left, textRect.top));
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ struct D2DState
|
||||
std::vector<D2D1::ColorF> solidBrushesColors);
|
||||
void DrawTextBox(const wchar_t* text,
|
||||
const size_t textLen,
|
||||
const std::optional<size_t> halfOpaqueSymbolPos,
|
||||
const size_t halfOpaqueSymbolPos[2],
|
||||
const D2D_POINT_2F center,
|
||||
const bool screenQuadrantAware,
|
||||
const HWND window) const;
|
||||
|
||||
@@ -19,17 +19,17 @@ namespace
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case MeasureToolState::Mode::Cross:
|
||||
return { true, true };
|
||||
case MeasureToolState::Mode::Cross:
|
||||
return { true, true };
|
||||
|
||||
case MeasureToolState::Mode::Vertical:
|
||||
return { false, true };
|
||||
case MeasureToolState::Mode::Vertical:
|
||||
return { false, true };
|
||||
|
||||
case MeasureToolState::Mode::Horizontal:
|
||||
return { true, false };
|
||||
case MeasureToolState::Mode::Horizontal:
|
||||
return { true, false };
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Unknown MeasureToolState Mode");
|
||||
default:
|
||||
throw std::runtime_error("Unknown MeasureToolState Mode");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace
|
||||
CopyToClipboard(window, *toolState);
|
||||
|
||||
auto& perScreen = toolState->perScreen[window];
|
||||
|
||||
|
||||
const bool shiftPress = GetKeyState(VK_SHIFT) & 0x8000;
|
||||
if (shiftPress && perScreen.measuredEdges)
|
||||
{
|
||||
@@ -144,10 +144,10 @@ namespace
|
||||
|
||||
const auto [crossSymbolPos, measureStringBufLen] =
|
||||
measurement.Print(text.buffer.data(),
|
||||
text.buffer.size(),
|
||||
drawHorizontalCrossLine,
|
||||
drawVerticalCrossLine,
|
||||
commonState.units);
|
||||
text.buffer.size(),
|
||||
drawHorizontalCrossLine,
|
||||
drawVerticalCrossLine,
|
||||
commonState.units | Measurement::Unit::Pixel); // Always show pixels.
|
||||
|
||||
d2dState.DrawTextBox(text.buffer.data(),
|
||||
measureStringBufLen,
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
Measurement::Measurement(RECT winRect)
|
||||
Measurement::Measurement(RECT winRect, float px2mmRatio) :
|
||||
px2mmRatio{ px2mmRatio }
|
||||
{
|
||||
rect.left = static_cast<float>(winRect.left);
|
||||
rect.right = static_cast<float>(winRect.right);
|
||||
@@ -12,81 +13,192 @@ Measurement::Measurement(RECT winRect)
|
||||
rect.bottom = static_cast<float>(winRect.bottom);
|
||||
}
|
||||
|
||||
Measurement::Measurement(D2D1_RECT_F d2dRect) :
|
||||
rect{ d2dRect }
|
||||
Measurement::Measurement(D2D1_RECT_F d2dRect, float px2mmRatio) :
|
||||
rect{ d2dRect }, px2mmRatio{ px2mmRatio }
|
||||
{
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
inline float Convert(const float pixels, const Measurement::Unit units)
|
||||
inline float Convert(const float pixels, const Measurement::Unit units, float px2mmRatio)
|
||||
{
|
||||
switch (units)
|
||||
if (px2mmRatio > 0)
|
||||
{
|
||||
case Measurement::Unit::Pixel:
|
||||
return pixels;
|
||||
case Measurement::Unit::Inch:
|
||||
return pixels / 96.f;
|
||||
case Measurement::Unit::Centimetre:
|
||||
return pixels / 96.f * 2.54f;
|
||||
default:
|
||||
return pixels;
|
||||
switch (units)
|
||||
{
|
||||
case Measurement::Unit::Pixel:
|
||||
return pixels;
|
||||
case Measurement::Unit::Inch:
|
||||
return pixels * px2mmRatio / 10.0f / 2.54f;
|
||||
case Measurement::Unit::Centimetre:
|
||||
return pixels * px2mmRatio / 10.0f;
|
||||
case Measurement::Unit::Millimetre:
|
||||
return pixels * px2mmRatio;
|
||||
default:
|
||||
return pixels;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (units)
|
||||
{
|
||||
case Measurement::Unit::Pixel:
|
||||
return pixels;
|
||||
case Measurement::Unit::Inch:
|
||||
return pixels / 96.0f;
|
||||
case Measurement::Unit::Centimetre:
|
||||
return pixels / 96.0f * 2.54f;
|
||||
case Measurement::Unit::Millimetre:
|
||||
return pixels / 96.0f / 10.0f * 2.54f;
|
||||
default:
|
||||
return pixels;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
winrt::hstring Measurement::abbreviations[4]{};
|
||||
|
||||
inline float Measurement::Width(const Unit units) const
|
||||
{
|
||||
return Convert(rect.right - rect.left + 1.f, units);
|
||||
return Convert(rect.right - rect.left + 1.f, units, px2mmRatio);
|
||||
}
|
||||
|
||||
inline float Measurement::Height(const Unit units) const
|
||||
{
|
||||
return Convert(rect.bottom - rect.top + 1.f, units);
|
||||
return Convert(rect.bottom - rect.top + 1.f, units, px2mmRatio);
|
||||
}
|
||||
|
||||
Measurement::Unit Measurement::GetUnitFromIndex(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return Measurement::Unit::Pixel;
|
||||
case 1:
|
||||
return Measurement::Unit::Inch;
|
||||
case 2:
|
||||
return Measurement::Unit::Centimetre;
|
||||
case 3:
|
||||
return Measurement::Unit::Millimetre;
|
||||
default:
|
||||
return Measurement::Unit::Pixel;
|
||||
}
|
||||
}
|
||||
|
||||
void Measurement::InitResources()
|
||||
{
|
||||
auto rm = winrt::ResourceManager{};
|
||||
auto mm = rm.MainResourceMap();
|
||||
abbreviations[0] = mm.GetValue(L"Resources/MeasurementUnitAbbrPixel").ValueAsString();
|
||||
abbreviations[1] = mm.GetValue(L"Resources/MeasurementUnitAbbrInch").ValueAsString();
|
||||
abbreviations[2] = mm.GetValue(L"Resources/MeasurementUnitAbbrCentimetre").ValueAsString();
|
||||
abbreviations[3] = mm.GetValue(L"Resources/MeasurementUnitAbbrMillimetre").ValueAsString();
|
||||
}
|
||||
|
||||
const wchar_t* Measurement::GetUnitAbbreviation(Measurement::Unit units)
|
||||
{
|
||||
switch (units)
|
||||
{
|
||||
case Unit::Pixel:
|
||||
return abbreviations[0].c_str();
|
||||
case Unit::Inch:
|
||||
return abbreviations[1].c_str();
|
||||
case Unit::Centimetre:
|
||||
return abbreviations[2].c_str();
|
||||
case Unit::Millimetre:
|
||||
return abbreviations[3].c_str();
|
||||
default:
|
||||
return L"??";
|
||||
}
|
||||
}
|
||||
|
||||
Measurement::PrintResult Measurement::Print(wchar_t* buf,
|
||||
const size_t bufSize,
|
||||
const bool printWidth,
|
||||
const bool printHeight,
|
||||
const Unit units) const
|
||||
const int units) const
|
||||
{
|
||||
PrintResult result;
|
||||
if (printWidth)
|
||||
{
|
||||
result.strLen += swprintf_s(buf,
|
||||
bufSize,
|
||||
L"%g",
|
||||
Width(units));
|
||||
if (printHeight)
|
||||
|
||||
auto print = [=, &result](Measurement::Unit unit, const bool paren) {
|
||||
if (paren)
|
||||
{
|
||||
result.strLen += swprintf_s(buf + result.strLen, bufSize - result.strLen, printWidth && printHeight ? L"\n(" : L" (");
|
||||
}
|
||||
if (printWidth)
|
||||
{
|
||||
result.crossSymbolPos = result.strLen + 1;
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" \x00D7 ");
|
||||
L"%.4g",
|
||||
Width(unit));
|
||||
if (printHeight)
|
||||
{
|
||||
result.crossSymbolPos[paren] = result.strLen + 1;
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" \x00D7 ");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (printHeight)
|
||||
{
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L"%.4g",
|
||||
Height(unit));
|
||||
}
|
||||
switch (unit)
|
||||
{
|
||||
case Measurement::Unit::Pixel:
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" %s",
|
||||
Measurement::GetUnitAbbreviation(unit));
|
||||
break;
|
||||
case Measurement::Unit::Inch:
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" %s",
|
||||
Measurement::GetUnitAbbreviation(unit));
|
||||
break;
|
||||
case Measurement::Unit::Centimetre:
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" %s",
|
||||
Measurement::GetUnitAbbreviation(unit));
|
||||
|
||||
if (printHeight)
|
||||
{
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L"%g",
|
||||
Height(units));
|
||||
}
|
||||
break;
|
||||
case Measurement::Unit::Millimetre:
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" %s",
|
||||
Measurement::GetUnitAbbreviation(unit));
|
||||
|
||||
switch (units)
|
||||
break;
|
||||
}
|
||||
if (paren)
|
||||
{
|
||||
result.strLen += swprintf_s(buf + result.strLen, bufSize - result.strLen, L")");
|
||||
}
|
||||
};
|
||||
|
||||
int count = 0;
|
||||
const Measurement::Unit allUnits[] = {
|
||||
Measurement::Unit::Pixel,
|
||||
Measurement::Unit::Millimetre,
|
||||
Measurement::Unit::Inch,
|
||||
Measurement::Unit::Centimetre,
|
||||
};
|
||||
// We only use two units at most, it would be to long otherwise.
|
||||
for each (Measurement::Unit unit in allUnits)
|
||||
{
|
||||
case Measurement::Unit::Inch:
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" in");
|
||||
break;
|
||||
case Measurement::Unit::Centimetre:
|
||||
result.strLen += swprintf_s(buf + result.strLen,
|
||||
bufSize - result.strLen,
|
||||
L" cm");
|
||||
break;
|
||||
if ((unit & units) == unit)
|
||||
{
|
||||
count += 1;
|
||||
if (count > 2)
|
||||
break;
|
||||
print(unit, count != 1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -117,15 +229,9 @@ void Measurement::PrintToStream(std::wostream& stream,
|
||||
stream << Height(units);
|
||||
}
|
||||
|
||||
switch (units)
|
||||
// If the unit is pixels, then the abbreviation will not be saved as it used to be.
|
||||
if (units != Measurement::Unit::Pixel)
|
||||
{
|
||||
case Measurement::Unit::Inch:
|
||||
stream << L" in";
|
||||
|
||||
break;
|
||||
case Measurement::Unit::Centimetre:
|
||||
stream << L" cm";
|
||||
break;
|
||||
stream << L" " << Measurement::GetUnitAbbreviation(units);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "pch.h"
|
||||
|
||||
#include <dcommon.h>
|
||||
#include <windef.h>
|
||||
@@ -8,38 +9,45 @@ struct Measurement
|
||||
{
|
||||
enum Unit
|
||||
{
|
||||
Pixel,
|
||||
Inch,
|
||||
Centimetre
|
||||
Pixel = 1,
|
||||
Inch = 2,
|
||||
Centimetre = 4,
|
||||
Millimetre = 8,
|
||||
};
|
||||
|
||||
D2D1_RECT_F rect = {}; // corners are inclusive
|
||||
|
||||
Measurement() = default;
|
||||
float px2mmRatio = 0;
|
||||
static winrt::hstring abbreviations[4]; // Abbreviations of units.
|
||||
|
||||
Measurement(const Measurement&) = default;
|
||||
Measurement& operator=(const Measurement&) = default;
|
||||
|
||||
explicit Measurement(D2D1_RECT_F d2dRect);
|
||||
explicit Measurement(RECT winRect);
|
||||
explicit Measurement(D2D1_RECT_F d2dRect, float px2mmRatio);
|
||||
explicit Measurement(RECT winRect, float px2mmRatio);
|
||||
|
||||
float Width(const Unit units) const;
|
||||
float Height(const Unit units) const;
|
||||
|
||||
struct PrintResult
|
||||
{
|
||||
std::optional<size_t> crossSymbolPos;
|
||||
size_t crossSymbolPos[2] = {};
|
||||
size_t strLen = {};
|
||||
};
|
||||
|
||||
static void InitResources();
|
||||
static Unit GetUnitFromIndex(int index);
|
||||
static const wchar_t* GetUnitAbbreviation(const Unit units);
|
||||
|
||||
PrintResult Print(wchar_t* buf,
|
||||
const size_t bufSize,
|
||||
const bool printWidth,
|
||||
const bool printHeight,
|
||||
const Unit units) const;
|
||||
const int units) const;
|
||||
|
||||
void PrintToStream(std::wostream& stream,
|
||||
const bool prependNewLine,
|
||||
const bool printWidth,
|
||||
const bool printHeight,
|
||||
const Unit units) const;
|
||||
const bool prependNewLine,
|
||||
const bool printWidth,
|
||||
const bool printHeight,
|
||||
const Unit units) const;
|
||||
};
|
||||
|
||||
@@ -62,6 +62,11 @@ namespace winrt::PowerToys::MeasureToolCore::implementation
|
||||
_mouseCaptureThread.join();
|
||||
}
|
||||
|
||||
void Core::InitResources()
|
||||
{
|
||||
Measurement::InitResources();
|
||||
}
|
||||
|
||||
void Core::ResetState()
|
||||
{
|
||||
_commonState.closeOnOtherMonitors = true;
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace winrt::PowerToys::MeasureToolCore::implementation
|
||||
~Core();
|
||||
void Close();
|
||||
|
||||
void InitResources();
|
||||
void StartBoundsTool();
|
||||
void StartMeasureTool(const bool horizontal, const bool vertical);
|
||||
void SetToolCompletionEvent(ToolSessionCompleted sessionCompletedTrigger);
|
||||
@@ -45,7 +46,7 @@ namespace winrt::PowerToys::MeasureToolCore::implementation
|
||||
wil::shared_event _stopMouseCaptureThreadSignal;
|
||||
std::thread _mouseCaptureThread;
|
||||
std::vector<std::thread> _screenCaptureThreads;
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<OverlayUIState>> _overlayUIStates;
|
||||
Serialized<MeasureToolState> _measureToolState;
|
||||
BoundsToolState _boundsToolState;
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace PowerToys
|
||||
void StartBoundsTool();
|
||||
void ResetState();
|
||||
|
||||
void InitResources();
|
||||
void SetToolbarBoundingBox(Int32 fromX, Int32 fromY, Int32 toX, Int32 toY);
|
||||
Single GetDPIScaleForWindow(Int64 windowHandle);
|
||||
}
|
||||
|
||||
@@ -294,11 +294,12 @@ void UpdateCaptureState(const CommonState& commonState,
|
||||
cursorPos,
|
||||
perColorChannelEdgeDetection,
|
||||
pixelTolerance);
|
||||
auto px2mmRatio = commonState.GetPhysicalPx2MmRatio(window);
|
||||
|
||||
#if defined(DEBUG_EDGES)
|
||||
char buffer[256];
|
||||
sprintf_s(buffer,
|
||||
"Cursor: [%ld,%ld] Bounds: [%ld,%ld]-[%ld,%ld] Screen size: [%zu, %zu]\n",
|
||||
"Cursor: [%ld,%ld] Bounds: [%ld,%ld]-[%ld,%ld] Screen size: [%zu, %zu] Ratio: %g\n",
|
||||
cursorPos.x,
|
||||
cursorPos.y,
|
||||
bounds.left,
|
||||
@@ -306,11 +307,12 @@ void UpdateCaptureState(const CommonState& commonState,
|
||||
bounds.right,
|
||||
bounds.bottom,
|
||||
textureView.view.width,
|
||||
textureView.view.height);
|
||||
textureView.view.height,
|
||||
px2mmRatio);
|
||||
OutputDebugStringA(buffer);
|
||||
#endif
|
||||
state.Access([&](MeasureToolState& state) {
|
||||
state.perScreen[window].measuredEdges = Measurement{ bounds };
|
||||
state.perScreen[window].measuredEdges = Measurement{ bounds, px2mmRatio };
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@ Settings Settings::LoadFromFile()
|
||||
|
||||
try
|
||||
{
|
||||
result.units = static_cast<Measurement::Unit>(props.GetNamedObject(JSON_KEY_UNITS_OF_MEASURE).GetNamedNumber(JSON_KEY_VALUE));
|
||||
auto index = static_cast<int>(props.GetNamedObject(JSON_KEY_UNITS_OF_MEASURE).GetNamedNumber(JSON_KEY_VALUE));
|
||||
result.units = Measurement::GetUnitFromIndex(index);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,17 @@ struct CommonState
|
||||
|
||||
POINT cursorPosSystemSpace = {}; // updated atomically
|
||||
std::atomic_bool closeOnOtherMonitors = false;
|
||||
|
||||
float GetPhysicalPx2MmRatio(HWND window) const
|
||||
{
|
||||
auto ratio = -1.0f;
|
||||
auto size = MonitorInfo::GetFromWindow(window).GetSize();
|
||||
if (size.width_physical > 0u)
|
||||
{
|
||||
ratio = size.width_mm / static_cast<float>(size.width_physical);
|
||||
}
|
||||
return ratio;
|
||||
}
|
||||
};
|
||||
|
||||
struct CursorDrag
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <initguid.h>
|
||||
#include <windows.h>
|
||||
#include <unknwn.h>
|
||||
#include <Unknwn.h>
|
||||
#include <restrictederrorinfo.h>
|
||||
#include <hstring.h>
|
||||
#include <dxgi.h>
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Shapes.h>
|
||||
#include <winrt/Microsoft.UI.Dispatching.h>
|
||||
#include <winrt/Microsoft.Windows.ApplicationModel.Resources.h>
|
||||
#include <winrt/Windows.Graphics.DirectX.h>
|
||||
#include <winrt/Windows.Graphics.DirectX.Direct3d11.h>
|
||||
#include <winrt/Windows.Graphics.Capture.h>
|
||||
@@ -73,6 +74,7 @@ namespace winrt
|
||||
using namespace Microsoft::UI::Xaml;
|
||||
using namespace Microsoft::UI::Xaml::Controls;
|
||||
using namespace Microsoft::UI::Xaml::Navigation;
|
||||
using namespace Microsoft::Windows::ApplicationModel::Resources;
|
||||
}
|
||||
|
||||
template<typename Func>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:p="using:PowerToys.MeasureToolUI.Properties"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
IsAlwaysOnTop="True"
|
||||
IsMaximizable="False"
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace MeasureToolUI
|
||||
_ = SetWindowLong(hwnd, GWL_STYLE, windowStyle);
|
||||
|
||||
_coreLogic = core;
|
||||
_coreLogic.InitResources();
|
||||
Closed += MainWindow_Closed;
|
||||
DisplayArea displayArea = DisplayArea.GetFromWindowId(windowId, DisplayAreaFallback.Nearest);
|
||||
float dpiScale = _coreLogic.GetDPIScaleForWindow((int)hwnd);
|
||||
|
||||
@@ -66,4 +66,16 @@
|
||||
<data name="BtnClosePanelTooltip.Text" xml:space="preserve">
|
||||
<value>Close (Esc)</value>
|
||||
</data>
|
||||
<data name="MeasurementUnitAbbrPixel" xml:space="preserve">
|
||||
<value>px</value>
|
||||
</data>
|
||||
<data name="MeasurementUnitAbbrInch" xml:space="preserve">
|
||||
<value>in</value>
|
||||
</data>
|
||||
<data name="MeasurementUnitAbbrCentimetre" xml:space="preserve">
|
||||
<value>cm</value>
|
||||
</data>
|
||||
<data name="MeasurementUnitAbbrMillimetre" xml:space="preserve">
|
||||
<value>mm</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -33,6 +33,7 @@ using Timer = System.Windows.Forms.Timer;
|
||||
[module: SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#Dispose(System.Boolean)", MessageId = "logoBitmap", Justification = "Dotnet port with style preservation")]
|
||||
[module: SuppressMessage("Microsoft.Mobility", "CA1601:DoNotUseTimersThatPreventPowerStateChanges", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#frmMatrix_Shown(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
|
||||
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.frmMatrix.#PaintMyLogo()", Justification = "Dotnet port with style preservation")]
|
||||
[module: SuppressMessage("Style", "IDE1006:Naming Styles", Scope = "member", Target = "~M:MouseWithoutBorders.FrmMatrix.M_EnabledChanged(System.Object,System.EventArgs)", Justification = "Dotnet port with style preservation")]
|
||||
|
||||
namespace MouseWithoutBorders
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <wrl.h>
|
||||
#include <wrl/module.h>
|
||||
#include <wrl/client.h>
|
||||
#include <unknwn.h>
|
||||
#include <Unknwn.h>
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
// PowerToys project common
|
||||
|
||||
@@ -215,10 +215,10 @@ namespace newplus::utilities
|
||||
|
||||
inline bool is_desktop_folder(const std::filesystem::path target_fullpath)
|
||||
{
|
||||
TCHAR desktopPath[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, desktopPath)))
|
||||
TCHAR desktop_path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, desktop_path)))
|
||||
{
|
||||
return StrCmpIW(target_fullpath.c_str(), desktopPath) == 0;
|
||||
return StrCmpIW(target_fullpath.c_str(), desktop_path) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -376,8 +376,10 @@ namespace newplus::utilities
|
||||
// Copy file and determine final filename
|
||||
std::filesystem::path target_final_fullpath = template_entry->copy_object_to(GetActiveWindow(), target_fullpath);
|
||||
|
||||
// Consider copy completed. If we do tracing after enter_rename_mode, then rename mode won't consistently work
|
||||
trace.UpdateState(true);
|
||||
Trace::EventCopyTemplate(target_final_fullpath.extension().c_str());
|
||||
Trace::EventCopyTemplateResult(hr);
|
||||
trace.Flush();
|
||||
trace.UpdateState(false);
|
||||
|
||||
@@ -392,13 +394,12 @@ namespace newplus::utilities
|
||||
Logger::error(ex.what());
|
||||
|
||||
hr = S_FALSE;
|
||||
trace.UpdateState(true);
|
||||
Trace::EventCopyTemplateResult(hr);
|
||||
trace.Flush();
|
||||
trace.UpdateState(false);
|
||||
}
|
||||
|
||||
trace.UpdateState(true);
|
||||
Trace::EventCopyTemplateResult(hr);
|
||||
trace.Flush();
|
||||
trace.UpdateState(false);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <atlbase.h>
|
||||
#include <wrl.h>
|
||||
#include <wrl/module.h>
|
||||
#include <unknwn.h>
|
||||
#include <Unknwn.h>
|
||||
|
||||
// PowerToys project common
|
||||
#include <ProjectTelemetry.h>
|
||||
|
||||
23
src/modules/Workspaces/WorkspacesCsharpLibrary/DrawHelper.cs
Normal file
23
src/modules/Workspaces/WorkspacesCsharpLibrary/DrawHelper.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace WorkspacesCsharpLibrary
|
||||
{
|
||||
public class DrawHelper
|
||||
{
|
||||
public static void SaveBitmap(Bitmap bitmap, MemoryStream memory)
|
||||
{
|
||||
ImageCodecInfo imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(codec => codec.FormatID == ImageFormat.Png.Guid);
|
||||
EncoderParameters encoderParameters = new(1);
|
||||
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 50);
|
||||
|
||||
bitmap.Save(memory, imageCodecInfo, encoderParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ namespace WorkspacesCsharpLibrary.Models
|
||||
|
||||
using (var memory = new MemoryStream())
|
||||
{
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
DrawHelper.SaveBitmap(previewBitmap, memory);
|
||||
memory.Position = 0;
|
||||
|
||||
BitmapImage bitmapImage = new BitmapImage();
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="WorkspacesEditor.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
||||
</startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false"/>
|
||||
<AppContextSwitchOverrides value="Switch.System.Windows.DoNotScaleForDpiChanges=false" />
|
||||
</runtime>
|
||||
<userSettings>
|
||||
<WorkspacesEditor.Properties.Settings>
|
||||
<setting name="Top" serializeAs="String">
|
||||
<value>-1</value>
|
||||
</setting>
|
||||
<setting name="Left" serializeAs="String">
|
||||
<value>-1</value>
|
||||
</setting>
|
||||
<setting name="Height" serializeAs="String">
|
||||
<value>-1</value>
|
||||
</setting>
|
||||
<setting name="Width" serializeAs="String">
|
||||
<value>-1</value>
|
||||
</setting>
|
||||
<setting name="Maximized" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
</WorkspacesEditor.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Workspaces.Data;
|
||||
|
||||
using static WorkspacesEditor.Data.ProjectData;
|
||||
|
||||
namespace WorkspacesEditor.Data
|
||||
|
||||
@@ -8,13 +8,7 @@ namespace WorkspacesEditor.Data
|
||||
{
|
||||
public class TempProjectData : ProjectData
|
||||
{
|
||||
public static string File
|
||||
{
|
||||
get
|
||||
{
|
||||
return FolderUtils.DataFolder() + "\\temp-workspaces.json";
|
||||
}
|
||||
}
|
||||
public static string File => FolderUtils.DataFolder() + "\\temp-workspaces.json";
|
||||
|
||||
public static void DeleteTempFile()
|
||||
{
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Workspaces.Data;
|
||||
using WorkspacesEditor.Utils;
|
||||
|
||||
using static WorkspacesEditor.Data.ProjectData;
|
||||
@@ -14,13 +12,7 @@ namespace WorkspacesEditor.Data
|
||||
{
|
||||
public class WorkspacesData : WorkspacesEditorData<WorkspacesListWrapper>
|
||||
{
|
||||
public string File
|
||||
{
|
||||
get
|
||||
{
|
||||
return FolderUtils.DataFolder() + "\\workspaces.json";
|
||||
}
|
||||
}
|
||||
public string File => FolderUtils.DataFolder() + "\\workspaces.json";
|
||||
|
||||
public struct WorkspacesListWrapper
|
||||
{
|
||||
|
||||
@@ -3,28 +3,24 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
using WorkspacesEditor.Utils;
|
||||
|
||||
namespace Workspaces.Data
|
||||
namespace WorkspacesEditor.Data
|
||||
{
|
||||
public class WorkspacesEditorData<T>
|
||||
{
|
||||
protected JsonSerializerOptions JsonOptions
|
||||
{
|
||||
get
|
||||
get => new()
|
||||
{
|
||||
return new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = new DashCaseNamingPolicy(),
|
||||
WriteIndented = true,
|
||||
};
|
||||
}
|
||||
PropertyNamingPolicy = new DashCaseNamingPolicy(),
|
||||
WriteIndented = true,
|
||||
};
|
||||
}
|
||||
|
||||
public T Read(string file)
|
||||
{
|
||||
IOUtils ioUtils = new IOUtils();
|
||||
IOUtils ioUtils = new();
|
||||
string data = ioUtils.ReadFile(file);
|
||||
return JsonSerializer.Deserialize<T>(data, JsonOptions);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
x:Name="WorkspacesMainWindow"
|
||||
Title="{x:Static props:Resources.MainTitle}"
|
||||
MinWidth="700"
|
||||
MinWidth="750"
|
||||
MinHeight="680"
|
||||
ui:TitleBar.Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
ui:TitleBar.InactiveBackground="{DynamicResource TertiaryBackgroundBrush}"
|
||||
|
||||
@@ -30,13 +30,28 @@ namespace WorkspacesEditor
|
||||
MainViewModel = mainViewModel;
|
||||
mainViewModel.SetMainWindow(this);
|
||||
|
||||
WindowInteropHelper windowInteropHelper = new WindowInteropHelper(this);
|
||||
System.Windows.Forms.Screen screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle);
|
||||
double dpi = MonitorHelper.GetScreenDpiFromScreen(screen);
|
||||
this.Height = screen.WorkingArea.Height / dpi * 0.90;
|
||||
this.Width = screen.WorkingArea.Width / dpi * 0.75;
|
||||
this.Top = screen.WorkingArea.Top + (int)(screen.WorkingArea.Height / dpi * 0.05);
|
||||
this.Left = screen.WorkingArea.Left + (int)(screen.WorkingArea.Width / dpi * 0.125);
|
||||
if (Properties.Settings.Default.Height == -1)
|
||||
{
|
||||
// This is the very first time the window is created. Place it on the screen center
|
||||
WindowInteropHelper windowInteropHelper = new WindowInteropHelper(this);
|
||||
System.Windows.Forms.Screen screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle);
|
||||
double dpi = MonitorHelper.GetScreenDpiFromScreen(screen);
|
||||
this.Height = screen.WorkingArea.Height / dpi * 0.90;
|
||||
this.Width = screen.WorkingArea.Width / dpi * 0.75;
|
||||
this.Top = screen.WorkingArea.Top + (int)(screen.WorkingArea.Height / dpi * 0.05);
|
||||
this.Left = screen.WorkingArea.Left + (int)(screen.WorkingArea.Width / dpi * 0.125);
|
||||
SavePosition();
|
||||
}
|
||||
|
||||
this.Top = Properties.Settings.Default.Top;
|
||||
this.Left = Properties.Settings.Default.Left;
|
||||
this.Height = Properties.Settings.Default.Height;
|
||||
this.Width = Properties.Settings.Default.Width;
|
||||
|
||||
if (Properties.Settings.Default.Maximized)
|
||||
{
|
||||
WindowState = WindowState.Maximized;
|
||||
}
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
@@ -73,8 +88,32 @@ namespace WorkspacesEditor
|
||||
cancellationToken.Token);
|
||||
}
|
||||
|
||||
private void SavePosition()
|
||||
{
|
||||
if (WindowState == WindowState.Maximized)
|
||||
{
|
||||
// Use the RestoreBounds as the current values will be 0, 0 and the size of the screen
|
||||
Properties.Settings.Default.Top = RestoreBounds.Top;
|
||||
Properties.Settings.Default.Left = RestoreBounds.Left;
|
||||
Properties.Settings.Default.Height = RestoreBounds.Height;
|
||||
Properties.Settings.Default.Width = RestoreBounds.Width;
|
||||
Properties.Settings.Default.Maximized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Properties.Settings.Default.Top = this.Top;
|
||||
Properties.Settings.Default.Left = this.Left;
|
||||
Properties.Settings.Default.Height = this.Height;
|
||||
Properties.Settings.Default.Width = this.Width;
|
||||
Properties.Settings.Default.Maximized = false;
|
||||
}
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void OnClosing(object sender, EventArgs e)
|
||||
{
|
||||
SavePosition();
|
||||
cancellationToken.Dispose();
|
||||
App.Current.Shutdown();
|
||||
}
|
||||
|
||||
@@ -18,14 +18,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
|
||||
{
|
||||
if (item is MonitorHeaderRow)
|
||||
{
|
||||
return HeaderTemplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AppTemplate;
|
||||
}
|
||||
return item is MonitorHeaderRow ? HeaderTemplate : AppTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +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.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ManagedCommon;
|
||||
using Windows.Management.Deployment;
|
||||
using WorkspacesCsharpLibrary;
|
||||
using WorkspacesCsharpLibrary.Models;
|
||||
|
||||
namespace WorkspacesEditor.Models
|
||||
{
|
||||
public enum WindowPositionKind
|
||||
{
|
||||
Custom = 0,
|
||||
Maximized = 1,
|
||||
Minimized = 2,
|
||||
}
|
||||
|
||||
public class Application : BaseApplication, IDisposable
|
||||
{
|
||||
private bool _isInitialized;
|
||||
@@ -79,7 +76,7 @@ namespace WorkspacesEditor.Models
|
||||
return left.X != right.X || left.Y != right.Y || left.Width != right.Width || left.Height != right.Height;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override readonly bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || GetType() != obj.GetType())
|
||||
{
|
||||
@@ -90,7 +87,7 @@ namespace WorkspacesEditor.Models
|
||||
return X == pos.X && Y == pos.Y && Width == pos.Width && Height == pos.Height;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
public override readonly int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
@@ -136,36 +133,24 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
private bool _minimized;
|
||||
public bool Minimized { get; set; }
|
||||
|
||||
public bool Minimized
|
||||
public bool Maximized { get; set; }
|
||||
|
||||
public bool EditPositionEnabled => !Minimized && !Maximized;
|
||||
|
||||
public int PositionComboboxIndex
|
||||
{
|
||||
get => _minimized;
|
||||
get => Maximized ? (int)WindowPositionKind.Maximized : Minimized ? (int)WindowPositionKind.Minimized : (int)WindowPositionKind.Custom;
|
||||
set
|
||||
{
|
||||
_minimized = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Minimized)));
|
||||
Maximized = value == (int)WindowPositionKind.Maximized;
|
||||
Minimized = value == (int)WindowPositionKind.Minimized;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(EditPositionEnabled)));
|
||||
RedrawPreviewImage();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _maximized;
|
||||
|
||||
public bool Maximized
|
||||
{
|
||||
get => _maximized;
|
||||
set
|
||||
{
|
||||
_maximized = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Maximized)));
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(EditPositionEnabled)));
|
||||
RedrawPreviewImage();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EditPositionEnabled { get => !Minimized && !Maximized; }
|
||||
|
||||
private string _appMainParams;
|
||||
|
||||
public string AppMainParams
|
||||
@@ -183,7 +168,7 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsAppMainParamVisible { get => !string.IsNullOrWhiteSpace(_appMainParams); }
|
||||
public bool IsAppMainParamVisible => !string.IsNullOrWhiteSpace(_appMainParams);
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsHighlighted { get; set; }
|
||||
@@ -192,13 +177,7 @@ namespace WorkspacesEditor.Models
|
||||
public int RepeatIndex { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string RepeatIndexString
|
||||
{
|
||||
get
|
||||
{
|
||||
return RepeatIndex <= 1 ? string.Empty : RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
public string RepeatIndexString => RepeatIndex <= 1 ? string.Empty : RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
private WindowPosition _position;
|
||||
|
||||
@@ -242,10 +221,7 @@ namespace WorkspacesEditor.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_monitorSetup == null)
|
||||
{
|
||||
_monitorSetup = Parent.GetMonitorForApp(this);
|
||||
}
|
||||
_monitorSetup ??= Parent.GetMonitorForApp(this);
|
||||
|
||||
return _monitorSetup;
|
||||
}
|
||||
@@ -271,7 +247,7 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
public string DeleteButtonContent { get => _isIncluded ? Properties.Resources.Delete : Properties.Resources.AddBack; }
|
||||
public string DeleteButtonContent => _isIncluded ? Properties.Resources.Delete : Properties.Resources.AddBack;
|
||||
|
||||
private bool _isIncluded = true;
|
||||
|
||||
@@ -298,15 +274,5 @@ namespace WorkspacesEditor.Models
|
||||
CommandLineArguments = newCommandLineValue;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(AppMainParams)));
|
||||
}
|
||||
|
||||
internal void MaximizedChecked()
|
||||
{
|
||||
Minimized = false;
|
||||
}
|
||||
|
||||
internal void MinimizedChecked()
|
||||
{
|
||||
Maximized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,28 +6,18 @@ using System.Windows;
|
||||
|
||||
namespace WorkspacesEditor.Models
|
||||
{
|
||||
public class Monitor
|
||||
public class Monitor(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
{
|
||||
public string MonitorName { get; private set; }
|
||||
public string MonitorName { get; private set; } = monitorName;
|
||||
|
||||
public string MonitorInstanceId { get; private set; }
|
||||
public string MonitorInstanceId { get; private set; } = monitorInstanceId;
|
||||
|
||||
public int MonitorNumber { get; private set; }
|
||||
public int MonitorNumber { get; private set; } = number;
|
||||
|
||||
public int Dpi { get; private set; }
|
||||
public int Dpi { get; private set; } = dpi;
|
||||
|
||||
public Rect MonitorDpiUnawareBounds { get; private set; }
|
||||
public Rect MonitorDpiUnawareBounds { get; private set; } = dpiUnawareBounds;
|
||||
|
||||
public Rect MonitorDpiAwareBounds { get; private set; }
|
||||
|
||||
public Monitor(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
{
|
||||
MonitorName = monitorName;
|
||||
MonitorInstanceId = monitorInstanceId;
|
||||
MonitorNumber = number;
|
||||
Dpi = dpi;
|
||||
MonitorDpiAwareBounds = dpiAwareBounds;
|
||||
MonitorDpiUnawareBounds = dpiUnawareBounds;
|
||||
}
|
||||
public Rect MonitorDpiAwareBounds { get; private set; } = dpiAwareBounds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace WorkspacesEditor.Models
|
||||
PropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public string MonitorInfo { get => MonitorName; }
|
||||
public string MonitorInfo => MonitorName;
|
||||
|
||||
public string MonitorInfoWithResolution { get => $"{MonitorName} {MonitorDpiAwareBounds.Width}x{MonitorDpiAwareBounds.Height}"; }
|
||||
public string MonitorInfoWithResolution => $"{MonitorName} {MonitorDpiAwareBounds.Width}x{MonitorDpiAwareBounds.Height}";
|
||||
|
||||
public MonitorSetup(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
: base(monitorName, monitorInstanceId, number, dpi, dpiAwareBounds, dpiUnawareBounds)
|
||||
|
||||
@@ -29,10 +29,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
get => _name;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -68,8 +65,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
DateTime lastLaunchDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(LastLaunchedTime);
|
||||
|
||||
var now = DateTime.UtcNow.Ticks;
|
||||
var ts = DateTime.UtcNow - lastLaunchDateTime;
|
||||
TimeSpan ts = DateTime.UtcNow - lastLaunchDateTime;
|
||||
double delta = Math.Abs(ts.TotalSeconds);
|
||||
|
||||
if (delta < 1 * MINUTE)
|
||||
@@ -120,10 +116,7 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeSaved
|
||||
{
|
||||
get => Name.Length > 0 && Applications.Count > 0;
|
||||
}
|
||||
public bool CanBeSaved => Name.Length > 0 && Applications.Count > 0;
|
||||
|
||||
private bool _isRevertEnabled;
|
||||
|
||||
@@ -145,10 +138,7 @@ namespace WorkspacesEditor.Models
|
||||
[JsonIgnore]
|
||||
public bool IsPopupVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isPopupVisible;
|
||||
}
|
||||
get => _isPopupVisible;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -163,11 +153,11 @@ namespace WorkspacesEditor.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
List<object> applicationsListed = new List<object>();
|
||||
List<object> applicationsListed = [];
|
||||
ILookup<MonitorSetup, Application> apps = Applications.Where(x => !x.Minimized).ToLookup(x => x.MonitorSetup);
|
||||
foreach (var appItem in apps.OrderBy(x => x.Key.MonitorDpiUnawareBounds.Left).ThenBy(x => x.Key.MonitorDpiUnawareBounds.Top))
|
||||
foreach (IGrouping<MonitorSetup, Application> appItem in apps.OrderBy(x => x.Key.MonitorDpiUnawareBounds.Left).ThenBy(x => x.Key.MonitorDpiUnawareBounds.Top))
|
||||
{
|
||||
MonitorHeaderRow headerRow = new MonitorHeaderRow { MonitorName = "Screen " + appItem.Key.MonitorNumber, SelectString = Properties.Resources.SelectAllAppsOnMonitor + " " + appItem.Key.MonitorInfo };
|
||||
MonitorHeaderRow headerRow = new() { MonitorName = "Screen " + appItem.Key.MonitorNumber, SelectString = Properties.Resources.SelectAllAppsOnMonitor + " " + appItem.Key.MonitorInfo };
|
||||
applicationsListed.Add(headerRow);
|
||||
foreach (Application app in appItem)
|
||||
{
|
||||
@@ -175,10 +165,10 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
var minimizedApps = Applications.Where(x => x.Minimized);
|
||||
IEnumerable<Application> minimizedApps = Applications.Where(x => x.Minimized);
|
||||
if (minimizedApps.Any())
|
||||
{
|
||||
MonitorHeaderRow headerRow = new MonitorHeaderRow { MonitorName = Properties.Resources.Minimized_Apps, SelectString = Properties.Resources.SelectAllMinimizedApps };
|
||||
MonitorHeaderRow headerRow = new() { MonitorName = Properties.Resources.Minimized_Apps, SelectString = Properties.Resources.SelectAllMinimizedApps };
|
||||
applicationsListed.Add(headerRow);
|
||||
foreach (Application app in minimizedApps)
|
||||
{
|
||||
@@ -219,17 +209,17 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
int screenIndex = 1;
|
||||
|
||||
Monitors = new List<MonitorSetup>();
|
||||
foreach (var item in selectedProject.Monitors.OrderBy(x => x.MonitorDpiAwareBounds.Left).ThenBy(x => x.MonitorDpiAwareBounds.Top))
|
||||
Monitors = [];
|
||||
foreach (MonitorSetup item in selectedProject.Monitors.OrderBy(x => x.MonitorDpiAwareBounds.Left).ThenBy(x => x.MonitorDpiAwareBounds.Top))
|
||||
{
|
||||
Monitors.Add(item);
|
||||
screenIndex++;
|
||||
}
|
||||
|
||||
Applications = new List<Application>();
|
||||
foreach (var item in selectedProject.Applications)
|
||||
Applications = [];
|
||||
foreach (Application item in selectedProject.Applications)
|
||||
{
|
||||
Application newApp = new Application(item);
|
||||
Application newApp = new(item);
|
||||
newApp.Parent = this;
|
||||
newApp.InitializationFinished();
|
||||
Applications.Add(newApp);
|
||||
@@ -244,14 +234,14 @@ namespace WorkspacesEditor.Models
|
||||
LastLaunchedTime = project.LastLaunchedTime;
|
||||
IsShortcutNeeded = project.IsShortcutNeeded;
|
||||
MoveExistingWindows = project.MoveExistingWindows;
|
||||
Monitors = new List<MonitorSetup>() { };
|
||||
Applications = new List<Models.Application> { };
|
||||
Monitors = [];
|
||||
Applications = [];
|
||||
|
||||
foreach (var app in project.Applications)
|
||||
foreach (ProjectData.ApplicationWrapper app in project.Applications)
|
||||
{
|
||||
Models.Application newApp = new Models.Application()
|
||||
Models.Application newApp = new()
|
||||
{
|
||||
Id = string.IsNullOrEmpty(app.Id) ? $"{{{Guid.NewGuid().ToString()}}}" : app.Id,
|
||||
Id = string.IsNullOrEmpty(app.Id) ? $"{{{Guid.NewGuid()}}}" : app.Id,
|
||||
AppName = app.Application,
|
||||
AppPath = app.ApplicationPath,
|
||||
AppTitle = app.Title,
|
||||
@@ -278,20 +268,17 @@ namespace WorkspacesEditor.Models
|
||||
Applications.Add(newApp);
|
||||
}
|
||||
|
||||
foreach (var monitor in project.MonitorConfiguration)
|
||||
foreach (ProjectData.MonitorConfigurationWrapper monitor in project.MonitorConfiguration)
|
||||
{
|
||||
System.Windows.Rect dpiAware = new System.Windows.Rect(monitor.MonitorRectDpiAware.Left, monitor.MonitorRectDpiAware.Top, monitor.MonitorRectDpiAware.Width, monitor.MonitorRectDpiAware.Height);
|
||||
System.Windows.Rect dpiUnaware = new System.Windows.Rect(monitor.MonitorRectDpiUnaware.Left, monitor.MonitorRectDpiUnaware.Top, monitor.MonitorRectDpiUnaware.Width, monitor.MonitorRectDpiUnaware.Height);
|
||||
System.Windows.Rect dpiAware = new(monitor.MonitorRectDpiAware.Left, monitor.MonitorRectDpiAware.Top, monitor.MonitorRectDpiAware.Width, monitor.MonitorRectDpiAware.Height);
|
||||
System.Windows.Rect dpiUnaware = new(monitor.MonitorRectDpiUnaware.Left, monitor.MonitorRectDpiUnaware.Top, monitor.MonitorRectDpiUnaware.Width, monitor.MonitorRectDpiUnaware.Height);
|
||||
Monitors.Add(new MonitorSetup(monitor.Id, monitor.InstanceId, monitor.MonitorNumber, monitor.Dpi, dpiAware, dpiUnaware));
|
||||
}
|
||||
}
|
||||
|
||||
public BitmapImage PreviewIcons
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewIcons;
|
||||
}
|
||||
get => _previewIcons;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -302,10 +289,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public BitmapImage PreviewImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewImage;
|
||||
}
|
||||
get => _previewImage;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -316,10 +300,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public double PreviewImageWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewImageWidth;
|
||||
}
|
||||
get => _previewImageWidth;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -366,6 +347,7 @@ namespace WorkspacesEditor.Models
|
||||
Id = other.Id;
|
||||
Name = other.Name;
|
||||
IsRevertEnabled = true;
|
||||
MoveExistingWindows = other.MoveExistingWindows;
|
||||
}
|
||||
|
||||
internal void CloseExpanders()
|
||||
@@ -378,13 +360,13 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
internal MonitorSetup GetMonitorForApp(Application app)
|
||||
{
|
||||
var monitorSetup = Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault();
|
||||
MonitorSetup monitorSetup = Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault();
|
||||
if (monitorSetup == null)
|
||||
{
|
||||
// monitors changed: try to determine monitor id based on middle point
|
||||
int middleX = app.Position.X + (app.Position.Width / 2);
|
||||
int middleY = app.Position.Y + (app.Position.Height / 2);
|
||||
var monitorCandidate = Monitors.Where(x =>
|
||||
MonitorSetup monitorCandidate = Monitors.Where(x =>
|
||||
(x.MonitorDpiUnawareBounds.Left < middleX) &&
|
||||
(x.MonitorDpiUnawareBounds.Right > middleX) &&
|
||||
(x.MonitorDpiUnawareBounds.Top < middleY) &&
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Add Back.
|
||||
/// Looks up a localized string similar to Add back.
|
||||
/// </summary>
|
||||
public static string AddBack {
|
||||
get {
|
||||
@@ -78,15 +78,6 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Launch new app instances.
|
||||
/// </summary>
|
||||
public static string AlwaysLaunch {
|
||||
get {
|
||||
return ResourceManager.GetString("AlwaysLaunch", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to app.
|
||||
/// </summary>
|
||||
@@ -169,7 +160,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create Desktop Shortcut.
|
||||
/// Looks up a localized string similar to Create desktop shortcut.
|
||||
/// </summary>
|
||||
public static string CreateShortcut {
|
||||
get {
|
||||
@@ -186,6 +177,15 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom.
|
||||
/// </summary>
|
||||
public static string Custom {
|
||||
get {
|
||||
return ResourceManager.GetString("Custom", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to days ago.
|
||||
/// </summary>
|
||||
@@ -223,7 +223,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove Selected Apps.
|
||||
/// Looks up a localized string similar to Remove selected apps.
|
||||
/// </summary>
|
||||
public static string DeleteSelected {
|
||||
get {
|
||||
@@ -322,7 +322,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Launch & Edit.
|
||||
/// Looks up a localized string similar to Launch & edit.
|
||||
/// </summary>
|
||||
public static string LaunchEdit {
|
||||
get {
|
||||
@@ -367,7 +367,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Minimized Apps.
|
||||
/// Looks up a localized string similar to Minimized apps.
|
||||
/// </summary>
|
||||
public static string Minimized_Apps {
|
||||
get {
|
||||
@@ -394,7 +394,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Move apps if present.
|
||||
/// Looks up a localized string similar to Move existing windows.
|
||||
/// </summary>
|
||||
public static string MoveIfExist {
|
||||
get {
|
||||
@@ -502,7 +502,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Pin Workspaces to Taskbar.
|
||||
/// Looks up a localized string similar to Pin Workspaces to taskbar.
|
||||
/// </summary>
|
||||
public static string PinToTaskbar {
|
||||
get {
|
||||
@@ -565,7 +565,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select All Apps on.
|
||||
/// Looks up a localized string similar to Select all apps on.
|
||||
/// </summary>
|
||||
public static string SelectAllAppsOnMonitor {
|
||||
get {
|
||||
@@ -574,7 +574,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select All Minimized Apps.
|
||||
/// Looks up a localized string similar to Select all minimized apps.
|
||||
/// </summary>
|
||||
public static string SelectAllMinimizedApps {
|
||||
get {
|
||||
@@ -583,7 +583,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select All Apps in Workspace.
|
||||
/// Looks up a localized string similar to Select all apps in Workspace.
|
||||
/// </summary>
|
||||
public static string SelectedAllInWorkspace {
|
||||
get {
|
||||
@@ -645,6 +645,15 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Window position.
|
||||
/// </summary>
|
||||
public static string WindowPosition {
|
||||
get {
|
||||
return ResourceManager.GetString("WindowPosition", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Workspace name.
|
||||
/// </summary>
|
||||
|
||||
@@ -123,9 +123,6 @@
|
||||
<data name="Admin" xml:space="preserve">
|
||||
<value>Admin</value>
|
||||
</data>
|
||||
<data name="AlwaysLaunch" xml:space="preserve">
|
||||
<value>Launch new app instances</value>
|
||||
</data>
|
||||
<data name="App" xml:space="preserve">
|
||||
<value>app</value>
|
||||
</data>
|
||||
@@ -160,6 +157,9 @@
|
||||
<data name="CreateShortcut" xml:space="preserve">
|
||||
<value>Create desktop shortcut</value>
|
||||
</data>
|
||||
<data name="Custom" xml:space="preserve">
|
||||
<value>Custom</value>
|
||||
</data>
|
||||
<data name="DaysAgo" xml:space="preserve">
|
||||
<value>days ago</value>
|
||||
</data>
|
||||
@@ -231,7 +231,7 @@
|
||||
<value>months ago</value>
|
||||
</data>
|
||||
<data name="MoveIfExist" xml:space="preserve">
|
||||
<value>Move apps if present</value>
|
||||
<value>Move existing windows</value>
|
||||
</data>
|
||||
<data name="Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
@@ -321,6 +321,9 @@
|
||||
<data name="Width" xml:space="preserve">
|
||||
<value>Width</value>
|
||||
</data>
|
||||
<data name="WindowPosition" xml:space="preserve">
|
||||
<value>Window position</value>
|
||||
</data>
|
||||
<data name="WriteArgs" xml:space="preserve">
|
||||
<value>Write arguments here</value>
|
||||
</data>
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace WorkspacesEditor.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -22,5 +22,65 @@ namespace WorkspacesEditor.Properties {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("-1")]
|
||||
public double Top {
|
||||
get {
|
||||
return ((double)(this["Top"]));
|
||||
}
|
||||
set {
|
||||
this["Top"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("-1")]
|
||||
public double Left {
|
||||
get {
|
||||
return ((double)(this["Left"]));
|
||||
}
|
||||
set {
|
||||
this["Left"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("-1")]
|
||||
public double Height {
|
||||
get {
|
||||
return ((double)(this["Height"]));
|
||||
}
|
||||
set {
|
||||
this["Height"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("-1")]
|
||||
public double Width {
|
||||
get {
|
||||
return ((double)(this["Width"]));
|
||||
}
|
||||
set {
|
||||
this["Width"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool Maximized {
|
||||
get {
|
||||
return ((bool)(this["Maximized"]));
|
||||
}
|
||||
set {
|
||||
this["Maximized"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user