Upgrade to check-spelling v0.0.24 (#36235)

This upgrades to [v0.0.24](https://github.com/check-spelling/check-spelling/releases/tag/v0.0.24).

A number of GitHub APIs are being turned off shortly, so you need to upgrade or various uncertain outcomes will occur.

There's a new accessibility forbidden pattern:

> 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
```pl
(?i)(?:>|\[)(?:(?:click |)here|link|(?:read |)more)(?:</|\]\()
```

There are some minor bugs that I'm aware of and which I've fixed since this release, but I don't expect to make another release this month.

I've added a pair of patterns for includes and pragmas. My argument is that the **compiler** will _generally_ tell you if you've misspelled an include and the **linker** will _generally_ tell you if you misspell a lib.

- There's a caveat here: If your include case-insensitively matches the referenced file (but doesn't properly match it), then unless you either use a case-sensitive file system (as opposed to case-preserving) or beg clang to warn, you won't notice when you make this specific mistake -- this matters in that a couple of Windows headers (e.g. Unknwn.h) have particular case and repositories don't tend to consistently/properly write them.
This commit is contained in:
Josh Soref 2024-12-06 06:33:08 -10:00 коммит произвёл GitHub
Родитель 1212ce2216
Коммит 74a1a6eca2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
84 изменённых файлов: 797 добавлений и 529 удалений

15
.github/actions/spell-check/allow/code.txt поставляемый
Просмотреть файл

@ -21,6 +21,9 @@ Pbgra
WHITEONBLACK WHITEONBLACK
# COUNTRIES
RUS
# FILES # FILES
AYUV AYUV
@ -128,6 +131,9 @@ XBUTTONDOWN
XBUTTONUP XBUTTONUP
XDOWN XDOWN
# Prefix
pcs
# User32.SYSTEM_METRICS_INDEX.cs # User32.SYSTEM_METRICS_INDEX.cs
CLEANBOOT CLEANBOOT
@ -220,12 +226,21 @@ TABLETPC
artanh artanh
arsinh arsinh
arcosh arcosh
roundf
# Linux # Linux
dbus dbus
anypass anypass
github
gpg gpg
https
ssh
ubuntu
workarounds
# For upgrade to check-spelling v0.0.24
pwa
# .NET # .NET

184
.github/actions/spell-check/candidate.patterns поставляемый
Просмотреть файл

@ -1,3 +1,6 @@
# D2D
#D?2D
# marker to ignore all code on line # marker to ignore all code on line
^.*/\* #no-spell-check-line \*/.*$ ^.*/\* #no-spell-check-line \*/.*$
# marker to ignore all code on 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 ^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b
# patch hunk comments # patch hunk comments
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .* ^@@ -\d+(?:,\d+|) \+\d+(?:,\d+|) @@ .*
# git index header # git index header
index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40} 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 url in quotes
([`'"])data:(?:[^ `'"].*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1} ([`'"])data:(?:[^ `'"].*?|)(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
# data url # data url
data:[-a-zA-Z=;:/0-9+]*,\S* \bdata:[-a-zA-Z=;:/0-9+]*,\S*
# https/http/file urls # 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 urls
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,} #mailto:[-a-zA-Z=;:/?%&0-9+@._]{3,}
# magnet urls # magnet urls
magnet:[?=:\w]+ magnet:[?=:\w]+
@ -152,6 +155,9 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
# GHSA # GHSA
GHSA(?:-[0-9a-z]{4}){3} GHSA(?:-[0-9a-z]{4}){3}
# GitHub actions
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
# GitLab commit # GitLab commit
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b \bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
# GitLab merge requests # GitLab merge requests
@ -210,7 +216,7 @@ accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
# medium link # medium link
\blink\.medium\.com/[a-zA-Z0-9]+ \blink\.medium\.com/[a-zA-Z0-9]+
# medium # medium
\bmedium\.com/\@?[^/\s"]+/[-\w]+ \bmedium\.com/@?[^/\s"]+/[-\w]+
# microsoft # microsoft
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]* \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 [0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
# Twitter markdown # Twitter markdown
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\) \[@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
# Twitter hashtag # Twitter hashtag
\btwitter\.com/hashtag/[\w?_=&]* \btwitter\.com/hashtag/[\w?_=&]*
# Twitter status # Twitter status
@ -330,7 +336,7 @@ ipfs://[0-9a-zA-Z]{3,}
[^"\s]+/gitweb/\S+;h=[0-9a-f]+ [^"\s]+/gitweb/\S+;h=[0-9a-f]+
# HyperKitty lists # HyperKitty lists
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/ /archives/list/[^@/]+@[^/\s"]*/message/[^/\s"]*/
# lists # lists
/thread\.html/[^"\s]+ /thread\.html/[^"\s]+
@ -348,7 +354,7 @@ ipfs://[0-9a-zA-Z]{3,}
\bopen\.spotify\.com/embed/playlist/\w+ \bopen\.spotify\.com/embed/playlist/\w+
# Mastodon # Mastodon
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]* \bmastodon\.[-a-z.]*/(?:media/|@)[?&=0-9a-zA-Z_]*
# scastie # scastie
\bscastie\.scala-lang\.org/[^/]+/\w+ \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 (?:\\(?:u00|x)1[Bb]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+|)m
# URL escaped characters # URL escaped characters
\%[0-9A-F][A-F] %[0-9A-F][A-F](?=[A-Za-z])
# lower URL escaped characters # lower URL escaped characters
\%[0-9a-f][a-f](?=[a-z]{2,}) %[0-9a-f][a-f](?=[a-z]{2,})
# IPv6 # IPv6
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b \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) # c99 hex digits (not the full format, just one I've seen)
@ -400,7 +406,7 @@ ipfs://[0-9a-zA-Z]{3,}
# Punycode # Punycode
\bxn--[-0-9a-z]+ \bxn--[-0-9a-z]+
# sha # 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 # sha-... -- uses a fancy capture
(\\?['"]|&quot;)[0-9a-f]{40,}\g{-1} (\\?['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hex runs # hex runs
@ -420,10 +426,13 @@ sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
# pki # pki
-----BEGIN.*-----END -----BEGIN.*-----END
# pki (base64)
LS0tLS1CRUdJT.*
# uuid: # uuid:
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b \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: # 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
integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1} 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\[[^\]]+\]=.* Name\[[^\]]+\]=.*
# IServiceProvider / isAThing # 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 # crypt
(['"])\$2[ayb]\$.{56}\g{-1} (['"])\$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
\$(?:scrypt|argon\d+[di]*)\$\S+ \$(?:scrypt|argon\d+[di]*)\$\S+
# go.sum # go.sum
\bh1:\S+ \bh1:\S+
# scala imports
^import (?:[\w.]|\{\w*?(?:,\s*(?:\w*|\*))+\})+
# scala modules # scala modules
#("[^"]+"\s*%%?\s*){2,3}"[^"]+" #("[^"]+"\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 # Input to GitHub JSON
content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1} 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. # you'll want to remove the `(?=.*?")` suffix.
# The `(?=.*?")` suffix should limit the false positives rate # The `(?=.*?")` suffix should limit the false positives rate
# printf # 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 # 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 # 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 # Regular expressions for (P|p)assword
\([A-Z]\|[a-z]\)[a-z]+ \([A-Z]\|[a-z]\)[a-z]+
# JavaScript regular expressions # JavaScript regular expressions
# javascript test regex # javascript test regex
/.*/[gim]*\.test\( /.{3,}/[gim]*\.test\(
# javascript match regex # javascript match regex
\.match\(/[^/\s"]*/[gim]*\s* \.match\(/[^/\s"]{3,}/[gim]*\s*
# javascript match regex # javascript match regex
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$) \.match\(/\\[b].{3,}?/[gim]*\s*\)(?:;|$)
# javascript regex # javascript regex
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$) ^\s*/\\[b].{3,}?/[gim]*\s*(?:\)(?:;|$)|,$)
# javascript replace regex # javascript replace regex
\.replace\(/[^/\s"]*/[gim]*\s*, \.replace\(/[^/\s"]{3,}/[gim]*\s*,
# assign regex # 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 # perl regex test
[!=]~ (?:/.*/|m\{.*?\}|m<.*?>|m([|!/@#,;']).*?\g{-1}) [!=]~ (?:/.*/|m\{.*?\}|m<.*?>|m([|!/@#,;']).*?\g{-1})
# perl qr regex # perl qr regex
(?<!\$)\bqr(?:\{.*?\}|<.*?>|\(.*?\)|([|!/@#,;']).*?\g{-1}) (?<!\$)\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 # Go regular expressions
regexp?\.MustCompile\(`[^`]*`\) regexp?\.MustCompile\(`[^`]*`\)
@ -503,14 +549,20 @@ regexp?\.MustCompile\(`[^`]*`\)
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2} sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
# node packages # node packages
(["'])\@[^/'" ]+/[^/'" ]+\g{-1} (["'])@[^/'" ]+/[^/'" ]+\g{-1}
# go install # go install
go install(?:\s+[a-z]+\.[-@\w/.]+)+ go install(?:\s+[a-z]+\.[-@\w/.]+)+
# pom.xml
<(?:group|artifact)Id>.*?<
# jetbrains schema https://youtrack.jetbrains.com/issue/RSRP-489571 # jetbrains schema https://youtrack.jetbrains.com/issue/RSRP-489571
urn:shemas-jetbrains-com urn:shemas-jetbrains-com
# Debian changelog severity
[-\w]+ \(.*\) (?:\w+|baseline|unstable|experimental); urgency=(?:low|medium|high|emergency|critical)\b
# kubernetes pod status lists # kubernetes pod status lists
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase # https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+ \w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
@ -518,9 +570,15 @@ urn:shemas-jetbrains-com
# kubectl - pods in CrashLoopBackOff # kubectl - pods in CrashLoopBackOff
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+ \w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
# kubernetes applications
\.apps/[-\w]+
# kubernetes object suffix # kubernetes object suffix
-[0-9a-f]{10}-\w{5}\s -[0-9a-f]{10}-\w{5}\s
# kubernetes crd patterns
^\s*pattern: .*$
# posthog secrets # posthog secrets
([`'"])phc_[^"',]+\g{-1} ([`'"])phc_[^"',]+\g{-1}
@ -532,6 +590,9 @@ urn:shemas-jetbrains-com
# xcode api botches # xcode api botches
customObjectInstantitationMethod customObjectInstantitationMethod
# msvc api botches
PrependWithABINamepsace
# configure flags # configure flags
.* \| --\w{2,}.*?(?=\w+\s\w+) .* \| --\w{2,}.*?(?=\w+\s\w+)
@ -539,21 +600,34 @@ customObjectInstantitationMethod
\.fa-[-a-z0-9]+ \.fa-[-a-z0-9]+
# bearer auth # 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 auth
(['"])Basic [-a-zA-Z=;:/0-9+]{3,}\g{-1} (['"])[Bb]asic [-a-zA-Z=;:/0-9+]{3,}\g{-1}
# base64 encoded content # base64 encoded content
([`'"])[-a-zA-Z=;:/0-9+]+=\g{-1} #([`'"])[-a-zA-Z=;:/0-9+]{3,}=\g{-1}
# base64 encoded content in xml/sgml # base64 encoded content in xml/sgml
>[-a-zA-Z=;:/0-9+]+=</ >[-a-zA-Z=;:/0-9+]{3,}=</
# base64 encoded content, possibly wrapped in mime # base64 encoded content, possibly wrapped in mime
(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$) (?:^|[\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 # encoded-word
=\?[-a-zA-Z0-9"*%]+\?[BQ]\?[^?]{0,75}\?= =\?[-a-zA-Z0-9"*%]+\?[BQ]\?[^?]{0,75}\?=
# numerator
\bnumer\b(?=.*denom)
# Time Zones # Time Zones
\b(?:Africa|Atlantic|America|Antarctica|Asia|Australia|Europe|Indian|Pacific)(?:/\w+)+ \b(?:Africa|Atlantic|America|Antarctica|Asia|Australia|Europe|Indian|Pacific)(?:/\w+)+
@ -563,16 +637,22 @@ customObjectInstantitationMethod
# systemd mode # systemd mode
systemd.*?running in system 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 ) # 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 - # 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: # 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). # ... 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]...` # ... 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) # ... 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|[,.])*)
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
# Non-English # 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,} [a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
# highlighted letters # highlighted letters
@ -585,27 +665,48 @@ systemd.*?running in system mode \([-+].*\)$
# latex (check-spelling >= 0.0.22) # latex (check-spelling >= 0.0.22)
\\\w{2,}\{ \\\w{2,}\{
# American Mathematical Society (AMS) / Doxygen
TeX/AMS
# File extensions
\*\.[+\w]+,
# eslint # eslint
"varsIgnorePattern": ".+" "varsIgnorePattern": ".+"
# nolint
nolint:\w+
# Windows short paths # 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 # in check-spelling@v0.0.22+, printf markers aren't automatically consumed
# printf markers # printf markers
#(?<!\\)\\[nrt](?=[a-z]{2,}) #(?<!\\)\\[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,})(?=.*['"`]) #(?<!\\)\\[nrt](?=[a-z]{2,})(?=.*['"`])
# Markdown anchor links
\(#\S*?[a-zA-Z]\S*?\)
# apache # apache
a2(?:en|dis) a2(?:en|dis)
# weak e-tag # weak e-tag
W/"[^"]+" W/"[^"]+"
# authors/credits
^\*(?: [A-Z](?:\w+|\.)){2,} (?=\[|$)
# the negative lookahead here is to allow catching 'templatesz' as a misspelling # 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: # 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: # ignore long runs of a single character:
\b([A-Za-z])\g{-1}{3,}\b \b([A-Za-z])\g{-1}{3,}\b
@ -624,13 +725,24 @@ W/"[^"]+"
# Compiler flags (linker) # Compiler flags (linker)
,-B ,-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 # 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 # 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 # tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+ \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... # 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 \btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
# macOS temp folders # macOS temp folders
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/ /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 поставляемый
Просмотреть файл

@ -1,23 +1,19 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes # See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
(?:^|/)(?i)COPYRIGHT (?:^|/)(?i)COPYRIGHT
(?:^|/)(?i)LICEN[CS]E (?:^|/)(?i)LICEN[CS]E
(?:^|/)(?i)third[-_]?party/
(?:^|/)3rdparty/ (?:^|/)3rdparty/
(?:^|/)src/Monaco/customLanguages/ (?:^|/)generated/
(?:^|/)src/Monaco/generateLanguagesJson.html
(?:^|/)src/Monaco/index.html
(?:^|/)src/Monaco/monaco_languages.json
(?:^|/)src/Monaco/monacoSpecialLanguages.js
(?:^|/)go\.sum$ (?:^|/)go\.sum$
(?:^|/)monacoSRC/
(?:^|/)package(?:-lock|)\.json$ (?:^|/)package(?:-lock|)\.json$
(?:^|/)Pipfile$ (?:^|/)Pipfile$
(?:^|/)power-rename-ui-flags$ (?:^|/)power-rename-ui-flags$
(?:^|/)pyproject.toml (?:^|/)pyproject.toml
(?:^|/)requirements(?:-dev|-doc|-test|)\.txt$
(?:^|/)sample\.qoi$ (?:^|/)sample\.qoi$
(?:^|/)timezones\.json$
(?:^|/)vendor/ (?:^|/)vendor/
(?:^|/)WindowsSettings\.json$ (?:^|/)WindowsSettings\.json$
(?:^|/|\b)requirements(?:-dev|-doc|-test|)\.txt$
(?:|$^ 92.31% - excluded 12/13)/editor/[^/]+$
/images/launcher/[^/]+$ /images/launcher/[^/]+$
/TestFiles/ /TestFiles/
[^/]\.gcode$ [^/]\.gcode$
@ -28,11 +24,10 @@
\.avi$ \.avi$
\.bmp$ \.bmp$
\.bz2$ \.bz2$
\.cer$ \.cert?$|\.crt$
\.class$ \.class$
\.coveragerc$ \.coveragerc$
\.crl$ \.crl$
\.crt$
\.csr$ \.csr$
\.dll$ \.dll$
\.docx?$ \.docx?$
@ -97,19 +92,19 @@
^\.gitmodules$ ^\.gitmodules$
^\Q.github/workflows/spelling2.yml\E$ ^\Q.github/workflows/spelling2.yml\E$
^\Q.pipelines/ESRPSigning_core.json\E$ ^\Q.pipelines/ESRPSigning_core.json\E$
^\Q.pipelines/sdl.gdnbaselines\E$ ^\Qdoc/devdocs/localization.md\E$
^\Qinstaller/PowerToysSetup/Settings.wxs\E$
^\Qsrc/Monaco/monaco_languages.json\E$
^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$ ^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$
^\Qsrc/common/notifications/BackgroundActivatorDLL/cpp.hint\E$ ^\Qsrc/common/notifications/BackgroundActivatorDLL/cpp.hint\E$
^\Qsrc/modules/colorPicker/ColorPickerUI/Assets/ColorPicker/colorPicker.cur\E$ ^\Qsrc/modules/colorPicker/ColorPickerUI/Assets/ColorPicker/colorPicker.cur\E$
^\Qsrc/modules/colorPicker/ColorPickerUI/Shaders/GridShader.cso\E$ ^\Qsrc/modules/colorPicker/ColorPickerUI/Shaders/GridShader.cso\E$
^\Qsrc/modules/MouseUtils/MouseJumpUI/MainForm.resx\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/frmAbout.cs\E$
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmInputCallback.resx\E$ ^\Qsrc/modules/MouseWithoutBorders/App/Form/frmInputCallback.resx\E$
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmLogon.resx\E$ ^\Qsrc/modules/MouseWithoutBorders/App/Form/frmLogon.resx\E$
^\Qsrc/modules/MouseWithoutBorders/App/Form/frmMatrix.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/App/Form/frmScreen.resx\E$
^\Qsrc/modules/MouseWithoutBorders/ModuleInterface/generateSecurityDescriptor.h\E$ ^\Qsrc/modules/MouseWithoutBorders/ModuleInterface/generateSecurityDescriptor.h\E$
^\Qsrc/modules/peek/Peek.Common/NativeMethods.txt\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/.*\.Designer\.cs$
^src/modules/MouseWithoutBorders/App/Form/.*\.resx$ ^src/modules/MouseWithoutBorders/App/Form/.*\.resx$
^src/modules/MouseWithoutBorders/App/Helper/.*\.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$ ^tools/Verification scripts/Check preview handler registration\.ps1$
ignore$ ignore$

106
.github/actions/spell-check/expect.txt поставляемый
Просмотреть файл

@ -1,6 +1,3 @@
# FALSE POSITIVES
## "PackagemanagerWrapper.cs" should be "PackageManagerWrapper.cs"
## NOTICE.MD > MOZILLA PUBLIC LICENSE v1.1
aaaa aaaa
abcdefghjkmnpqrstuvxyz abcdefghjkmnpqrstuvxyz
abgr abgr
@ -22,7 +19,6 @@ ADDUNDORECORD
ADifferent ADifferent
adml adml
admx admx
advapi
advfirewall advfirewall
AFeature AFeature
AFFINETRANSFORM AFFINETRANSFORM
@ -56,7 +52,6 @@ APPBARDATA
appdata appdata
APPEXECLINK APPEXECLINK
Appium Appium
Applicationcan
APPLICATIONFRAMEHOST APPLICATIONFRAMEHOST
appmanifest appmanifest
appmodel appmodel
@ -124,7 +119,6 @@ bmi
bms bms
BNumber BNumber
BODGY BODGY
BOKMAL
bootstrapper bootstrapper
BOOTSTRAPPERINSTALLFOLDER BOOTSTRAPPERINSTALLFOLDER
bostrot bostrot
@ -164,7 +158,6 @@ CCom
CContext CContext
CDeclaration CDeclaration
CDEF CDEF
cdpx
CElems CElems
CENTERALIGN CENTERALIGN
ceq ceq
@ -180,7 +173,6 @@ cidl
cim cim
CImage CImage
cla cla
clangformat
CLASSDC CLASSDC
CLASSNOTAVAILABLE CLASSNOTAVAILABLE
clickable clickable
@ -202,12 +194,10 @@ CMINVOKECOMMANDINFO
CMINVOKECOMMANDINFOEX CMINVOKECOMMANDINFOEX
CMock CMock
CMONITORS CMONITORS
cmpgt
cmph cmph
cne cne
CNF CNF
coclass coclass
codeofconduct
codereview codereview
Codespaces Codespaces
codicon codicon
@ -217,7 +207,6 @@ colorformat
colorhistory colorhistory
colorhistorylimit colorhistorylimit
COLORKEY COLORKEY
comctl
comdef comdef
comdlg comdlg
comexp comexp
@ -227,9 +216,6 @@ commctrl
commdlg commdlg
compmgmt compmgmt
COMPOSITIONFULL COMPOSITIONFULL
comsupp
comsuppw
comsuppwd
comutil comutil
CONFIGW CONFIGW
CONFLICTINGMODIFIERKEY CONFLICTINGMODIFIERKEY
@ -249,7 +235,6 @@ COULDNOT
countof countof
cph cph
CPower CPower
cppblog
cppwinrt cppwinrt
createdump createdump
CREATESCHEDULEDTASK CREATESCHEDULEDTASK
@ -266,7 +251,6 @@ CSettings
cso cso
CSRW CSRW
CStyle CStyle
CSY
CTest CTest
currentculture currentculture
CURRENTDIR CURRENTDIR
@ -277,7 +261,6 @@ CUSTOMACTIONTEST
CVal CVal
cvd cvd
CVirtual CVirtual
cvtepu
cxfksword cxfksword
CXSCREEN CXSCREEN
CXSMICON CXSMICON
@ -293,7 +276,6 @@ datareader
datatracker datatracker
dataversion dataversion
Dayof Dayof
Dbghelp
DBLCLKS DBLCLKS
DBLEPSILON DBLEPSILON
DCapture DCapture
@ -378,7 +360,7 @@ drivedetectionwarning
dshow dshow
DSTINVERT DSTINVERT
DUMMYUNIONNAME DUMMYUNIONNAME
dutil Dutil
DVASPECT DVASPECT
DVASPECTINFO DVASPECTINFO
DVD DVD
@ -407,21 +389,17 @@ dwrite
dxgi dxgi
dxgidebug dxgidebug
dxgiformat dxgiformat
dxguid
easeofaccess easeofaccess
ecount ecount
EData EData
Edid Edid
EDITKEYBOARD EDITKEYBOARD
editkeyboardwindow
EDITSHORTCUTS EDITSHORTCUTS
editshortcutswindow
EFile EFile
ekus ekus
emmintrin emmintrin
Emoji Emoji
ENABLEDELAYEDEXPANSION ENABLEDELAYEDEXPANSION
enabledisable
ENABLEDPOPUP ENABLEDPOPUP
encodedlaunch encodedlaunch
encryptor encryptor
@ -444,11 +422,9 @@ ESettings
esrp esrp
etl etl
etw etw
EUQ
eurochange eurochange
eventlog eventlog
eventvwr eventvwr
everytime
evntrace evntrace
evt evt
EWXFORCE EWXFORCE
@ -521,6 +497,7 @@ FZE
gacutil gacutil
Gaeilge Gaeilge
Gaidhlig Gaidhlig
GC'ed
GCLP GCLP
gdi gdi
gdiplus gdiplus
@ -549,12 +526,10 @@ GSM
gtm gtm
guiddata guiddata
guiddef guiddef
guidgenerator
GUITHREADINFO GUITHREADINFO
GValue GValue
gwl gwl
GWLP GWLP
handlekeyboardhookevent
hangeul hangeul
Hanzi Hanzi
Hardlines Hardlines
@ -640,38 +615,25 @@ HWNDLAST
HWNDNEXT HWNDNEXT
HWNDPREV HWNDPREV
hyjiacan hyjiacan
IApp
IBeam IBeam
ICapture
IClass
ICONERROR ICONERROR
ICONLOCATION ICONLOCATION
IData
IDD IDD
IDesktop
IDirect
idl idl
idlist idlist
IDOn
IDR IDR
IDXGI IDXGI
IEnum
ietf ietf
IExec
IEXPLORE IEXPLORE
IFACEMETHOD IFACEMETHOD
IFACEMETHODIMP IFACEMETHODIMP
IFile IFile
IFilter
IGNOREUNKNOWN IGNOREUNKNOWN
IGraphics
iid iid
Iindex Iindex
IJson
Ijwhost Ijwhost
IKs IKs
iljxck iljxck
ILogon
IMAGEHLP IMAGEHLP
IMAGERESIZERCONTEXTMENU IMAGERESIZERCONTEXTMENU
IMAGERESIZEREXT IMAGERESIZEREXT
@ -683,7 +645,7 @@ inetcpl
Infobar Infobar
INFOEXAMPLE INFOEXAMPLE
Infotip Infotip
initguid INITGUID
inorder inorder
INPC INPC
inproc inproc
@ -691,7 +653,6 @@ INPUTHARDWARE
INPUTKEYBOARD INPUTKEYBOARD
INPUTLANGCHANGED INPUTLANGCHANGED
INPUTMOUSE INPUTMOUSE
inputparser
INPUTSINK INPUTSINK
INPUTTYPE INPUTTYPE
INSTALLDESKTOPSHORTCUT INSTALLDESKTOPSHORTCUT
@ -712,30 +673,21 @@ INTRESOURCE
INVALIDARG INVALIDARG
invalidoperatioexception invalidoperatioexception
ipcmanager ipcmanager
IPlugin
IPower
IPREVIEW IPREVIEW
ipreviewhandlervisualssetfont ipreviewhandlervisualssetfont
IProperty
IPublic
irprops irprops
isbi isbi
ISearch ISearch
ISettings ISettings
IShell
isocpp isocpp
iss iss
issecret issecret
ISSEPARATOR ISSEPARATOR
ITask
ith ith
ITHUMBNAIL ITHUMBNAIL
ITwoWayPipeMessageIPCManaged
IUI IUI
IUnknown IUnknown
IUse IUse
IWbem
IWeb
IWIC IWIC
iwr iwr
IYUV IYUV
@ -757,7 +709,6 @@ keyboardmanagercommon
KEYBOARDMANAGEREDITOR KEYBOARDMANAGEREDITOR
keyboardmanagerstate keyboardmanagerstate
keyboardmanagerui keyboardmanagerui
keydropdowncontrol
KEYEVENTF KEYEVENTF
KEYIMAGE KEYIMAGE
keynum keynum
@ -769,25 +720,21 @@ kmph
Knownfolders Knownfolders
KSPROPERTY KSPROPERTY
Kybd Kybd
languagesjson
lastcodeanalysissucceeded lastcodeanalysissucceeded
Lastdevice Lastdevice
LASTEXITCODE LASTEXITCODE
LAYOUTRTL LAYOUTRTL
lcb lcb
LCIDTo LCIDTo
lcl
Lclean Lclean
Ldone Ldone
ldx ldx
LEFTSCROLLBAR LEFTSCROLLBAR
lego
LError LError
LEVELID LEVELID
LExit LExit
lhwnd lhwnd
LIBID LIBID
licate
lindex lindex
LINKOVERLAY LINKOVERLAY
LINQTo LINQTo
@ -864,7 +811,6 @@ MAKEINTRESOURCE
MAKEINTRESOURCEA MAKEINTRESOURCEA
MAKEINTRESOURCEW MAKEINTRESOURCEW
MAKELANGID MAKELANGID
makepri
manifestdependency manifestdependency
MAPPEDTOSAMEKEY MAPPEDTOSAMEKEY
MAPTOSAMESHORTCUT MAPTOSAMESHORTCUT
@ -892,13 +838,11 @@ mfc
mfidl mfidl
mfobjects mfobjects
mfplat mfplat
Mfsensorgroup
mftransform mftransform
Mgmt Mgmt
mic mic
midl midl
mii mii
MIIM
mindaro mindaro
Minimatch Minimatch
Minimizable Minimizable
@ -988,7 +932,6 @@ NCPAINT
NCRENDERING NCRENDERING
ndp ndp
NEEDDISPATCH NEEDDISPATCH
needinfo
netcoreapp netcoreapp
netcpl netcpl
netframework netframework
@ -1006,7 +949,6 @@ NEWPLUSSHELLEXTENSIONWIN
newrow newrow
newsgroups newsgroups
NIF NIF
NLD
NLog NLog
NLSTEXT NLSTEXT
NNN NNN
@ -1083,7 +1025,6 @@ oldpath
oldtheme oldtheme
oleaut oleaut
OLECHAR OLECHAR
onebranch
opencode opencode
OPENFILENAME OPENFILENAME
opensource opensource
@ -1140,7 +1081,6 @@ pdto
pdtobj pdtobj
pdw pdw
Peb Peb
pef
PElems PElems
Pels Pels
PERCEIVEDFLAG PERCEIVEDFLAG
@ -1165,7 +1105,6 @@ pinvoke
pipename pipename
PKBDLLHOOKSTRUCT PKBDLLHOOKSTRUCT
plib plib
PLK
ploc ploc
ploca ploca
plocm plocm
@ -1212,7 +1151,6 @@ prgms
pri pri
PRINTCLIENT PRINTCLIENT
printmanagement printmanagement
privacystatement
prm prm
proactively proactively
PROCESSENTRY PROCESSENTRY
@ -1227,7 +1165,6 @@ projectname
PROPBAG PROPBAG
PROPERTYKEY PROPERTYKEY
propkey propkey
propsys
PROPVARIANT PROPVARIANT
propvarutil propvarutil
prvpane prvpane
@ -1237,7 +1174,6 @@ PSECURITY
psfgao psfgao
psfi psfi
PSMODULEPATH PSMODULEPATH
Psr
psrm psrm
psrree psrree
pstatstg pstatstg
@ -1254,7 +1190,7 @@ PTOKEN
PToy PToy
ptstr ptstr
pui pui
pwa PWAs
pwcs pwcs
PWSTR PWSTR
pwsz pwsz
@ -1320,7 +1256,6 @@ Renamer
reparented reparented
reparenting reparenting
reparse reparse
reportbug
reportfileaccesses reportfileaccesses
requery requery
requerying requerying
@ -1332,7 +1267,6 @@ RESIZETOFIT
resmimetype resmimetype
RESOURCEID RESOURCEID
RESTORETOMAXIMIZED RESTORETOMAXIMIZED
restrictedcapabilities
restrictederrorinfo restrictederrorinfo
resultlist resultlist
RETURNONLYFSDIRS RETURNONLYFSDIRS
@ -1359,7 +1293,6 @@ Rsp
rstringalnum rstringalnum
rstringalpha rstringalpha
rstringdigit rstringdigit
Rstrtmgr
RTB RTB
RTLREADING RTLREADING
ruleset ruleset
@ -1368,7 +1301,6 @@ rundll
rungameid rungameid
RUNLEVEL RUNLEVEL
runtimeclass runtimeclass
runtimeobject
runtimepack runtimepack
runtimes runtimes
ruuid ruuid
@ -1388,14 +1320,13 @@ Scode
screensaver screensaver
screenshots screenshots
scrollviewer scrollviewer
sddl SDDL
SDKDDK SDKDDK
sdns sdns
searchterm searchterm
SEARCHUI SEARCHUI
secpol secpol
SENDCHANGE SENDCHANGE
sendinput
sendvirtualinput sendvirtualinput
serverside serverside
SETCONTEXT SETCONTEXT
@ -1411,7 +1342,6 @@ settingsheader
settingshotkeycontrol settingshotkeycontrol
setvariable setvariable
SETWORKAREA SETWORKAREA
setzero
sfgao sfgao
SFGAOF SFGAOF
SHANDLE SHANDLE
@ -1419,7 +1349,7 @@ sharpkeys
SHCNE SHCNE
SHCNF SHCNF
SHCONTF SHCONTF
shcore Shcore
shellapi shellapi
SHELLDETAILS SHELLDETAILS
SHELLDLL SHELLDLL
@ -1440,7 +1370,6 @@ shmem
SHNAMEMAPPING SHNAMEMAPPING
shobjidl shobjidl
SHORTCUTATLEAST SHORTCUTATLEAST
shortcutcontrol
SHORTCUTMAXONEACTIONKEY SHORTCUTMAXONEACTIONKEY
SHORTCUTNOREPEATEDMODIFIER SHORTCUTNOREPEATEDMODIFIER
SHORTCUTONEACTIONKEY SHORTCUTONEACTIONKEY
@ -1469,7 +1398,6 @@ sigdn
SIGNINGSCENARIO SIGNINGSCENARIO
Signtool Signtool
SINGLEKEY SINGLEKEY
singlekeyremapcontrol
sipolicy sipolicy
SIZEBOX SIZEBOX
Sizename Sizename
@ -1540,7 +1468,6 @@ STRINGIZE
stringtable stringtable
stringval stringval
Strm Strm
Strmiids
strret strret
strsafe strsafe
strutil strutil
@ -1581,7 +1508,6 @@ SYSLIB
SYSMENU SYSMENU
SYSTEMAPPS SYSTEMAPPS
SYSTEMTIME SYSTEMTIME
SYSTEMWOW
tailwindcss tailwindcss
tapp tapp
TApplication TApplication
@ -1594,7 +1520,7 @@ TARGETHEADER
targetver targetver
taskkill taskkill
taskschd taskschd
tchar TCHAR
Tcollab Tcollab
tcs tcs
tcscpy tcscpy
@ -1645,7 +1571,6 @@ traies
transicc transicc
TRAYMOUSEMESSAGE TRAYMOUSEMESSAGE
triaging triaging
TRK
trl trl
trx trx
tsa tsa
@ -1680,7 +1605,7 @@ uniquifier
Uniquifies Uniquifies
unitconverter unitconverter
unittests unittests
unknwn Unknwn
UNLEN UNLEN
UNORM UNORM
unregistering unregistering
@ -1698,14 +1623,13 @@ Usb
USEDEFAULT USEDEFAULT
USEFILEATTRIBUTES USEFILEATTRIBUTES
USERDATA USERDATA
Userenv
USESHOWWINDOW USESHOWWINDOW
USESTDHANDLES USESTDHANDLES
USRDLL USRDLL
UType UType
uuidv uuidv
uwp uwp
uxtheme Uxtheme
vabdq vabdq
validmodulename validmodulename
valuegenerator valuegenerator
@ -1769,8 +1693,6 @@ Vtbl
WANTMAPPINGHANDLE WANTMAPPINGHANDLE
WANTPALM WANTPALM
wbem wbem
Wbemidl
wbemuuid
WBounds WBounds
Wca Wca
wcautil wcautil
@ -1788,9 +1710,9 @@ webcam
webpage webpage
websites websites
wekyb wekyb
Wevtapi
wgpocpl wgpocpl
WIC WIC
wifi
wil wil
winapi winapi
wincodec wincodec
@ -1806,7 +1728,6 @@ WINDOWPOSCHANGED
WINDOWPOSCHANGING WINDOWPOSCHANGING
windowsapp windowsapp
WINDOWSBUILDNUMBER WINDOWSBUILDNUMBER
Windowscodecs
windowssearch windowssearch
windowssettings windowssettings
WINDOWSTYLES WINDOWSTYLES
@ -1817,20 +1738,17 @@ WINEVENT
winevt winevt
winexe winexe
winforms winforms
winfx
winget winget
wingetcreate wingetcreate
Winhook Winhook
WINL WINL
winlogon winlogon
winmd winmd
winmm WINNT
winnt
winres winres
winrt winrt
winsdk winsdk
winsdkver winsdkver
winspool
winsta winsta
winternl winternl
WINTHRESHOLD WINTHRESHOLD
@ -1857,7 +1775,6 @@ WNDCLASSEXW
WNDCLASSW WNDCLASSW
WNDPROC WNDPROC
wnode wnode
workarounds
WORKSPACESEDITOR WORKSPACESEDITOR
WORKSPACESLAUNCHER WORKSPACESLAUNCHER
WORKSPACESSNAPSHOTTOOL WORKSPACESSNAPSHOTTOOL
@ -1897,7 +1814,6 @@ XElement
xfd xfd
XFile XFile
XIncrement XIncrement
XLoc
XNamespace XNamespace
Xoshiro Xoshiro
XPels XPels

Просмотреть файл

@ -1,119 +1,289 @@
# reject `m_data` as VxWorks defined it and that breaks things if it's used elsewhere # 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) # 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) # 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, # 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 # you might not want to check in code where you skip all the other tests.
# to use this:
#\bfit\( #\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[,.] \bany more[,.]
# s.b. GitHub # Should be `'`
(?<![&*.]|// |\btype )\bGithub\b(?![{)]) (?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 # Should be `briefcase`
(?<![&*.]|// |\btype )\bGitlab\b(?![{)]) \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 \bJavascript\b
# s.b. macOS or Mac OS X or ... # Should be `macOS` or `Mac OS X` or ...
\bMacOS\b \bMacOS\b
# s.b. Microsoft # Should be `Microsoft`
\bMicroSoft\b \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 \bTypescript\b
# s.b. another # Should be `another`
\ban[- ]other\b \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 \b[Dd]epreciation [Ww]arnings?\b
# s.b. greater than # Should be `greater than`
\bgreater then\b \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 \bin from of\b
# s.b. into # Should be `into`
# when not phrasal and when `in order to` would be wrong: # when not phrasal and when `in order to` would be wrong:
# https://thewritepractice.com/into-vs-in-to/ # https://thewritepractice.com/into-vs-in-to/
\sin to\s(?!if\b) \sin to\s(?!if\b)
# s.b. is obsolete # Should be `use`
\sin used by\b
# Should be `is obsolete`
\bis obsolescent\b \bis obsolescent\b
# s.b. it's or its # Should be `it's` or `its`
\bits['] \bits[']
# s.b. opt-in # Should be `its`
(?<!\sfor)\sopt in\s \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 \bless then\b
# s.b. one of # Should be `load balancer`
\bon of\b \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 \bother[- ]wise\b
# s.b. or (more|less) # Should be `or (more|less)`
\bore (?:more|less)\b \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 \bnon existing\b
# Should be `nonexistent`
\b[Nn]o[nt][- ]existent\b \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*|(?:\*|//|/*)\s+`)[\\@](?:breif|(?:detail|detials)|(?:params(?!\.)|prama?)|ret(?:uns?)|retvl)\b
# s.b. preexisting # Should be `preexisting`
[Pp]re[- ]existing [Pp]re[- ]existing
# s.b. preempt # Should be `preempt`
[Pp]re[- ]empt\b [Pp]re[- ]empt\b
# s.b. preemptively # Should be `preemptively`
[Pp]re[- ]emptively [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 [Rr]ecent changed
# s.b. reentrancy # Should be `reentrancy`
[Rr]e[- ]entrancy [Rr]e[- ]entrancy
# s.b. reentrant # Should be `reentrant`
[Rr]e[- ]entrant [Rr]e[- ]entrant
# s.b. understand # Should be `strong suit`
\b(?:my|his|her|their) strong suite\b
# Should be `understand`
\bunder stand\b \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 #\bwork[- ]arounds\b
# s.b. workaround # Should be `workaround`
(?:(?:[Aa]|[Tt]he|ugly)\swork[- ]around\b|\swork[- ]around\s+for) (?:(?:[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 \b(?:coarse|fine) grained\b
# s.b. neither/nor -- or reword # Homoglyph (Cyrillic) should be `A`/`B`/`C`/`E`/`H`/`I`/`I`/`J`/`K`/`M`/`O`/`P`/`S`/`T`/`Y`
#\bnot\b[^.?!"/(]+\bnor\b # 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 # Homoglyph (Cyrillic) should be `a`/`b`/`e`
# s.b. neither/nor (plus rewording the beginning) # It's possible that your content is intentionally mixing Cyrllic and Latin scripts, but if it isn't, you definitely want to correct this.
\bnot\b[^.?!"/]*\bneither\b[^.?!"/(]*\bnor\b [аве](?=[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. # Should be `neither/nor` -- or reword
# Duplicated words are generally mistakes. #(?!<do )\bnot\b([^.?!"/(](?!neither|,.*?,))+\bnor\b
# 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. # Should be `neither/nor` (plus rewording the beginning)
# If the highlighted doubled word pair is in prose, have someone read the English before you dismiss this error. # 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 \s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s

279
.github/actions/spell-check/patterns.txt поставляемый
Просмотреть файл

@ -1,41 +1,22 @@
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns # See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
# Automatically suggested patterns # #includes
# hit-count: 3011 file-count: 842 ^\s*#include\s*(?:<.*?>|".*?")
# IServiceProvider / isAThing
\b(?:I|isA)(?=(?:[A-Z][a-z]{2,})+\b)
# hit-count: 2239 file-count: 134 # #pragma lib
# hex runs ^\s*#pragma comment\(lib, ".*?"\)
\b[0-9a-fA-F]{16,}\b
# hit-count: 1868 file-count: 1 # languageHashTable
# sha-... -- uses a fancy capture "\w+(?:-\w+|)"\s+=\s+@\(".*"\)
(\\?['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hit-count: 1100 file-count: 97 # wikipedia
# base64 encoded content, possibly wrapped in mime \b\w\w\.wikipedia\.org/wiki/[-\w%.#]+
(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)
# hit-count: 426 file-count: 165 # css fonts
# GitHub SHAs (markdown) \bfont-family:[^;}]+
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
# hit-count: 331 file-count: 117 # .github/policies/resourceManagement.yml
# hex digits including css/html color classes: pattern: '.*'
(?:[\\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,})(?=.*['"`](?:, "[^{]|\]))
# tabs in c# # tabs in c#
\$"\\t \$"\\t
@ -46,81 +27,6 @@
# windows line breaks in strings # windows line breaks in strings
\\r\\n \\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 # power shell gallery website
\bpowershellgallery.com/[-_a-zA-Z0-9()=./%]* \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 # UnitTests
\[DataRow\(.*\)\] \[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 # 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 # hit-count: 1 file-count: 1
# GHSA # GHSA
GHSA(?:-[0-9a-z]{4}){3} GHSA(?:-[0-9a-z]{4}){3}
# hit-count: 1 file-count: 1 # hit-count: 1 file-count: 1
# medium # GitHub actions
\bmedium\.com/\@?[^/\s"]+/[-\w]+ \buses:\s+[-\w.]+/[-\w./]+@[-\w.]+
# hit-count: 1 file-count: 1 # hit-count: 1 file-count: 1
# kubectl.kubernetes.io/last-applied-configuration # medium
"kubectl.kubernetes.io/last-applied-configuration": ".*" \bmedium\.com/@?[^/\s"]+/[-\w]+
# hit-count: 1 file-count: 1
# sha-... -- uses a fancy capture
(\\?['"]|&quot;)[0-9a-f]{40,}\g{-1}
# hit-count: 1 file-count: 1 # hit-count: 1 file-count: 1
# tar arguments # tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+ \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` # Questionably acceptable forms of `in to`
# Personally, I prefer `log into`, but people object # Personally, I prefer `log into`, but people object
# https://www.tprteaching.com/log-into-log-in-to-login/ # 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 # to opt in
\bto opt in\b \bto opt in\b
# acceptable duplicates # acceptable duplicates
# ls directory listings # 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 # mount
\bmount\s+-t\s+(\w+)\s+\g{-1}\b \bmount\s+-t\s+(\w+)\s+\g{-1}\b
# C types and repeated CSS values # C types and repeated CSS values
\s(auto|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?: \g{-1})+\s \s(auto|buffalo|center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?: \g{-1})+\s
# C struct # C enum and struct
\bstruct\s+(\w+)\s+\g{-1}\b \b(?:enum|struct)\s+(\w+)\s+\g{-1}\b
# go templates # go templates
\s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml): \s(\w+)\s+\g{-1}\s+\`(?:graphql|inject|json|yaml):
# doxygen / javadoc / .net # 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 # Commit message -- Signed-off-by and friends
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$ ^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$

2
.github/actions/spell-check/reject.txt поставляемый
Просмотреть файл

@ -3,9 +3,11 @@
benefitting benefitting
occurences? occurences?
^dependan.* ^dependan.*
^diables?$
^oer$ ^oer$
Sorce Sorce
^[Ss]pae.* ^[Ss]pae.*
^Teh$
^untill$ ^untill$
^untilling$ ^untilling$
^wether.* ^wether.*

174
.github/workflows/spelling2.yml поставляемый
Просмотреть файл

@ -34,14 +34,14 @@ name: Spell checking
# #
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key # 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` # Requires enabling `security-events: write`
# and configuring the action with `use_sarif: 1` # 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: # Minimal workflow structure:
# #
@ -60,23 +60,23 @@ name: Spell checking
on: on:
push: push:
branches: branches:
- "**" - "**"
tags-ignore: tags-ignore:
- "**" - "**"
pull_request_target: pull_request_target:
branches: branches:
- "**" - "**"
types: types:
- 'opened' - "opened"
- 'reopened' - "reopened"
- 'synchronize' - "synchronize"
issue_comment: issue_comment:
types: types:
- 'created' - "created"
jobs: jobs:
spelling: spelling:
name: Spell checking name: Check Spelling
permissions: permissions:
contents: read contents: read
pull-requests: read pull-requests: read
@ -91,52 +91,59 @@ jobs:
# note: If you use only_check_changed_files, you do not want cancel-in-progress # note: If you use only_check_changed_files, you do not want cancel-in-progress
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: check-spelling - name: check-spelling
id: spelling id: spelling
uses: check-spelling/check-spelling@v0.0.22 uses: check-spelling/check-spelling@v0.0.24
with: with:
config: .github/actions/spell-check config: .github/actions/spell-check
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }} suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
checkout: true checkout: true
check_file_names: 1 check_file_names: 1
spell_check_this: microsoft/PowerToys@main spell_check_this: microsoft/PowerToys@main
post_comment: 0 post_comment: 0
use_magic_file: 1 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 report-timing: 1
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 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
use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }} experimental_apply_changes_via_bot: 1
extra_dictionary_limit: 20 use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }}
extra_dictionaries: check_extra_dictionaries: ""
cspell:aws/aws.txt dictionary_source_prefixes: >
cspell:cpp/src/compiler-clang-attributes.txt {
cspell:cpp/src/compiler-msvc.txt "cspell": "https://raw.githubusercontent.com/check-spelling/cspell-dicts/v20241114/dictionaries/"
cspell:cpp/src/lang-keywords.txt }
cspell:cpp/src/stdlib-c.txt extra_dictionaries: |
cspell:cpp/src/stdlib-cmath.txt cspell:software-terms/softwareTerms.txt
cspell:cpp/src/stdlib-cpp.txt cspell:cpp/stdlib-cpp.txt
cspell:csharp/csharp.txt cspell:filetypes/filetypes.txt
cspell:css/dict/css.txt cspell:cpp/stdlib-c.txt
cspell:django/dict/django.txt cspell:lorem-ipsum/dictionary.txt
cspell:dotnet/dict/dotnet.txt cspell:python/python/python-lib.txt
cspell:filetypes/filetypes.txt cspell:php/php.txt
cspell:fullstack/dict/fullstack.txt cspell:fullstack/fullstack.txt
cspell:golang/dict/go.txt cspell:dotnet/dotnet.txt
cspell:html/dict/html.txt cspell:swift/swift.txt
cspell:java/src/java.txt cspell:node/node.txt
cspell:java/src/java-terms.txt cspell:dart/dart.txt
cspell:k8s/dict/k8s.txt cspell:django/django.txt
cspell:lorem-ipsum/dictionary.txt cspell:python/python/python.txt
cspell:monkeyc/src/monkeyc_keywords.txt cspell:powershell/powershell.txt
cspell:node/dict/node.txt cspell:npm/npm.txt
cspell:php/dict/php.txt cspell:golang/go.txt
cspell:powershell/dict/powershell.txt cspell:cpp/compiler-msvc.txt
cspell:python/src/common/extra.txt cspell:csharp/csharp.txt
cspell:python/src/python/python.txt cspell:html/html.txt
cspell:python/src/python/python-lib.txt cspell:java/java.txt
cspell:scala/dict/scala.txt cspell:aws/aws.txt
cspell:software-terms/dict/softwareTerms.txt cspell:typescript/typescript.txt
cspell:swift/src/swift.txt cspell:cpp/lang-keywords.txt
cspell:typescript/dict/typescript.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: comment-push:
name: Report (Push) name: Report (Push)
@ -144,16 +151,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: spelling needs: spelling
permissions: permissions:
actions: read
contents: write contents: write
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push' if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
steps: steps:
- name: comment - name: comment
uses: check-spelling/check-spelling@v0.0.22 uses: check-spelling/check-spelling@v0.0.24
with: with:
config: .github/actions/spell-check config: .github/actions/spell-check
checkout: true checkout: true
spell_check_this: microsoft/PowerToys@main spell_check_this: microsoft/PowerToys@main
task: ${{ needs.spelling.outputs.followup }} task: ${{ needs.spelling.outputs.followup }}
comment-pr: comment-pr:
name: Report (PR) name: Report (PR)
@ -161,18 +169,19 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: spelling needs: spelling
permissions: permissions:
actions: read
contents: read contents: read
pull-requests: write pull-requests: write
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request') if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
steps: steps:
- name: comment - name: comment
uses: check-spelling/check-spelling@v0.0.22 uses: check-spelling/check-spelling@v0.0.24
with: with:
config: .github/actions/spell-check config: .github/actions/spell-check
checkout: true checkout: true
spell_check_this: check-spelling/spell-check-this@prerelease spell_check_this: check-spelling/spell-check-this@prerelease
task: ${{ needs.spelling.outputs.followup }} task: ${{ needs.spelling.outputs.followup }}
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }} experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
update: update:
name: Update PR name: Update PR
@ -182,18 +191,19 @@ jobs:
actions: read actions: read
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ if: ${{
github.repository_owner != 'microsoft' && github.repository_owner != 'microsoft' &&
github.event_name == 'issue_comment' && github.event_name == 'issue_comment' &&
github.event.issue.pull_request && github.event.issue.pull_request &&
contains(github.event.comment.body, '@check-spelling-bot apply') contains(github.event.comment.body, '@check-spelling-bot apply') &&
contains(github.event.comment.body, 'https://')
}} }}
concurrency: concurrency:
group: spelling-update-${{ github.event.issue.number }} group: spelling-update-${{ github.event.issue.number }}
cancel-in-progress: false cancel-in-progress: false
steps: steps:
- name: apply spelling updates - name: apply spelling updates
uses: check-spelling/check-spelling@v0.0.22 uses: check-spelling/check-spelling@v0.0.24
with: with:
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }} experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
checkout: true checkout: true
ssh_key: "${{ secrets.CHECK_SPELLING }}" ssh_key: "${{ secrets.CHECK_SPELLING }}"

Просмотреть файл

@ -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) ## 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 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 ## 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. 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++
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. 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> </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) #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
@ -71,7 +71,7 @@ END
#endif #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" /> <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" /> <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. **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). 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"> <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" /> <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. - 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). - 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. - 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 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. - 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 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: - 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. - [**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 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. - 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). - [**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 ## 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: [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. - 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. - 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. - 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) ## 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. - 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 ### 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): 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). - 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 `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 ## 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. 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 ## Settings format
KBM uses two sets of settings files. 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. - `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. - 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. - `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 ## 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 ## 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)). 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: 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. - **`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. - **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.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 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 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 [here](keyboardeventhandlers.md#HandleSingleKeyRemapEvent). - **`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.** - **[`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.** - **`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 [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.** - **`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. **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 ## 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 ## SendInput Special Scenarios
### Extended keys ### 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: The weird behavior that is caused by this can be found at these issues:
- https://github.com/microsoft/PowerToys/issues/3478 - 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 - https://github.com/microsoft/PowerToys/issues/3981
### Scan code ### 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 ## 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. 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 - https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/KeyboardEventHandlers.cpp#L509-L510
### Suppressing Num Lock in a keyboard hook ### 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). 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. 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 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) - [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 ## 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)): 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_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 [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L159-L163)). - **`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 [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L220)). - **`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 [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/ui/LoadingAndSavingRemappingHelper.cpp#L221)). - **`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 [here](https://github.com/microsoft/PowerToys/blob/b80578b1b9a4b24c9945bddac33c771204280107/src/modules/keyboardmanager/dll/dllmain.cpp#L364-L369)). - **`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. 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 ## 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. **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. 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 ### 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 ### 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. [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
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 ## 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 ### 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). [`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. 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) [**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 ### 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). [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. 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. **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. 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 ## 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 #### 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. 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.

Просмотреть файл

@ -96,7 +96,7 @@ The plugin uses only these interfaces (all inside the `Main.cs`):
#### Build Dependency #### Build Dependency
Access to PluginManager was needed to make this plugin work. Because of this a reference to PowerToys.PowerLauncher was needed. 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. 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 ### Caching

Просмотреть файл

@ -32,7 +32,7 @@ Each plugin implements the `IPlugin` interface which comprises of the `Init()` a
### Score ### 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 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. - 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
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. 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) 5. Common start menu (Applications which are common to all users)
8. Locations pointed to by the PATH environment variable. 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. - 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 1. Lnk Shortcuts
2. Appref files 2. Appref files
3. Internet shortcut - steam and epic games 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 | | `SubtitleShowPid` | `false` | Show process id in subtitle |
| `SubtitleShowDesktopName` | `true` | Show desktop name in subtitle (If two or more desktops exist) | | `SubtitleShowDesktopName` | `true` | Show desktop name in subtitle (If two or more desktops exist) |
| `ConfirmKillProcess` | `true` | Request confirmation when killing a process | | `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) | | `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 | | `HideKillProcessOnElevatedProcesses` | `false` | Hide "kill process" button if additional permissions required |
| `HideExplorerSettingInfo` | `false` | Hide Explorer process information | | `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.` 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)
[`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)
[`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. [`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.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)
[`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). 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) #### [`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) #### [`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. 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 ## 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. - 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. 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 ## Keyboard Manager

Просмотреть файл

@ -1,5 +1,5 @@
# Overview # 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 ## Settings V2 Project structure
The Settings project .Net WinUI3 based project which The Settings project .Net WinUI3 based project which

Просмотреть файл

@ -3,7 +3,7 @@ export function regDefinition() {
tokenPostfix: '.reg', tokenPostfix: '.reg',
tokenizer: { tokenizer: {
root: [ root: [
// Header (case sensitive) // Header (case-sensitive)
[/Windows Registry Editor Version 5.00/, 'comment'], [/Windows Registry Editor Version 5.00/, 'comment'],
[/REGEDIT4/, 'comment'], [/REGEDIT4/, 'comment'],
// Comments // Comments

Просмотреть файл

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

Просмотреть файл

@ -39,7 +39,7 @@ namespace Microsoft.PowerToys.Telemetry
public const EventKeywords ProjectKeywordMeasure = (EventKeywords)0x0; public const EventKeywords ProjectKeywordMeasure = (EventKeywords)0x0;
/// <summary> /// <summary>
/// Group ID for Powertoys project. /// Group ID for PowerToys project.
/// </summary> /// </summary>
private static readonly string[] PowerToysTelemetryTraits = { "ETW_GROUP", "{42749043-438c-46a2-82be-c6cbeb192ff2}" }; private static readonly string[] PowerToysTelemetryTraits = { "ETW_GROUP", "{42749043-438c-46a2-82be-c6cbeb192ff2}" };

Просмотреть файл

@ -6,7 +6,7 @@
#pragma once #pragma once
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
// add headers that you want to pre-compile here // add headers that you want to pre-compile here
#include <unknwn.h> #include <Unknwn.h>
#include <winrt/base.h> #include <winrt/base.h>
#include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.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 // todo: that message should be shown from init caller and strings should be localized
MessageBoxW(NULL, MessageBoxW(NULL,
L"Logger can not be initialized", L"Logger cannot be initialized",
L"PowerToys", L"PowerToys",
MB_OK | MB_ICONERROR); MB_OK | MB_ICONERROR);

Просмотреть файл

@ -1,5 +1,5 @@
#pragma once #pragma once
#include <unknwn.h> #include <Unknwn.h>
#include <winrt/Windows.ApplicationModel.Background.h> #include <winrt/Windows.ApplicationModel.Background.h>
#include <winrt/Windows.Data.Xml.Dom.h> #include <winrt/Windows.Data.Xml.Dom.h>
#include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.h>

Просмотреть файл

@ -4,7 +4,7 @@
#include "utils/com_object_factory.h" #include "utils/com_object_factory.h"
#include "utils/window.h" #include "utils/window.h"
#include <unknwn.h> #include <Unknwn.h>
#include <winrt/base.h> #include <winrt/base.h>
#include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Data.Xml.Dom.h> #include <winrt/Windows.Data.Xml.Dom.h>

Просмотреть файл

@ -11,7 +11,7 @@ public:
EventWaiter() {} EventWaiter() {}
EventWaiter(const std::wstring& name, std::function<void(DWORD)> callback) 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); auto localExitThreadEvent = exitThreadEvent = CreateEvent(nullptr, false, false, nullptr);
HANDLE localWaitingEvent = waitingEvent = CreateEvent(nullptr, false, false, name.c_str()); HANDLE localWaitingEvent = waitingEvent = CreateEvent(nullptr, false, false, name.c_str());
std::thread([=]() { std::thread([=]() {

Просмотреть файл

@ -2,7 +2,7 @@
#include <winrt/Windows.Foundation.Metadata.h> #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 // Source : Microsoft-ui-xaml github
// Link: https://github.com/microsoft/microsoft-ui-xaml/blob/c045cde57c5c754683d674634a0baccda34d58c4/dev/dll/SharedHelpers.cpp // Link: https://github.com/microsoft/microsoft-ui-xaml/blob/c045cde57c5c754683d674634a0baccda34d58c4/dev/dll/SharedHelpers.cpp
template<uint16_t APIVersion> template<uint16_t APIVersion>

Просмотреть файл

@ -157,7 +157,7 @@ private:
} }
catch (const winrt::hresult_error& ex) 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 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 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)) if (ex.code() == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))

Просмотреть файл

@ -275,7 +275,7 @@
<value>Add variable</value> <value>Add variable</value>
</data> </data>
<data name="ProfileNotApplicableTitle" xml:space="preserve"> <data name="ProfileNotApplicableTitle" xml:space="preserve">
<value>Profile can not be applied.</value> <value>Profile cannot be applied.</value>
</data> </data>
<data name="StateProfileNotApplicableMsg" xml:space="preserve"> <data name="StateProfileNotApplicableMsg" xml:space="preserve">
<value>Variables or backup variables are invalid.</value> <value>Variables or backup variables are invalid.</value>

Просмотреть файл

@ -4,7 +4,7 @@
#include <initguid.h> #include <initguid.h>
#include <windows.h> #include <windows.h>
#include <unknwn.h> #include <Unknwn.h>
#include <restrictederrorinfo.h> #include <restrictederrorinfo.h>
#include <hstring.h> #include <hstring.h>
#include <dxgi.h> #include <dxgi.h>

Просмотреть файл

@ -21,7 +21,7 @@
#include <wrl.h> #include <wrl.h>
#include <wrl/module.h> #include <wrl/module.h>
#include <wrl/client.h> #include <wrl/client.h>
#include <unknwn.h> #include <Unknwn.h>
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
// PowerToys project common // PowerToys project common

Просмотреть файл

@ -20,7 +20,7 @@
#include <atlbase.h> #include <atlbase.h>
#include <wrl.h> #include <wrl.h>
#include <wrl/module.h> #include <wrl/module.h>
#include <unknwn.h> #include <Unknwn.h>
// PowerToys project common // PowerToys project common
#include <ProjectTelemetry.h> #include <ProjectTelemetry.h>

Просмотреть файл

@ -10,7 +10,7 @@ namespace WorkspacesEditor.Utils
{ {
public static string UpperCamelCaseToDashCase(this string str) public static string UpperCamelCaseToDashCase(this string str)
{ {
// If it's single letter variable, leave it as it is // If it's a single letter variable, leave it as it is
return str.Length == 1 return str.Length == 1
? str ? str
: string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLowerInvariant(); : string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLowerInvariant();

Просмотреть файл

@ -10,7 +10,7 @@ namespace WorkspacesLauncherUI.Utils
{ {
public static string UpperCamelCaseToDashCase(this string str) public static string UpperCamelCaseToDashCase(this string str)
{ {
// If it's single letter variable, leave it as it is // If it's a single letter variable, leave it as it is
if (str.Length == 1) if (str.Length == 1)
{ {
return str; return str;

Просмотреть файл

@ -1,5 +1,5 @@
#pragma once #pragma once
extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when the a watched settings file is updated extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when a watched settings file is updated
void InitializeWinhookEventIds(); void InitializeWinhookEventIds();

Просмотреть файл

@ -102,7 +102,7 @@ namespace ColorPicker.Views
private void HistoryColors_ItemClick(object sender, ItemClickEventArgs e) private void HistoryColors_ItemClick(object sender, ItemClickEventArgs e)
{ {
// Note: it does not handle clicking on the same color. // Note: it does not handle clicking on the same color.
// More appropriate event would be SelectionChanged but we can not distinguish between user action and program action inside of it. // More appropriate event would be SelectionChanged but we cannot distinguish between user action and program action inside of it.
SessionEventHelper.Event.EditorHistoryColorPicked = true; SessionEventHelper.Event.EditorHistoryColorPicked = true;
} }
*/ */

Просмотреть файл

@ -15,6 +15,6 @@ extern UINT WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE; // Scheduled when the watched a
extern UINT WM_PRIV_DEFAULT_LAYOUTS_FILE_UPDATE; // Scheduled when the watched default-layouts.json file is updated extern UINT WM_PRIV_DEFAULT_LAYOUTS_FILE_UPDATE; // Scheduled when the watched default-layouts.json file is updated
extern UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press extern UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press
extern UINT WM_PRIV_QUICK_LAYOUT_KEY; // Scheduled when we receive a key down press to quickly apply a layout extern UINT WM_PRIV_QUICK_LAYOUT_KEY; // Scheduled when we receive a key down press to quickly apply a layout
extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when the a watched settings file is updated extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when a watched settings file is updated
void InitializeWinhookEventIds(); void InitializeWinhookEventIds();

Просмотреть файл

@ -197,7 +197,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (ExcludedApp_ByUser) TEST_METHOD (ExcludedApp_ByUser)
{ {
// case sensitive, should be uppercase // case-sensitive, should be uppercase
FancyZonesSettings::instance().SetSettings(Settings{ .excludedAppsArray = { L"TEST_EXCLUDED" } }); FancyZonesSettings::instance().SetSettings(Settings{ .excludedAppsArray = { L"TEST_EXCLUDED" } });
// exclude by window title // exclude by window title

Просмотреть файл

@ -24,7 +24,7 @@ namespace FancyZonesEditor
Logger.LogTrace(); Logger.LogTrace();
// If new custom Canvas layout is created (i.e. edited Blank layout), // If new custom Canvas layout is created (i.e. edited Blank layout),
// it's type needs to be updated // its type needs to be updated
if (EditingLayout.Type == LayoutType.Blank) if (EditingLayout.Type == LayoutType.Blank)
{ {
EditingLayout.Type = LayoutType.Custom; EditingLayout.Type = LayoutType.Custom;

Просмотреть файл

@ -228,12 +228,12 @@ private:
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS) if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
{ {
auto val = get_last_error_message(GetLastError()); auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidCreate can not create guid. {}", val.has_value() ? val.value() : L""); Logger::warn(L"UuidCreate cannot create guid. {}", val.has_value() ? val.value() : L"");
} }
else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(& uuid_chars)) != RPC_S_OK) else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(& uuid_chars)) != RPC_S_OK)
{ {
auto val = get_last_error_message(GetLastError()); auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidToString can not convert to string. {}", val.has_value() ? val.value() : L""); Logger::warn(L"UuidToString cannot convert to string. {}", val.has_value() ? val.value() : L"");
} }
if (uuid_chars != nullptr) if (uuid_chars != nullptr)

Просмотреть файл

@ -8,7 +8,7 @@
#include <common/Telemetry/EtwTrace/EtwTrace.h> #include <common/Telemetry/EtwTrace/EtwTrace.h>
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms." #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of its single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif #endif
using namespace ATL; using namespace ATL;

Просмотреть файл

@ -430,7 +430,7 @@
<comment>Row as in horizontal rows in a table, and columns</comment> <comment>Row as in horizontal rows in a table, and columns</comment>
</data> </data>
<data name="ERRORMESSAGE_DISABLEASACTIONKEY" xml:space="preserve"> <data name="ERRORMESSAGE_DISABLEASACTIONKEY" xml:space="preserve">
<value>Disable can not be an action or a modifier key</value> <value>Disable cannot be an action or a modifier key</value>
<comment>Key on a keyboard</comment> <comment>Key on a keyboard</comment>
</data> </data>
<data name="EditShortcuts_SourceHeader" xml:space="preserve"> <data name="EditShortcuts_SourceHeader" xml:space="preserve">

Просмотреть файл

@ -139,7 +139,7 @@ namespace BufferValidationHelpers
} }
else if (selectedKeyCode == CommonSharedConstants::VK_DISABLED && dropDownIndex) else if (selectedKeyCode == CommonSharedConstants::VK_DISABLED && dropDownIndex)
{ {
// Disable can not be selected if one modifier key has already been selected // Disable cannot be selected if one modifier key has already been selected
errorType = ShortcutErrorType::ShortcutDisableAsActionKey; errorType = ShortcutErrorType::ShortcutDisableAsActionKey;
} }
// If none of the above, then the action key will be set // If none of the above, then the action key will be set

Просмотреть файл

@ -500,7 +500,7 @@ LRESULT CALLBACK EditKeyboardWindowProc(HWND hWnd, UINT messageCode, WPARAM wPar
} }
break; break;
default: default:
// If the Xaml Bridge object exists, then use it's message handler to handle keyboard focus operations // If the Xaml Bridge object exists, then use its message handler to handle keyboard focus operations
if (xamlBridgePtr != nullptr) if (xamlBridgePtr != nullptr)
{ {
return xamlBridgePtr->MessageHandler(messageCode, wParam, lParam); return xamlBridgePtr->MessageHandler(messageCode, wParam, lParam);

Просмотреть файл

@ -523,7 +523,7 @@ LRESULT CALLBACK EditShortcutsWindowProc(HWND hWnd, UINT messageCode, WPARAM wPa
} }
break; break;
default: default:
// If the Xaml Bridge object exists, then use it's message handler to handle keyboard focus operations // If the Xaml Bridge object exists, then use its message handler to handle keyboard focus operations
if (xamlBridgePtr != nullptr) if (xamlBridgePtr != nullptr)
{ {
return xamlBridgePtr->MessageHandler(messageCode, wParam, lParam); return xamlBridgePtr->MessageHandler(messageCode, wParam, lParam);

Просмотреть файл

@ -3,7 +3,7 @@
#include "targetver.h" #include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <unknwn.h> #include <Unknwn.h>
#include <windows.h> #include <windows.h>
#include <shellapi.h> #include <shellapi.h>

Просмотреть файл

@ -613,7 +613,7 @@ namespace KeyboardEventHandlers
if (!isAltRightKeyInvoked) if (!isAltRightKeyInvoked)
{ {
// Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate its own key message
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut), data->lParam->vkCode); Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut), data->lParam->vkCode);
} }
else else
@ -637,7 +637,7 @@ namespace KeyboardEventHandlers
// Ensures that after releasing both the action key and AltGr, Ctrl does not remain falsely pressed. // Ensures that after releasing both the action key and AltGr, Ctrl does not remain falsely pressed.
if (!isAltRightKeyInvoked) if (!isAltRightKeyInvoked)
{ {
// Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate its own key message
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode);
} }
else else
@ -1711,7 +1711,7 @@ namespace KeyboardEventHandlers
query_string = process_name; query_string = process_name;
it = state.appSpecificShortcutReMap.find(query_string); it = state.appSpecificShortcutReMap.find(query_string);
// If no entry is found, search for the process name without it's file extension // If no entry is found, search for the process name without its file extension
if (it == state.appSpecificShortcutReMap.end()) if (it == state.appSpecificShortcutReMap.end())
{ {
// Find index of the file extension // Find index of the file extension

Просмотреть файл

@ -338,7 +338,7 @@ namespace Helpers
return key; return key;
} }
// Function to sort a vector of shortcuts based on it's size // Function to sort a vector of shortcuts based on its size
void SortShortcutVectorBasedOnSize(std::vector<Shortcut>& shortcutVector) void SortShortcutVectorBasedOnSize(std::vector<Shortcut>& shortcutVector)
{ {
std::sort(shortcutVector.begin(), shortcutVector.end(), [](Shortcut first, Shortcut second) { std::sort(shortcutVector.begin(), shortcutVector.end(), [](Shortcut first, Shortcut second) {

Просмотреть файл

@ -52,6 +52,6 @@ namespace Helpers
// Function to filter the key codes for artificial key codes // Function to filter the key codes for artificial key codes
int32_t FilterArtificialKeys(const int32_t& key); int32_t FilterArtificialKeys(const int32_t& key);
// Function to sort a vector of shortcuts based on it's size // Function to sort a vector of shortcuts based on its size
void SortShortcutVectorBasedOnSize(std::vector<Shortcut>& shortcutVector); void SortShortcutVectorBasedOnSize(std::vector<Shortcut>& shortcutVector);
} }

Просмотреть файл

@ -21,7 +21,7 @@ std::vector<std::wstring> Shortcut::splitwstring(const std::wstring& input, wcha
return splittedStrings; return splittedStrings;
} }
// Constructor to initialize Shortcut from it's virtual key code string representation. // Constructor to initialize Shortcut from its virtual key code string representation.
Shortcut::Shortcut(const std::wstring& shortcutVK) : Shortcut::Shortcut(const std::wstring& shortcutVK) :
winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL) winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
{ {
@ -46,7 +46,7 @@ Shortcut::Shortcut(const DWORD key)
SetKey(key); SetKey(key);
} }
// Constructor to initialize Shortcut from it's virtual key code string representation. // Constructor to initialize Shortcut from its virtual key code string representation.
Shortcut::Shortcut(const std::wstring& shortcutVK, const DWORD secondKeyOfChord) : Shortcut::Shortcut(const std::wstring& shortcutVK, const DWORD secondKeyOfChord) :
winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL) winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
{ {

Просмотреть файл

@ -82,10 +82,10 @@ public:
// Constructor to initialize Shortcut from single key // Constructor to initialize Shortcut from single key
Shortcut(const DWORD key); Shortcut(const DWORD key);
// Constructor to initialize Shortcut from it's virtual key code string representation. // Constructor to initialize Shortcut from its virtual key code string representation.
Shortcut(const std::wstring& shortcutVK); Shortcut(const std::wstring& shortcutVK);
// Constructor to initialize Shortcut from it's virtual key code string representation. // Constructor to initialize Shortcut from its virtual key code string representation.
Shortcut(const std::wstring& shortcutVK, const DWORD _secondKeyOfChord); Shortcut(const std::wstring& shortcutVK, const DWORD _secondKeyOfChord);
// Constructor to initialize shortcut from a list of keys // Constructor to initialize shortcut from a list of keys

Просмотреть файл

@ -163,7 +163,7 @@ namespace Microsoft.Plugin.Indexer
}; };
r.ContextData = searchResult; r.ContextData = searchResult;
// If the result is a directory, then it's display should show a directory. // If the result is a directory, then its display should show a directory.
if (_fileSystem.Directory.Exists(path)) if (_fileSystem.Directory.Exists(path))
{ {
r.QueryTextDisplay = path; r.QueryTextDisplay = path;

Просмотреть файл

@ -252,10 +252,10 @@ namespace Microsoft.Plugin.Program.Programs
logoUri = LogoUriFromManifest(manifestApp); logoUri = LogoUriFromManifest(manifestApp);
Enabled = true; Enabled = true;
CanRunElevated = IfApplicationcanRunElevated(); CanRunElevated = IfApplicationCanRunElevated();
} }
private bool IfApplicationcanRunElevated() private bool IfApplicationCanRunElevated()
{ {
if (EntryPoint == "Windows.FullTrustApplication") if (EntryPoint == "Windows.FullTrustApplication")
{ {

Просмотреть файл

@ -132,7 +132,7 @@ namespace Microsoft.Plugin.Uri.UnitTests.UriHelper
// All following cases should be parsed as application URI // All following cases should be parsed as application URI
[DataRow("mailto:", true, null, "mailto:")] [DataRow("mailto:", true, null, "mailto:")]
[DataRow("mailto:/", false, null, null)] [DataRow("mailto:/", false, null, null)]
[DataRow("mailto:example@mail.com", true, null, "mailto:example@mail.com")] [DataRow("mailto:mail@example.com", true, null, "mailto:mail@example.com")]
[DataRow("ms-settings:", true, null, "ms-settings:")] [DataRow("ms-settings:", true, null, "ms-settings:")]
[DataRow("ms-settings:/", false, null, null)] [DataRow("ms-settings:/", false, null, null)]
[DataRow("ms-settings://", false, null, null)] [DataRow("ms-settings://", false, null, null)]

Просмотреть файл

@ -39,7 +39,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
{ {
if (!windowData.IsWindow) if (!windowData.IsWindow)
{ {
Log.Debug($"Can not close the window '{windowData.Title}' ({windowData.Hwnd}), because it doesn't exist.", typeof(ContextMenuHelper)); Log.Debug($"Cannot close the window '{windowData.Title}' ({windowData.Hwnd}), because it doesn't exist.", typeof(ContextMenuHelper));
return false; return false;
} }
@ -79,7 +79,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
// Validate process // Validate process
if (!window.IsWindow || !window.Process.DoesExist || !window.Process.Name.Equals(WindowProcess.GetProcessNameFromProcessID(window.Process.ProcessID), StringComparison.Ordinal)) if (!window.IsWindow || !window.Process.DoesExist || !window.Process.Name.Equals(WindowProcess.GetProcessNameFromProcessID(window.Process.ProcessID), StringComparison.Ordinal))
{ {
Log.Debug($"Can not kill process '{window.Process.Name}' ({window.Process.ProcessID}) of the window '{window.Title}' ({window.Hwnd}), because it doesn't exist.", typeof(ContextMenuHelper)); Log.Debug($"Cannot kill process '{window.Process.Name}' ({window.Process.ProcessID}) of the window '{window.Title}' ({window.Hwnd}), because it doesn't exist.", typeof(ContextMenuHelper));
return false; return false;
} }

Просмотреть файл

@ -363,7 +363,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
{ {
if (_handlesToProcessCache.Count > 7000) if (_handlesToProcessCache.Count > 7000)
{ {
Debug.Print("Clearing Process Cache because it's size is " + _handlesToProcessCache.Count); Debug.Print("Clearing Process Cache because its size is " + _handlesToProcessCache.Count);
_handlesToProcessCache.Clear(); _handlesToProcessCache.Clear();
} }
@ -381,7 +381,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
} }
else else
{ {
// For the dwm process we can not receive the name. This is no problem because the window isn't part of result list. // For the dwm process we cannot receive the name. This is no problem because the window isn't part of result list.
Log.Debug($"Invalid process {processId} ({processName}) for window handle {hWindow}.", typeof(Window)); Log.Debug($"Invalid process {processId} ({processName}) for window handle {hWindow}.", typeof(Window));
_handlesToProcessCache.Add(hWindow, new WindowProcess(0, 0, string.Empty)); _handlesToProcessCache.Add(hWindow, new WindowProcess(0, 0, string.Empty));
} }

Просмотреть файл

@ -203,7 +203,7 @@ namespace Microsoft.Plugin.WindowWalker.Components
} }
/// <summary> /// <summary>
/// Kills the process by it's id. If permissions are required, they will be requested. /// Kills the process by its id. If permissions are required, they will be requested.
/// </summary> /// </summary>
/// <param name="killProcessTree">Kill process and sub processes.</param> /// <param name="killProcessTree">Kill process and sub processes.</param>
internal void KillThisProcess(bool killProcessTree) internal void KillThisProcess(bool killProcessTree)

Просмотреть файл

@ -20,7 +20,7 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
internal string Label { get; set; } internal string Label { get; set; }
/// <summary> /// <summary>
/// Gets or sets an an alternative search tag that will be evaluated if label doesn't match. For example we like to show the era on searches for 'year' too. /// Gets or sets an alternative search tag that will be evaluated if label doesn't match. For example we like to show the era on searches for 'year' too.
/// </summary> /// </summary>
internal string AlternativeSearchTag { get; set; } internal string AlternativeSearchTag { get; set; }

Просмотреть файл

@ -15,7 +15,7 @@ using Stopwatch = Wox.Infrastructure.Stopwatch;
namespace PowerLauncher.Helper namespace PowerLauncher.Helper
{ {
/// <Note> /// <Note>
/// On Windows operating system the name of environment variables is case insensitive. This means if we have a user and machine variable with differences in their name casing (eg. test vs Test), the name casing from machine level is used and won't be overwritten by the user var. /// On Windows operating system the name of environment variables is case-insensitive. This means if we have a user and machine variable with differences in their name casing (eg. test vs Test), the name casing from machine level is used and won't be overwritten by the user var.
/// Example for Window's behavior: test=ValueMachine (Machine level) + TEST=ValueUser (User level) => test=ValueUser (merged) /// Example for Window's behavior: test=ValueMachine (Machine level) + TEST=ValueUser (User level) => test=ValueUser (merged)
/// To get the same behavior we use "StringComparer.OrdinalIgnoreCase" as compare property for the HashSet and Dictionaries where we merge machine and user variable names. /// To get the same behavior we use "StringComparer.OrdinalIgnoreCase" as compare property for the HashSet and Dictionaries where we merge machine and user variable names.
/// </Note> /// </Note>
@ -96,7 +96,7 @@ namespace PowerLauncher.Helper
// Determine deleted variables and add them with a "string.Empty" value as marker to the dictionary // Determine deleted variables and add them with a "string.Empty" value as marker to the dictionary
foreach (DictionaryEntry pVar in oldProcessEnvironment) foreach (DictionaryEntry pVar in oldProcessEnvironment)
{ {
// We must compare case insensitive (see dictionary assignment) to avoid false positives when the variable name has changed (Example: "path" -> "Path") // We must compare case-insensitive (see dictionary assignment) to avoid false positives when the variable name has changed (Example: "path" -> "Path")
if (!newEnvironment.ContainsKey((string)pVar.Key) & !_protectedProcessVariables.Contains((string)pVar.Key)) if (!newEnvironment.ContainsKey((string)pVar.Key) & !_protectedProcessVariables.Contains((string)pVar.Key))
{ {
newEnvironment.Add((string)pVar.Key, string.Empty); newEnvironment.Add((string)pVar.Key, string.Empty);
@ -107,7 +107,7 @@ namespace PowerLauncher.Helper
// Later we only like to recreate the changed ones // Later we only like to recreate the changed ones
foreach (string varName in newEnvironment.Keys.ToList()) foreach (string varName in newEnvironment.Keys.ToList())
{ {
// To be able to detect changed names correctly we have to compare case sensitive // To be able to detect changed names correctly we have to compare case-sensitive
if (oldProcessEnvironment.Contains(varName)) if (oldProcessEnvironment.Contains(varName))
{ {
if (oldProcessEnvironment[varName].Equals(newEnvironment[varName])) if (oldProcessEnvironment[varName].Equals(newEnvironment[varName]))
@ -155,7 +155,7 @@ namespace PowerLauncher.Helper
} }
catch (Exception ex) catch (Exception ex)
{ {
// The dotnet method "System.Environment.SetEnvironmentVariable" has it's own internal method to check the input parameters. Here we catch the exceptions that we don't check before updating the environment variable and log it to avoid crashes of PT Run. // The dotnet method "System.Environment.SetEnvironmentVariable" has its own internal method to check the input parameters. Here we catch the exceptions that we don't check before updating the environment variable and log it to avoid crashes of PT Run.
Log.Exception($"Unhandled exception while updating the environment variable [{kv.Key}] for the PT Run process. (The variable value has a length of [{varValueLength}].)", ex, typeof(PowerLauncher.Helper.EnvironmentHelper)); Log.Exception($"Unhandled exception while updating the environment variable [{kv.Key}] for the PT Run process. (The variable value has a length of [{varValueLength}].)", ex, typeof(PowerLauncher.Helper.EnvironmentHelper));
} }
} }
@ -189,7 +189,7 @@ namespace PowerLauncher.Helper
string uVarKey = (string)uVar.Key; string uVarKey = (string)uVar.Key;
string uVarValue = (string)uVar.Value; string uVarValue = (string)uVar.Value;
// The variable name of the path variable can be upper case, lower case ore mixed case. So we have to compare case insensitive. // The variable name of the path variable can be upper case, lower case ore mixed case. So we have to compare case-insensitive.
if (!uVarKey.Equals(PathVariableName, StringComparison.OrdinalIgnoreCase)) if (!uVarKey.Equals(PathVariableName, StringComparison.OrdinalIgnoreCase))
{ {
environment[uVarKey] = uVarValue; environment[uVarKey] = uVarValue;

Просмотреть файл

@ -617,7 +617,7 @@ namespace PowerLauncher
catch (ArgumentOutOfRangeException ex) catch (ArgumentOutOfRangeException ex)
{ {
// Due to virtualization being enabled for the listview, the layout system updates elements in a deferred manner using an algorithm that balances performance and concurrency. // Due to virtualization being enabled for the listview, the layout system updates elements in a deferred manner using an algorithm that balances performance and concurrency.
// Hence, there can be a situation where the element index that we want to scroll into view is out of range for it's parent control. // Hence, there can be a situation where the element index that we want to scroll into view is out of range for its parent control.
// To mitigate this we use the UpdateLayout function, which forces layout update to ensure that the parent element contains the latest properties. // To mitigate this we use the UpdateLayout function, which forces layout update to ensure that the parent element contains the latest properties.
// However, it has a performance impact and is therefore not called each time. // However, it has a performance impact and is therefore not called each time.
Log.Exception("The parent element layout is not updated yet", ex, GetType()); Log.Exception("The parent element layout is not updated yet", ex, GetType());

Просмотреть файл

@ -91,7 +91,7 @@ namespace Wox.Plugin.Common.VirtualDesktop.Helper
/// Method to update the list of Virtual Desktops from Registry /// Method to update the list of Virtual Desktops from Registry
/// The data in the registry are always up to date /// The data in the registry are always up to date
/// </summary> /// </summary>
/// <remarks>If we can not read from registry, we set the list/guid to empty values.</remarks> /// <remarks>If we cannot read from registry, we set the list/guid to empty values.</remarks>
public void UpdateDesktopList() public void UpdateDesktopList()
{ {
int userSessionId = Process.GetCurrentProcess().SessionId; int userSessionId = Process.GetCurrentProcess().SessionId;

Просмотреть файл

@ -223,7 +223,7 @@ namespace Wox.Plugin
{ {
if (Plugin == null) if (Plugin == null)
{ {
Log.Warn($"Can not initialize {Metadata.Name} plugin as it was not loaded", GetType()); Log.Warn($"Cannot initialize {Metadata.Name} plugin as it was not loaded", GetType());
return false; return false;
} }

Просмотреть файл

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

Просмотреть файл

@ -218,12 +218,12 @@ private:
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS) if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
{ {
auto val = get_last_error_message(GetLastError()); auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidCreate can not create guid. {}", val.has_value() ? val.value() : L""); Logger::warn(L"UuidCreate cannot create guid. {}", val.has_value() ? val.value() : L"");
} }
else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(& uuid_chars)) != RPC_S_OK) else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(& uuid_chars)) != RPC_S_OK)
{ {
auto val = get_last_error_message(GetLastError()); auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidToString can not convert to string. {}", val.has_value() ? val.value() : L""); Logger::warn(L"UuidToString cannot convert to string. {}", val.has_value() ? val.value() : L"");
} }
if (uuid_chars != nullptr) if (uuid_chars != nullptr)

Просмотреть файл

@ -3,10 +3,10 @@
#define NOMINMAX #define NOMINMAX
#include <windows.h> #include <windows.h>
#include <unknwn.h> #include <Unknwn.h>
#include <restrictederrorinfo.h> #include <restrictederrorinfo.h>
#include <hstring.h> #include <hstring.h>
#include <unknwn.h> #include <Unknwn.h>
// Undefine GetCurrentTime macro to prevent // Undefine GetCurrentTime macro to prevent
// conflict with Storyboard::GetCurrentTime // conflict with Storyboard::GetCurrentTime

Просмотреть файл

@ -8,7 +8,7 @@
#include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h> #include <winrt/Windows.Foundation.Collections.h>
#include <windows.h> #include <windows.h>
#include <unknwn.h> #include <Unknwn.h>
#include <shlwapi.h> #include <shlwapi.h>
#include <atlbase.h> #include <atlbase.h>
#include <atlcom.h> #include <atlcom.h>

Просмотреть файл

@ -19,7 +19,7 @@ To add a new Previewer update the `Product.wxs` file in `PowerToysSetup` similar
**[Important] This method of registering Preview Handler DLL's is not recommended. It could lead to registry corruption.** **[Important] This method of registering Preview Handler DLL's is not recommended. It could lead to registry corruption.**
#### Registering Preview Handler #### Registering Preview Handler
1. Restart Visual studio as administrator. 1. Restart Visual studio as administrator.
2. Sign `XYZPreviewHandler` and it's dependencies. To sign an assembly in VS, follow steps given [here](https://learn.microsoft.com/dotnet/standard/assembly/sign-strong-name#create-and-sign-an-assembly-with-a-strong-name-by-using-visual-studio). 2. Sign `XYZPreviewHandler` and its dependencies. To sign an assembly in VS, follow steps given [Create and sign an assembly with a strong name by using Visual Studio](https://learn.microsoft.com/en-us/dotnet/standard/assembly/sign-strong-name#create-and-sign-an-assembly-with-a-strong-name-by-using-visual-studio).
3. Build `XYZPreviewHandler` project. 3. Build `XYZPreviewHandler` project.
4. Open developer command prompt from `Tools > Command Line > Developer Command Prompt`. 4. Open developer command prompt from `Tools > Command Line > Developer Command Prompt`.
5. Run following command for each nuget and project dependency to add them to Global Assembly Cache(GAC). 5. Run following command for each nuget and project dependency to add them to Global Assembly Cache(GAC).

Просмотреть файл

@ -52,9 +52,9 @@ STRINGTABLE
BEGIN BEGIN
IDS_EXPLR_ICONS_PREV_STTNGS_GROUP_HEADER_ID L"EXPLR_ICONS_PREV_STTNGS_GROUP_HEADER_ID" IDS_EXPLR_ICONS_PREV_STTNGS_GROUP_HEADER_ID L"EXPLR_ICONS_PREV_STTNGS_GROUP_HEADER_ID"
IDS_PRVPANE_FILE_PREV_STTNGS_GROUP_HEADER_ID L"PRVPANE_FILE_PREV_STTNGS_GROUP_HEADER_ID" IDS_PRVPANE_FILE_PREV_STTNGS_GROUP_HEADER_ID L"PRVPANE_FILE_PREV_STTNGS_GROUP_HEADER_ID"
IDS_PREVPANE_MD_BOOL_TOGGLE_CONTROLL L"PREVPANE_MD_BOOL_TOGGLE_CONTROLL_ID" IDS_PREVPANE_MD_BOOL_TOGGLE_CONTROL L"PREVPANE_MD_BOOL_TOGGLE_CONTROLL_ID"
IDS_PREVPANE_SVG_BOOL_TOGGLE_CONTROLL L"IDS_PREVPANE_SVG_BOOL_TOGGLE_CONTROLL" IDS_PREVPANE_SVG_BOOL_TOGGLE_CONTROL L"IDS_PREVPANE_SVG_BOOL_TOGGLE_CONTROL"
IDS_EXPLR_SVG_BOOL_TOGGLE_CONTROLL L"EXPLR_SVG_BOOL_TOGGLE_CONTROLL" IDS_EXPLR_SVG_BOOL_TOGGLE_CONTROL L"EXPLR_SVG_BOOL_TOGGLE_CONTROLL"
END END
// Non-localizable // Non-localizable

Просмотреть файл

@ -10,9 +10,9 @@
#define ORIGINAL_FILENAME "PowerToys.powerpreview.dll" #define ORIGINAL_FILENAME "PowerToys.powerpreview.dll"
#define IDS_EXPLR_ICONS_PREV_STTNGS_GROUP_HEADER_ID 1001 #define IDS_EXPLR_ICONS_PREV_STTNGS_GROUP_HEADER_ID 1001
#define IDS_PRVPANE_FILE_PREV_STTNGS_GROUP_HEADER_ID 1002 #define IDS_PRVPANE_FILE_PREV_STTNGS_GROUP_HEADER_ID 1002
#define IDS_PREVPANE_MD_BOOL_TOGGLE_CONTROLL 1003 #define IDS_PREVPANE_MD_BOOL_TOGGLE_CONTROL 1003
#define IDS_PREVPANE_SVG_BOOL_TOGGLE_CONTROLL 1004 #define IDS_PREVPANE_SVG_BOOL_TOGGLE_CONTROL 1004
#define IDS_EXPLR_SVG_BOOL_TOGGLE_CONTROLL 1005 #define IDS_EXPLR_SVG_BOOL_TOGGLE_CONTROL 1005
// Non-localizable // Non-localizable
////////////////////////////// //////////////////////////////

Просмотреть файл

@ -196,7 +196,7 @@ namespace RegistryPreviewUILib
return false; return false;
} }
// REG files have to start with one of two headers and it's case insensitive // REG files have to start with one of two headers and it's case-insensitive
registryLine = registryLines[0]; registryLine = registryLines[0];
registryLine = registryLine.ToLowerInvariant(); registryLine = registryLine.ToLowerInvariant();
@ -232,7 +232,7 @@ namespace RegistryPreviewUILib
} }
else if (registryLine.StartsWith("@=", StringComparison.InvariantCulture)) else if (registryLine.StartsWith("@=", StringComparison.InvariantCulture))
{ {
// This is the a Value called "(Default)" so we tweak the line for the UX // This is the Value called "(Default)" so we tweak the line for the UX
registryLine = registryLine.Replace("@=", "\"(Default)\"="); registryLine = registryLine.Replace("@=", "\"(Default)\"=");
} }

Просмотреть файл

@ -132,7 +132,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
} }.detach(); } }.detach();
chdir_current_executable(); chdir_current_executable();
// Load Powertoys DLLs // Load PowerToys DLLs
std::vector<std::wstring_view> knownModules = { std::vector<std::wstring_view> knownModules = {
L"PowerToys.FancyZonesModuleInterface.dll", L"PowerToys.FancyZonesModuleInterface.dll",

Просмотреть файл

@ -93,7 +93,7 @@ std::optional<std::wstring> dispatch_json_action_to_module(const json::JsonObjec
else if (action == L"restart_maintain_elevation") else if (action == L"restart_maintain_elevation")
{ {
// this was added to restart and maintain elevation, which is needed after settings are change from outside the normal process. // this was added to restart and maintain elevation, which is needed after settings are change from outside the normal process.
// since a normal PostQuitMessage(0) would usually cause this process to save it's in memory settings to disk, we need to // since a normal PostQuitMessage(0) would usually cause this process to save its in memory settings to disk, we need to
// send a PostQuitMessage(1) and check for that on exit, and skip the settings-flush. // send a PostQuitMessage(1) and check for that on exit, and skip the settings-flush.
auto loaded = PTSettingsHelper::load_general_settings(); auto loaded = PTSettingsHelper::load_general_settings();
@ -348,12 +348,12 @@ void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::op
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS) if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
{ {
auto val = get_last_error_message(GetLastError()); auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidCreate can not create guid. {}", val.has_value() ? val.value() : L""); Logger::warn(L"UuidCreate cannot create guid. {}", val.has_value() ? val.value() : L"");
} }
else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(&uuid_chars)) != RPC_S_OK) else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(&uuid_chars)) != RPC_S_OK)
{ {
auto val = get_last_error_message(GetLastError()); auto val = get_last_error_message(GetLastError());
Logger::warn(L"UuidToString can not convert to string. {}", val.has_value() ? val.value() : L""); Logger::warn(L"UuidToString cannot convert to string. {}", val.has_value() ? val.value() : L"");
} }
if (uuid_chars != nullptr) if (uuid_chars != nullptr)

Просмотреть файл

@ -281,7 +281,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
return (string.IsNullOrEmpty(NewRemapString) || NewRemapString == "*Unsupported*") ? MapKeys(NewRemapKeys) : new List<string> { NewRemapString }; return (string.IsNullOrEmpty(NewRemapString) || NewRemapString == "*Unsupported*") ? MapKeys(NewRemapKeys) : new List<string> { NewRemapString };
} }
// Instead of doing something fancy pants, we 'll just display the RunProgramFilePath data when it's IsRunProgram // Instead of doing something fancy pants, we'll just display the RunProgramFilePath data when it's IsRunProgram
// It truncates the start of the program to run, if it's long and truncates the end of the args if it's long // It truncates the start of the program to run, if it's long and truncates the end of the args if it's long
// e.g.: c:\MyCool\PathIs\Long\software.exe myArg1 myArg2 myArg3 -> (something like) "...ng\software.exe myArg1..." // e.g.: c:\MyCool\PathIs\Long\software.exe myArg1 myArg2 myArg3 -> (something like) "...ng\software.exe myArg1..."
// the idea is you get the most important part of the program to run and some of the args in case that the only thing thats different, // the idea is you get the most important part of the program to run and some of the args in case that the only thing thats different,

Просмотреть файл

@ -43,7 +43,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private void OnConfigFileUpdate() private void OnConfigFileUpdate()
{ {
// Note: FileSystemWatcher raise notification multiple times for single update operation. // Note: FileSystemWatcher raise notification multiple times for single update operation.
// Todo: Handle duplicate events either by somehow suppress them or re-read the configuration everytime since we will be updating the UI only if something is changed. // Todo: Handle duplicate events either by somehow suppress them or re-read the configuration every time since we will be updating the UI only if something is changed.
if (ViewModel.LoadProfile()) if (ViewModel.LoadProfile())
{ {
this.DispatcherQueue.TryEnqueue(() => this.DispatcherQueue.TryEnqueue(() =>

Просмотреть файл

@ -52,7 +52,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private void OnConfigFileUpdate() private void OnConfigFileUpdate()
{ {
// Note: FileSystemWatcher raise notification multiple times for single update operation. // Note: FileSystemWatcher raise notification multiple times for single update operation.
// Todo: Handle duplicate events either by somehow suppress them or re-read the configuration everytime since we will be updating the UI only if something is changed. // Todo: Handle duplicate events either by somehow suppress them or re-read the configuration every time since we will be updating the UI only if something is changed.
this.DispatcherQueue.TryEnqueue(() => this.DispatcherQueue.TryEnqueue(() =>
{ {
if (ViewModel.LoadUpdatedSettings()) if (ViewModel.LoadUpdatedSettings())

Просмотреть файл

@ -4579,7 +4579,7 @@ Activate by holding the key for the character you want to add an accent to, then
<value>Rules defined by your organization</value> <value>Rules defined by your organization</value>
</data> </data>
<data name="MouseWithoutBorders_PolicyIPAddressMappingInfo_TextBoxControl.Description" xml:space="preserve"> <data name="MouseWithoutBorders_PolicyIPAddressMappingInfo_TextBoxControl.Description" xml:space="preserve">
<value>You can not change, remove or disable these enforced rules.</value> <value>You cannot change, remove or disable these enforced rules.</value>
</data> </data>
<data name="OpenSettings.Content" xml:space="preserve"> <data name="OpenSettings.Content" xml:space="preserve">
<value>Open settings</value> <value>Open settings</value>

Просмотреть файл

@ -418,7 +418,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
InitializeEnabledValue(); InitializeEnabledValue();
InitializePolicyValues(); InitializePolicyValues();
// MouseWithoutBorders settings may be changed by the logic in the utility as machines connect. We need to get a fresh version everytime instead of using a repository. // MouseWithoutBorders settings may be changed by the logic in the utility as machines connect. We need to get a fresh version every time instead of using a repository.
MouseWithoutBordersSettings moduleSettings; MouseWithoutBordersSettings moduleSettings;
moduleSettings = SettingsUtils.GetSettingsOrDefault<MouseWithoutBordersSettings>("MouseWithoutBorders"); moduleSettings = SettingsUtils.GetSettingsOrDefault<MouseWithoutBordersSettings>("MouseWithoutBorders");

Просмотреть файл

@ -50,7 +50,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{ {
if (settings == null) if (settings == null)
{ {
throw new ArgumentException("settings argument can not be null"); throw new ArgumentException("settings argument cannot be null");
} }
this.settings = settings; this.settings = settings;

Просмотреть файл

@ -14,7 +14,7 @@ void ZipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath)
struct zip_t* zip = zip_open(tmpZipPath.string().c_str(), ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); struct zip_t* zip = zip_open(tmpZipPath.string().c_str(), ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
if (!zip) if (!zip)
{ {
printf("Can not open zip."); printf("Cannot open zip.");
throw -1; throw -1;
} }