mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-15 18:51:00 +00:00
Compare commits
135 Commits
dev/lhecke
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fefe2fd703 | ||
|
|
7f288414b7 | ||
|
|
be63f95a08 | ||
|
|
c53b71411c | ||
|
|
56f9d241d3 | ||
|
|
471034ba10 | ||
|
|
bb67c1b02c | ||
|
|
31d4345ea4 | ||
|
|
7d401e8293 | ||
|
|
843195cc89 | ||
|
|
83d4009589 | ||
|
|
2f1d2ea0d1 | ||
|
|
a7b0fdfbd2 | ||
|
|
0cd9b15451 | ||
|
|
fe4d276fd6 | ||
|
|
82b63c2574 | ||
|
|
c95552a8c1 | ||
|
|
ee6d3655bb | ||
|
|
dbc30ad741 | ||
|
|
152740676b | ||
|
|
bc860a9256 | ||
|
|
e1fccd8905 | ||
|
|
0d130a7397 | ||
|
|
a23423a98d | ||
|
|
b73718a42a | ||
|
|
4938b92a1c | ||
|
|
d19b96289a | ||
|
|
c0999305fc | ||
|
|
c518397fe9 | ||
|
|
5ed748c3bf | ||
|
|
5b474b6468 | ||
|
|
47ba4b2c3d | ||
|
|
9657a88820 | ||
|
|
b65ffdb281 | ||
|
|
785704f9b7 | ||
|
|
0fe29b7599 | ||
|
|
18e4a824cf | ||
|
|
c1729bcc09 | ||
|
|
e192d543ed | ||
|
|
2449f274bd | ||
|
|
8a9da742c8 | ||
|
|
cd367e6411 | ||
|
|
f29c3e3598 | ||
|
|
0dccbaca58 | ||
|
|
afdd628ac7 | ||
|
|
6b4a3e813d | ||
|
|
cfb8f66658 | ||
|
|
d2d3600855 | ||
|
|
ef7b8497e2 | ||
|
|
d3a66ff297 | ||
|
|
a9cf3d78f3 | ||
|
|
100dbc5038 | ||
|
|
e376f8c99f | ||
|
|
926c8e08e0 | ||
|
|
c82a577529 | ||
|
|
ce26137128 | ||
|
|
b150a98fc0 | ||
|
|
4af96a2133 | ||
|
|
47f1167af2 | ||
|
|
45310d77a8 | ||
|
|
3717fae714 | ||
|
|
9d0346c2b3 | ||
|
|
8876417f87 | ||
|
|
9310db572d | ||
|
|
9ec3e799ed | ||
|
|
73ea629c18 | ||
|
|
8f013d7ae8 | ||
|
|
c2c5f410f9 | ||
|
|
5e9147e994 | ||
|
|
b899d49a26 | ||
|
|
b73e39ce17 | ||
|
|
bccd97257e | ||
|
|
124058f276 | ||
|
|
c02bb296f5 | ||
|
|
37c159abba | ||
|
|
95a9d8c31b | ||
|
|
e682cdad5e | ||
|
|
6816620a6d | ||
|
|
1ef4a42762 | ||
|
|
2c341c8deb | ||
|
|
666c446bc3 | ||
|
|
276405a476 | ||
|
|
813286c523 | ||
|
|
bfd5248a2e | ||
|
|
fe0d57071e | ||
|
|
284d0456ae | ||
|
|
fecccaa257 | ||
|
|
81ac9765fc | ||
|
|
d11ea72639 | ||
|
|
a440e15744 | ||
|
|
7076613374 | ||
|
|
36f67d7627 | ||
|
|
a96a5b7e79 | ||
|
|
83aff8d6f0 | ||
|
|
cbbd1e8699 | ||
|
|
11e7bbc1f3 | ||
|
|
f499e4df9d | ||
|
|
0b1b7e673b | ||
|
|
f07b9e195e | ||
|
|
3ae67a9b68 | ||
|
|
12122b2bf9 | ||
|
|
a85d9e69ed | ||
|
|
19b6d351a5 | ||
|
|
76a5ff143e | ||
|
|
0ca1356859 | ||
|
|
7e47f6aab9 | ||
|
|
deb5e7c650 | ||
|
|
623a59ecaa | ||
|
|
4488a25971 | ||
|
|
b4ada09776 | ||
|
|
94339c10e5 | ||
|
|
3d36017ee1 | ||
|
|
3ab859b8d1 | ||
|
|
4f3afee728 | ||
|
|
70313db246 | ||
|
|
2dedc9af7f | ||
|
|
c12987af41 | ||
|
|
64bcc0bd25 | ||
|
|
f58240c9c0 | ||
|
|
14919073a1 | ||
|
|
9f9f5de78d | ||
|
|
21adb804fa | ||
|
|
8ba43f9fcb | ||
|
|
1e18ab9442 | ||
|
|
8cf56971f6 | ||
|
|
fed9b0044d | ||
|
|
23e4d313d5 | ||
|
|
96eeac10c2 | ||
|
|
1b3d004782 | ||
|
|
ed800dc72d | ||
|
|
ea0482345b | ||
|
|
8721573957 | ||
|
|
a43d5028b1 | ||
|
|
751db3d114 | ||
|
|
a161307c84 |
1
.github/actions/spelling/README.md
vendored
1
.github/actions/spelling/README.md
vendored
@@ -6,6 +6,7 @@ File | Purpose | Format | Info
|
||||
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
|
||||
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
|
||||
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
|
||||
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
|
||||
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)
|
||||
|
||||
2
.github/actions/spelling/advice.md
vendored
2
.github/actions/spelling/advice.md
vendored
@@ -21,7 +21,7 @@ See the `README.md` in each directory for more information.
|
||||
:microscope: You can test your commits **without** *appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
|
||||
|
||||
|
||||
<details><summary>:clamp: If the flagged items are false positives</summary>
|
||||
<details><summary>If the flagged items are :exploding_head: false positives</summary>
|
||||
|
||||
If items relate to a ...
|
||||
* binary file (or some other file you wouldn't want to check at all).
|
||||
|
||||
12
.github/actions/spelling/allow/allow.txt
vendored
12
.github/actions/spelling/allow/allow.txt
vendored
@@ -1,7 +1,7 @@
|
||||
admins
|
||||
allcolors
|
||||
apc
|
||||
Apc
|
||||
apc
|
||||
breadcrumb
|
||||
breadcrumbs
|
||||
bsd
|
||||
@@ -14,8 +14,8 @@ CMMI
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
dcs
|
||||
Dcs
|
||||
dcs
|
||||
dialytika
|
||||
dje
|
||||
downside
|
||||
@@ -34,10 +34,12 @@ gantt
|
||||
gcc
|
||||
geeksforgeeks
|
||||
ghe
|
||||
github
|
||||
gje
|
||||
godbolt
|
||||
hostname
|
||||
hostnames
|
||||
https
|
||||
hyperlink
|
||||
hyperlinking
|
||||
hyperlinks
|
||||
@@ -54,9 +56,11 @@ Llast
|
||||
llvm
|
||||
Lmid
|
||||
locl
|
||||
lol
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
minimalistic
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
@@ -80,6 +84,7 @@ runtimes
|
||||
shcha
|
||||
slnt
|
||||
Sos
|
||||
ssh
|
||||
timeline
|
||||
timelines
|
||||
timestamped
|
||||
@@ -88,6 +93,7 @@ tokenizes
|
||||
tonos
|
||||
toolset
|
||||
tshe
|
||||
ubuntu
|
||||
uiatextrange
|
||||
UIs
|
||||
und
|
||||
@@ -96,5 +102,7 @@ versioned
|
||||
vsdevcmd
|
||||
We'd
|
||||
wildcards
|
||||
XBox
|
||||
YBox
|
||||
yeru
|
||||
zhe
|
||||
|
||||
12
.github/actions/spelling/allow/apis.txt
vendored
12
.github/actions/spelling/allow/apis.txt
vendored
@@ -32,10 +32,10 @@ DERR
|
||||
dlldata
|
||||
DNE
|
||||
DONTADDTORECENT
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
DWMSBT
|
||||
DWMWA
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
endfor
|
||||
ENDSESSION
|
||||
enumset
|
||||
@@ -92,6 +92,7 @@ istream
|
||||
IStringable
|
||||
ITab
|
||||
ITaskbar
|
||||
itow
|
||||
IUri
|
||||
IVirtual
|
||||
KEYSELECT
|
||||
@@ -103,13 +104,14 @@ lround
|
||||
Lsa
|
||||
lsass
|
||||
LSHIFT
|
||||
LTGRAY
|
||||
MAINWINDOW
|
||||
memchr
|
||||
memicmp
|
||||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUITEMINFOW
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
mmeapi
|
||||
MOUSELEAVE
|
||||
mov
|
||||
@@ -146,6 +148,7 @@ OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PATINVERT
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
@@ -155,8 +158,8 @@ rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
roundf
|
||||
ROOTOWNER
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
schandle
|
||||
@@ -208,6 +211,7 @@ UPDATEINIFILE
|
||||
userenv
|
||||
USEROBJECTFLAGS
|
||||
Viewbox
|
||||
virtualalloc
|
||||
wcsstr
|
||||
wcstoui
|
||||
winmain
|
||||
|
||||
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
@@ -0,0 +1,523 @@
|
||||
# marker to ignore all code on line
|
||||
^.*/\* #no-spell-check-line \*/.*$
|
||||
# marker for ignoring a comment to the end of the line
|
||||
// #no-spell-check.*$
|
||||
|
||||
# patch hunk comments
|
||||
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
|
||||
# git index header
|
||||
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
|
||||
# cid urls
|
||||
(['"])cid:.*?\g{-1}
|
||||
|
||||
# data url in parens
|
||||
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
|
||||
# data url in quotes
|
||||
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
|
||||
# data url
|
||||
data:[-a-zA-Z=;:/0-9+]*,\S*
|
||||
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# magnet urls
|
||||
magnet:[?=:\w]+
|
||||
|
||||
# magnet urls
|
||||
"magnet:[^"]+"
|
||||
|
||||
# obs:
|
||||
"obs:[^"]*"
|
||||
|
||||
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
|
||||
# In this examples content, I'm using a number of different ways to match things to show various approaches
|
||||
# asciinema
|
||||
\basciinema\.org/a/[0-9a-zA-Z]+
|
||||
|
||||
# apple
|
||||
\bdeveloper\.apple\.com/[-\w?=/]+
|
||||
# Apple music
|
||||
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
|
||||
|
||||
# appveyor api
|
||||
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
|
||||
# appveyor project
|
||||
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
|
||||
|
||||
# Amazon
|
||||
|
||||
# Amazon
|
||||
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
|
||||
# AWS S3
|
||||
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS execute-api
|
||||
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
|
||||
# AWS ELB
|
||||
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
|
||||
# AWS SNS
|
||||
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS VPC
|
||||
vpc-\w+
|
||||
|
||||
# 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?&=_%]*
|
||||
# YouTube music
|
||||
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
|
||||
# YouTube tag
|
||||
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
|
||||
# YouTube image
|
||||
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
|
||||
# Google Accounts
|
||||
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
|
||||
# Google Analytics
|
||||
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
|
||||
# Google APIs
|
||||
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
|
||||
# Google Storage
|
||||
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
|
||||
# Google Calendar
|
||||
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
|
||||
\w+\@group\.calendar\.google\.com\b
|
||||
# Google DataStudio
|
||||
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
|
||||
# The leading `/` here is as opposed to the `\b` above
|
||||
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
|
||||
# Google Docs
|
||||
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
|
||||
# Google Drive
|
||||
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
|
||||
# Google Groups
|
||||
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
|
||||
# Google Maps
|
||||
\bmaps\.google\.com/maps\?[\w&;=]*
|
||||
# Google themes
|
||||
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||
# Google CDN
|
||||
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
|
||||
# Goo.gl
|
||||
/goo\.gl/[a-zA-Z0-9]+
|
||||
# Google Chrome Store
|
||||
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
|
||||
# Google Books
|
||||
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
|
||||
# Google Fonts
|
||||
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
|
||||
# Google Forms
|
||||
\bforms\.gle/\w+
|
||||
# Google Scholar
|
||||
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
|
||||
# Google Colab Research Drive
|
||||
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
|
||||
|
||||
# GitHub SHAs (api)
|
||||
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
|
||||
# GitHub SHAs (markdown)
|
||||
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
|
||||
# GitHub SHAs
|
||||
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
|
||||
# GitHub wiki
|
||||
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
|
||||
# githubusercontent
|
||||
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
||||
# githubassets
|
||||
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
|
||||
# gist github
|
||||
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
|
||||
# git.io
|
||||
\bgit\.io/[0-9a-zA-Z]+
|
||||
# GitHub JSON
|
||||
"node_id": "[-a-zA-Z=;:/0-9+]*"
|
||||
# Contributor
|
||||
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
|
||||
# GHSA
|
||||
GHSA(?:-[0-9a-z]{4}){3}
|
||||
|
||||
# GitLab commit
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
|
||||
# GitLab merge requests
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
|
||||
# GitLab uploads
|
||||
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
|
||||
# GitLab commits
|
||||
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
|
||||
|
||||
# binanace
|
||||
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
|
||||
# bitbucket diff
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
|
||||
# bitbucket repositories commits
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
# bitbucket commits
|
||||
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
|
||||
# bit.ly
|
||||
\bbit\.ly/\w+
|
||||
|
||||
# bitrise
|
||||
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
|
||||
|
||||
# bootstrapcdn.com
|
||||
\bbootstrapcdn\.com/[-./\w]+
|
||||
|
||||
# cdn.cloudflare.com
|
||||
\bcdnjs\.cloudflare\.com/[./\w]+
|
||||
|
||||
# circleci
|
||||
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
|
||||
|
||||
# gitter
|
||||
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
|
||||
|
||||
# gravatar
|
||||
\bgravatar\.com/avatar/[0-9a-f]+
|
||||
|
||||
# ibm
|
||||
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
|
||||
|
||||
# imgur
|
||||
\bimgur\.com/[^.]+
|
||||
|
||||
# Internet Archive
|
||||
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
|
||||
|
||||
# discord
|
||||
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
|
||||
|
||||
# Disqus
|
||||
\bdisqus\.com/[-\w/%.()!?&=_]*
|
||||
|
||||
# medium link
|
||||
\blink\.medium\.com/[a-zA-Z0-9]+
|
||||
# medium
|
||||
\bmedium\.com/\@?[^/\s"]+/[-\w]+
|
||||
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||
# powerbi
|
||||
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
|
||||
# vs devops
|
||||
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
|
||||
# microsoft store
|
||||
\bmicrosoft\.com/store/apps/\w+
|
||||
|
||||
# mvnrepository.com
|
||||
\bmvnrepository\.com/[-0-9a-z./]+
|
||||
|
||||
# now.sh
|
||||
/[0-9a-z-.]+\.now\.sh\b
|
||||
|
||||
# oracle
|
||||
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
|
||||
|
||||
# chromatic.com
|
||||
/\S+.chromatic.com\S*[")]
|
||||
|
||||
# codacy
|
||||
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
|
||||
|
||||
# compai
|
||||
\bcompai\.pub/v1/png/[0-9a-f]+
|
||||
|
||||
# mailgun api
|
||||
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
|
||||
# mailgun
|
||||
\b[0-9a-z]+.mailgun.org
|
||||
|
||||
# /message-id/
|
||||
/message-id/[-\w@./%]+
|
||||
|
||||
# Reddit
|
||||
\breddit\.com/r/[/\w_]*
|
||||
|
||||
# requestb.in
|
||||
\brequestb\.in/[0-9a-z]+
|
||||
|
||||
# sched
|
||||
\b[a-z0-9]+\.sched\.com\b
|
||||
|
||||
# Slack url
|
||||
slack://[a-zA-Z0-9?&=]+
|
||||
# Slack
|
||||
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
|
||||
# Slack edge
|
||||
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
|
||||
# Slack images
|
||||
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
|
||||
|
||||
# shields.io
|
||||
\bshields\.io/[-\w/%?=&.:+;,]*
|
||||
|
||||
# stackexchange -- https://stackexchange.com/feeds/sites
|
||||
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
|
||||
|
||||
# Sentry
|
||||
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
|
||||
|
||||
# Twitter markdown
|
||||
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
|
||||
# Twitter hashtag
|
||||
\btwitter\.com/hashtag/[\w?_=&]*
|
||||
# Twitter status
|
||||
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
|
||||
# Twitter profile images
|
||||
\btwimg\.com/profile_images/[_\w./]*
|
||||
# Twitter media
|
||||
\btwimg\.com/media/[-_\w./?=]*
|
||||
# Twitter link shortened
|
||||
\bt\.co/\w+
|
||||
|
||||
# facebook
|
||||
\bfburl\.com/[0-9a-z_]+
|
||||
# facebook CDN
|
||||
\bfbcdn\.net/[\w/.,]*
|
||||
# facebook watch
|
||||
\bfb\.watch/[0-9A-Za-z]+
|
||||
|
||||
# dropbox
|
||||
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
|
||||
|
||||
# ipfs protocol
|
||||
ipfs://[0-9a-z]*
|
||||
# ipfs url
|
||||
/ipfs/[0-9a-z]*
|
||||
|
||||
# w3
|
||||
\bw3\.org/[-0-9a-zA-Z/#.]+
|
||||
|
||||
# loom
|
||||
\bloom\.com/embed/[0-9a-f]+
|
||||
|
||||
# regex101
|
||||
\bregex101\.com/r/[^/\s"]+/\d+
|
||||
|
||||
# figma
|
||||
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
|
||||
|
||||
# freecodecamp.org
|
||||
\bfreecodecamp\.org/[-\w/.]+
|
||||
|
||||
# image.tmdb.org
|
||||
\bimage\.tmdb\.org/[/\w.]+
|
||||
|
||||
# mermaid
|
||||
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
|
||||
|
||||
# Wikipedia
|
||||
\ben\.wikipedia\.org/wiki/[-\w%.#]+
|
||||
|
||||
# gitweb
|
||||
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
|
||||
|
||||
# HyperKitty lists
|
||||
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
|
||||
|
||||
# lists
|
||||
/thread\.html/[^"\s]+
|
||||
|
||||
# list-management
|
||||
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
|
||||
|
||||
# kubectl.kubernetes.io/last-applied-configuration
|
||||
"kubectl.kubernetes.io/last-applied-configuration": ".*"
|
||||
|
||||
# pgp
|
||||
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
|
||||
|
||||
# Spotify
|
||||
\bopen\.spotify\.com/embed/playlist/\w+
|
||||
|
||||
# Mastodon
|
||||
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
|
||||
|
||||
# scastie
|
||||
\bscastie\.scala-lang\.org/[^/]+/\w+
|
||||
|
||||
# images.unsplash.com
|
||||
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
|
||||
|
||||
# pastebin
|
||||
\bpastebin\.com/[\w/]+
|
||||
|
||||
# heroku
|
||||
\b\w+\.heroku\.com/source/archive/\w+
|
||||
|
||||
# quip
|
||||
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
|
||||
|
||||
# badgen.net
|
||||
\bbadgen\.net/badge/[^")\]'\s]+
|
||||
|
||||
# statuspage.io
|
||||
\w+\.statuspage\.io\b
|
||||
|
||||
# media.giphy.com
|
||||
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
|
||||
|
||||
# tinyurl
|
||||
\btinyurl\.com/\w+
|
||||
|
||||
# getopts
|
||||
\bgetopts\s+(?:"[^"]+"|'[^']+')
|
||||
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# URL escaped characters
|
||||
\%[0-9A-F][A-F]
|
||||
# IPv6
|
||||
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
|
||||
# c99 hex digits (not the full format, just one I've seen)
|
||||
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
|
||||
# Punycode
|
||||
\bxn--[-0-9a-z]+
|
||||
# sha
|
||||
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
|
||||
# sha-... -- uses a fancy capture
|
||||
(['"]|")[0-9a-f]{40,}\g{-1}
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
# hex in url queries
|
||||
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
|
||||
# ssh
|
||||
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
|
||||
|
||||
# PGP
|
||||
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
|
||||
# GPG keys
|
||||
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
|
||||
# Well known gpg keys
|
||||
.well-known/openpgpkey/[\w./]+
|
||||
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||
# integrity
|
||||
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
|
||||
|
||||
# https://www.gnu.org/software/groff/manual/groff.html
|
||||
# man troff content
|
||||
\\f[BCIPR]
|
||||
# '
|
||||
\\\(aq
|
||||
|
||||
# .desktop mime types
|
||||
^MimeTypes?=.*$
|
||||
# .desktop localized entries
|
||||
^[A-Z][a-z]+\[[a-z]+\]=.*$
|
||||
# Localized .desktop content
|
||||
Name\[[^\]]+\]=.*
|
||||
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# crypt
|
||||
"\$2[ayb]\$.{56}"
|
||||
|
||||
# scrypt / argon
|
||||
\$(?:scrypt|argon\d+[di]*)\$\S+
|
||||
|
||||
# Input to GitHub JSON
|
||||
content: "[-a-zA-Z=;:/0-9+]*="
|
||||
|
||||
# Python stringprefix / binaryprefix
|
||||
# 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,})
|
||||
|
||||
# Regular expressions for (P|p)assword
|
||||
\([A-Z]\|[a-z]\)[a-z]+
|
||||
|
||||
# JavaScript regular expressions
|
||||
# javascript test regex
|
||||
/.*/[gim]*\.test\(
|
||||
# javascript match regex
|
||||
\.match\(/[^/\s"]*/[gim]*\s*
|
||||
# javascript match regex
|
||||
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
|
||||
# javascript regex
|
||||
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||
# javascript replace regex
|
||||
\.replace\(/[^/\s"]*/[gim]*\s*,
|
||||
|
||||
# Go regular expressions
|
||||
regexp?\.MustCompile\(`[^`]*`\)
|
||||
|
||||
# sed regular expressions
|
||||
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
|
||||
|
||||
# go install
|
||||
go install(?:\s+[a-z]+\.[-@\w/.]+)+
|
||||
|
||||
# kubernetes pod status lists
|
||||
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
|
||||
|
||||
# kubectl - pods in CrashLoopBackOff
|
||||
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
|
||||
|
||||
# kubernetes object suffix
|
||||
-[0-9a-f]{10}-\w{5}\s
|
||||
|
||||
# posthog secrets
|
||||
posthog\.init\((['"])phc_[^"',]+\g{-1},
|
||||
|
||||
# xcode
|
||||
|
||||
# xcodeproject scenes
|
||||
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
|
||||
|
||||
# xcode api botches
|
||||
customObjectInstantitationMethod
|
||||
|
||||
# font awesome classes
|
||||
\.fa-[-a-z0-9]+
|
||||
|
||||
# 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|[,.])*
|
||||
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
|
||||
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
|
||||
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
# Note that the next example is no longer necessary if you are using
|
||||
# to match a string starting with a `#`, use a character-class:
|
||||
[#]backwards
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
# Compiler flags (Scala)
|
||||
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
# Compiler flags
|
||||
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# Compiler flags (linker)
|
||||
,-B
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
# set arguments
|
||||
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
|
||||
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
|
||||
# macOS temp folders
|
||||
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/
|
||||
38
.github/actions/spelling/excludes.txt
vendored
38
.github/actions/spelling/excludes.txt
vendored
@@ -2,14 +2,14 @@
|
||||
(?:(?i)\.png$)
|
||||
(?:^|/)(?i)COPYRIGHT
|
||||
(?:^|/)(?i)LICEN[CS]E
|
||||
(?:^|/)3rdparty/
|
||||
(?:^|/)dirs$
|
||||
(?:^|/)go\.mod$
|
||||
(?:^|/)go\.sum$
|
||||
(?:^|/)package(?:-lock|)\.json$
|
||||
(?:^|/)sources(?:|\.dep)$
|
||||
(?:^|/)vendor/
|
||||
ignore$
|
||||
SUMS$
|
||||
\.a$
|
||||
\.ai$
|
||||
\.avi$
|
||||
\.bmp$
|
||||
@@ -20,6 +20,8 @@ SUMS$
|
||||
\.crt$
|
||||
\.csr$
|
||||
\.dll$
|
||||
\.docx?$
|
||||
\.drawio$
|
||||
\.DS_Store$
|
||||
\.eot$
|
||||
\.eps$
|
||||
@@ -31,6 +33,7 @@ SUMS$
|
||||
\.icns$
|
||||
\.ico$
|
||||
\.jar$
|
||||
\.jks$
|
||||
\.jpeg$
|
||||
\.jpg$
|
||||
\.key$
|
||||
@@ -41,6 +44,7 @@ SUMS$
|
||||
\.mod$
|
||||
\.mp3$
|
||||
\.mp4$
|
||||
\.o$
|
||||
\.ocf$
|
||||
\.otf$
|
||||
\.pbxproj$
|
||||
@@ -48,22 +52,41 @@ SUMS$
|
||||
\.pem$
|
||||
\.png$
|
||||
\.psd$
|
||||
\.pyc$
|
||||
\.runsettings$
|
||||
\.s$
|
||||
\.sig$
|
||||
\.so$
|
||||
\.svg$
|
||||
\.svgz$
|
||||
\.svgz?$
|
||||
\.tar$
|
||||
\.tgz$
|
||||
\.tiff?$
|
||||
\.ttf$
|
||||
\.vsdx$
|
||||
\.wav$
|
||||
\.webm$
|
||||
\.webp$
|
||||
\.woff
|
||||
\.woff2?$
|
||||
\.xcf$
|
||||
\.xls
|
||||
\.xlsx?$
|
||||
\.xpm$
|
||||
\.yml$
|
||||
\.zip$
|
||||
^\.github/actions/spelling/
|
||||
^\.github/fabricbot.json$
|
||||
^\.gitignore$
|
||||
^\Q.git-blame-ignore-revs\E$
|
||||
^\Q.github/workflows/spelling.yml\E$
|
||||
^\Qdoc/reference/windows-terminal-logo.ans\E$
|
||||
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
|
||||
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
|
||||
^\Qsrc/host/ft_host/chafa.txt\E$
|
||||
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
|
||||
^\XamlStyler.json$
|
||||
^build/config/
|
||||
^consolegit2gitfilters\.json$
|
||||
^dep/
|
||||
@@ -90,12 +113,5 @@ SUMS$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^tools/ReleaseEngineering/ServicingPipeline.ps1$
|
||||
^\.github/actions/spelling/
|
||||
^\.github/fabricbot.json$
|
||||
^\.gitignore$
|
||||
^\Q.github/workflows/spelling.yml\E$
|
||||
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
|
||||
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
|
||||
^\Qsrc/host/ft_host/chafa.txt\E$
|
||||
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
|
||||
^\XamlStyler.json$
|
||||
ignore$
|
||||
SUMS$
|
||||
|
||||
7
.github/actions/spelling/expect/alphabet.txt
vendored
7
.github/actions/spelling/expect/alphabet.txt
vendored
@@ -5,26 +5,19 @@ AAAAAABBBBBBCCC
|
||||
AAAAABBBBBBCCC
|
||||
abcd
|
||||
abcd
|
||||
abcde
|
||||
abcdef
|
||||
ABCDEFG
|
||||
ABCDEFGH
|
||||
ABCDEFGHIJ
|
||||
abcdefghijk
|
||||
ABCDEFGHIJKLMNO
|
||||
abcdefghijklmnop
|
||||
ABCDEFGHIJKLMNOPQRST
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
ABCG
|
||||
ABE
|
||||
abf
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
BBBBBBBBBBBBBBDDDD
|
||||
BBBBBCCC
|
||||
BBBBCCCCC
|
||||
BBGGRR
|
||||
CCE
|
||||
EFG
|
||||
EFGh
|
||||
QQQQQQQQQQABCDEFGHIJ
|
||||
|
||||
717
.github/actions/spelling/expect/expect.txt
vendored
717
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
2
.github/actions/spelling/expect/web.txt
vendored
2
.github/actions/spelling/expect/web.txt
vendored
@@ -1,5 +1,3 @@
|
||||
http
|
||||
www
|
||||
WCAG
|
||||
winui
|
||||
appshellintegration
|
||||
|
||||
30
.github/actions/spelling/line_forbidden.patterns
vendored
30
.github/actions/spelling/line_forbidden.patterns
vendored
@@ -1,3 +1,11 @@
|
||||
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
|
||||
# \bm_data\b
|
||||
|
||||
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
|
||||
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
|
||||
# to use this:
|
||||
#\bfit\(
|
||||
|
||||
# s.b. GitHub
|
||||
\bGithub\b
|
||||
|
||||
@@ -16,6 +24,12 @@
|
||||
# s.b. greater than
|
||||
\bgreater then\b
|
||||
|
||||
# s.b. into
|
||||
#\sin to\s
|
||||
|
||||
# s.b. opt-in
|
||||
\sopt in\s
|
||||
|
||||
# s.b. less than
|
||||
\bless then\b
|
||||
|
||||
@@ -27,10 +41,22 @@
|
||||
\b[Nn]o[nt][- ]existent\b
|
||||
|
||||
# s.b. preexisting
|
||||
[Pp]re-existing
|
||||
[Pp]re[- ]existing
|
||||
|
||||
# s.b. preempt
|
||||
[Pp]re[- ]empt\b
|
||||
|
||||
# s.b. preemptively
|
||||
[Pp]re-emptively
|
||||
[Pp]re[- ]emptively
|
||||
|
||||
# s.b. reentrancy
|
||||
[Rr]e[- ]entrancy
|
||||
|
||||
# s.b. reentrant
|
||||
[Rr]e[- ]entrant
|
||||
|
||||
# s.b. workaround(s)
|
||||
#\bwork[- ]arounds?\b
|
||||
|
||||
# Reject duplicate words
|
||||
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
|
||||
|
||||
57
.github/actions/spelling/patterns/patterns.txt
vendored
57
.github/actions/spelling/patterns/patterns.txt
vendored
@@ -27,13 +27,68 @@ ROY\sG\.\sBIV
|
||||
# Python stringprefix / binaryprefix
|
||||
\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)'
|
||||
|
||||
# Automatically suggested patterns
|
||||
# hit-count: 3831 file-count: 582
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# hit-count: 71 file-count: 35
|
||||
# Compiler flags
|
||||
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
|
||||
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# hit-count: 41 file-count: 28
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 20 file-count: 9
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
|
||||
# hit-count: 10 file-count: 7
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
|
||||
# hit-count: 4 file-count: 4
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# hit-count: 4 file-count: 1
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# 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}|u\d+)\b
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# acceptable duplicates
|
||||
# ls directory listings
|
||||
[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+
|
||||
# C/idl types + English ...
|
||||
\s(Guid|long|LONG|that) \g{-1}\s
|
||||
|
||||
# javadoc / .net
|
||||
(?:\@(?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
|
||||
(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
# Commit message -- Signed-off-by and friends
|
||||
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
|
||||
|
||||
# Autogenerated revert commit message
|
||||
^This reverts commit [0-9a-f]{40}\.$
|
||||
|
||||
# vtmode
|
||||
--vtmode\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
|
||||
27
.github/actions/spelling/reject.txt
vendored
27
.github/actions/spelling/reject.txt
vendored
@@ -1,31 +1,12 @@
|
||||
benefitting
|
||||
occurences?
|
||||
Sorce
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^oer$
|
||||
^spae$
|
||||
^spae-man$
|
||||
^spaebook$
|
||||
^spaecraft$
|
||||
^spaed$
|
||||
^spaedom$
|
||||
^spaeing$
|
||||
^spaeings$
|
||||
^spaeman$
|
||||
^spaer$
|
||||
^Spaerobee$
|
||||
^spaes$
|
||||
^spaewife$
|
||||
^spaewoman$
|
||||
^spaework$
|
||||
^spaewright$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether$
|
||||
^wether.*
|
||||
^wethers$
|
||||
^wetherteg$
|
||||
^[Ss]pae.*
|
||||
|
||||
106
.github/workflows/spelling2.yml
vendored
106
.github/workflows/spelling2.yml
vendored
@@ -1,10 +1,57 @@
|
||||
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
|
||||
name: Spell checking
|
||||
|
||||
# Comment management is handled through a secondary job, for details see:
|
||||
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
|
||||
#
|
||||
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# (in odd cases, it might actually run just to collapse a commment, but that's fairly rare)
|
||||
# it needs `contents: write` in order to add a comment.
|
||||
#
|
||||
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment)
|
||||
# it needs `pull-requests: write` in order to manipulate those comments.
|
||||
|
||||
# Updating pull request branches is managed via comment handling.
|
||||
# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list
|
||||
#
|
||||
# These elements work together to make it happen:
|
||||
#
|
||||
# `on.issue_comment`
|
||||
# This event listens to comments by users asking to update the metadata.
|
||||
#
|
||||
# `jobs.update`
|
||||
# This job runs in response to an issue_comment and will push a new commit
|
||||
# to update the spelling metadata.
|
||||
#
|
||||
# `with.experimental_apply_changes_via_bot`
|
||||
# Tells the action to support and generate messages that enable it
|
||||
# to make a commit to update the spelling metadata.
|
||||
#
|
||||
# `with.ssh_key`
|
||||
# In order to trigger workflows when the commit is made, you can provide a
|
||||
# secret (typically, a write-enabled github deploy key).
|
||||
#
|
||||
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
push:
|
||||
branches: ["**"]
|
||||
tags-ignore: ["**"]
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
pull_request_target:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
- 'synchronize'
|
||||
issue_comment:
|
||||
types:
|
||||
- 'created'
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
@@ -24,23 +71,64 @@ jobs:
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.20
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
suppress_push_for_open_pull_request: 1
|
||||
checkout: true
|
||||
check_file_names: 1
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
post_comment: 0
|
||||
use_magic_file: 1
|
||||
extra_dictionary_limit: 10
|
||||
extra_dictionaries:
|
||||
cspell:software-terms/src/software-terms.txt
|
||||
cspell:python/src/python/python-lib.txt
|
||||
cspell:node/node.txt
|
||||
cspell:cpp/src/stdlib-c.txt
|
||||
cspell:cpp/src/stdlib-cpp.txt
|
||||
cspell:fullstack/fullstack.txt
|
||||
cspell:filetypes/filetypes.txt
|
||||
cspell:html/html.txt
|
||||
cspell:cpp/src/compiler-msvc.txt
|
||||
cspell:python/src/common/extra.txt
|
||||
cspell:powershell/powershell.txt
|
||||
cspell:aws/aws.txt
|
||||
cspell:cpp/src/lang-keywords.txt
|
||||
cspell:npm/npm.txt
|
||||
cspell:dotnet/dotnet.txt
|
||||
cspell:python/src/python/python.txt
|
||||
cspell:css/css.txt
|
||||
cspell:cpp/src/stdlib-cmath.txt
|
||||
check_extra_dictionaries: ''
|
||||
|
||||
comment:
|
||||
name: Report
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
# If your workflow isn't running on push, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name != 'push'
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.20
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
comment-pr:
|
||||
name: Report (PR)
|
||||
# If you workflow isn't running on pull_request*, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
||||
"Microsoft.VisualStudio.Component.VC.Tools.ARM64",
|
||||
"Microsoft.VisualStudio.Component.VC.ASAN",
|
||||
"Microsoft.VisualStudio.Component.VC.v142.x86.x64",
|
||||
"Microsoft.VisualStudio.Component.VC.v142.ARM64",
|
||||
"Microsoft.VisualStudio.Component.VC.v143.x86.x64",
|
||||
"Microsoft.VisualStudio.Component.VC.v143.ARM64",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC.v142",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC.v143",
|
||||
"Microsoft.VisualStudio.Component.UWP.VC.ARM64"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ When you hit "New Issue", select the type of issue closest to what you want to r
|
||||
Microsoft Windows [Version 10.0.18900.1001]
|
||||
```
|
||||
|
||||
* What tools and apps you're using (e.g. VS 2019, VSCode, etc.)
|
||||
* What tools and apps you're using (e.g. VS 2022, VSCode, etc.)
|
||||
* Don't assume we're experts in setting up YOUR environment and don't assume we are experts in `<your distro/tool of choice>`. Teach us to help you!
|
||||
* **We LOVE detailed repro steps!** What steps do we need to take to reproduce the issue? Assume we love to read repro steps. As much detail as you can stand is probably _barely_ enough detail for us!
|
||||
* If you're reporting a particular character/glyph not rendering correctly, the specific Unicode codepoint would be MOST welcome (e.g. U+1F4AF, U+4382)
|
||||
|
||||
33
NOTICE.md
33
NOTICE.md
@@ -276,6 +276,39 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## wyhash
|
||||
|
||||
**Source**: [https://github.com/wangyi-fudan/wyhash](https://github.com/wangyi-fudan/wyhash)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
```
|
||||
|
||||
## ConEmu
|
||||
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)
|
||||
|
||||
|
||||
@@ -643,7 +643,8 @@ Global
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x64Test.Build.0 = Debug|x64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.Build.0 = Debug|x64
|
||||
@@ -661,7 +662,8 @@ Global
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x64Test.Build.0 = Release|x64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.ActiveCfg = Release|x64
|
||||
{DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|x64.Build.0 = Release|x64
|
||||
@@ -2308,7 +2310,8 @@ Global
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x64Test.Build.0 = Debug|x64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x64.Build.0 = Debug|x64
|
||||
@@ -2325,7 +2328,8 @@ Global
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x64Test.Build.0 = Release|x64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|x64.ActiveCfg = Release|x64
|
||||
{48D21369-3D7B-4431-9967-24E81292CF63}.Release|x64.Build.0 = Release|x64
|
||||
@@ -3313,7 +3317,8 @@ Global
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.Build.0 = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64
|
||||
@@ -3333,7 +3338,8 @@ Global
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.Build.0 = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64
|
||||
|
||||
@@ -177,7 +177,7 @@ While overhauling Windows Console, we modernized its codebase considerably,
|
||||
cleanly separating logical entities into modules and classes, introduced some
|
||||
key extensibility points, replaced several old, home-grown collections and
|
||||
containers with safer, more efficient [STL
|
||||
containers](https://docs.microsoft.com/en-us/cpp/standard-library/stl-containers?view=vs-2019),
|
||||
containers](https://docs.microsoft.com/en-us/cpp/standard-library/stl-containers?view=vs-2022),
|
||||
and made the code simpler and safer by using Microsoft's [Windows Implementation
|
||||
Libraries - WIL](https://github.com/Microsoft/wil).
|
||||
|
||||
@@ -293,14 +293,14 @@ If you would like to ask a question that you feel doesn't warrant an issue
|
||||
SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/)
|
||||
installed
|
||||
* You must have at least [VS
|
||||
2019](https://visualstudio.microsoft.com/downloads/) installed
|
||||
2022](https://visualstudio.microsoft.com/downloads/) installed
|
||||
* You must install the following Workloads via the VS Installer. Note: Opening
|
||||
the solution in VS 2019 will [prompt you to install missing components
|
||||
the solution in VS 2022 will [prompt you to install missing components
|
||||
automatically](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/):
|
||||
* Desktop Development with C++
|
||||
* Universal Windows Platform Development
|
||||
* **The following Individual Components**
|
||||
* C++ (v142) Universal Windows Platform Tools
|
||||
* C++ (v143) Universal Windows Platform Tools
|
||||
* You must install the [.NET Framework Targeting Pack](https://docs.microsoft.com/dotnet/framework/install/guide-for-developers#to-install-the-net-framework-developer-pack-or-targeting-pack) to build test projects
|
||||
|
||||
## Building the Code
|
||||
|
||||
117
build/config/ESRPSigning_Terminal.json
Normal file
117
build/config/ESRPSigning_Terminal.json
Normal file
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"Version": "1.0.0",
|
||||
"UseMinimatch": false,
|
||||
"SignBatches": [
|
||||
{
|
||||
"MatchedPath": [
|
||||
// Namespaced DLLs
|
||||
"Microsoft.Terminal.*.dll",
|
||||
"Microsoft.Terminal.*.winmd",
|
||||
|
||||
// ConPTY and DefTerm
|
||||
"OpenConsole.exe",
|
||||
"OpenConsoleProxy.dll",
|
||||
|
||||
// VCRT Forwarders
|
||||
"*_app.dll",
|
||||
|
||||
// Legacy DLLs with old names
|
||||
"TerminalApp.dll",
|
||||
"TerminalApp.winmd",
|
||||
"TerminalConnection.dll",
|
||||
"TerminalThemeHelpers.dll",
|
||||
"WindowsTerminalShellExt.dll",
|
||||
|
||||
// The rest
|
||||
"TerminalAzBridge.exe",
|
||||
"wt.exe",
|
||||
"WindowsTerminal.exe",
|
||||
"elevate-shim.exe"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-230012",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
// THIRD PARTY SOFTWARE
|
||||
"MatchedPath": [
|
||||
"cpprest*.dll"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
{
|
||||
"KeyCode": "CP-231522",
|
||||
"OperationSetCode": "SigntoolSign",
|
||||
"Parameters": [
|
||||
{
|
||||
"parameterName": "OpusName",
|
||||
"parameterValue": "Microsoft"
|
||||
},
|
||||
{
|
||||
"parameterName": "OpusInfo",
|
||||
"parameterValue": "http://www.microsoft.com"
|
||||
},
|
||||
{
|
||||
"parameterName": "FileDigest",
|
||||
"parameterValue": "/fd \"SHA256\""
|
||||
},
|
||||
{
|
||||
"parameterName": "PageHash",
|
||||
"parameterValue": "/NPH"
|
||||
},
|
||||
{
|
||||
"parameterName": "TimeStamp",
|
||||
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
}
|
||||
],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-231522",
|
||||
"OperationSetCode": "SigntoolVerify",
|
||||
"Parameters": [],
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"collection": "microsoft",
|
||||
"project": "OS",
|
||||
"repo": "os.2020",
|
||||
"name": "official/rs_wdx_dxp_windev",
|
||||
"name": "official/rs_we_adept_e4d2",
|
||||
"workitem": "38106206",
|
||||
"CheckinFiles": [
|
||||
{
|
||||
@@ -21,4 +21,4 @@
|
||||
"sendOnErrorOnly": "False"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
|
||||
<!-- This cannot be included in another project that depends on XAML (as it would be a duplicate package ID) -->
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.0" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
|
||||
<package id="Microsoft.Debugging.Tools.PdbStr" version="20220617.1556.0" targetFramework="native" />
|
||||
<package id="Microsoft.Debugging.Tools.SrcTool" version="20220617.1556.0" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Optional, defaults to main. Name of the branch which will be used for calculating branch point. -->
|
||||
<PGOBranch>main</PGOBranch>
|
||||
<PGOBranch>release-1.16</PGOBranch>
|
||||
|
||||
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
|
||||
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>
|
||||
|
||||
@@ -63,6 +63,7 @@ parameters:
|
||||
- Win11
|
||||
|
||||
variables:
|
||||
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
|
||||
TerminalInternalPackageVersion: "0.0.7"
|
||||
# If we are building a branch called "release-*", change the NuGet suffix
|
||||
# to "preview". If we don't do that, XES will set the suffix to "release1"
|
||||
@@ -270,6 +271,28 @@ jobs:
|
||||
displayName: 'Generate SBOM manifest'
|
||||
inputs:
|
||||
BuildDropPath: '$(System.ArtifactsDirectory)/appx'
|
||||
|
||||
- pwsh: |-
|
||||
$Package = (Get-ChildItem "$(Build.ArtifactStagingDirectory)/appx" -Recurse -Filter "Cascadia*.msix" | Select -First 1)
|
||||
$PackageFilename = $Package.FullName
|
||||
Write-Host "##vso[task.setvariable variable=WindowsTerminalPackagePath]${PackageFilename}"
|
||||
& "$(MakeAppxPath)" unpack /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
|
||||
displayName: Unpack the new Terminal package for signing
|
||||
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit Terminal's binaries for signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: '$(Build.SourcesDirectory)\UnpackedTerminalPackage'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(Build.SourcesDirectory)\build\config\ESRPSigning_Terminal.json'
|
||||
|
||||
- pwsh: |-
|
||||
$PackageFilename = "$(WindowsTerminalPackagePath)"
|
||||
Remove-Item "$(Build.SourcesDirectory)\UnpackedTerminalPackage\CodeSignSummary*"
|
||||
& "$(MakeAppxPath)" pack /h SHA256 /o /p $PackageFilename /d "$(Build.SourcesDirectory)\UnpackedTerminalPackage"
|
||||
displayName: Re-pack the new Terminal package after signing
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (appx)
|
||||
inputs:
|
||||
@@ -330,6 +353,13 @@ jobs:
|
||||
${{ windowsVersion }}:
|
||||
TerminalTargetWindowsVersion: ${{ windowsVersion }}
|
||||
displayName: Create and sign AppX/MSIX bundles
|
||||
variables:
|
||||
${{ if eq(parameters.branding, 'Release') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminal
|
||||
${{ elseif eq(parameters.branding, 'Preview') }}:
|
||||
BundleStemName: Microsoft.WindowsTerminalPreview
|
||||
${{ else }}:
|
||||
BundleStemName: WindowsTerminalDev
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -354,14 +384,15 @@ jobs:
|
||||
$Components = "$(XES_APPXMANIFESTVERSION)" -Split "\."
|
||||
$Components[0] = ([int]$Components[0] + $VersionEpoch)
|
||||
$BundleVersion = $Components -Join "."
|
||||
.\build\scripts\Create-AppxBundle.ps1 -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminal_$(TerminalTargetWindowsVersion)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
New-Item -Type Directory "$(System.ArtifactsDirectory)\bundle"
|
||||
.\build\scripts\Create-AppxBundle.ps1 -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion $BundleVersion -OutputPath "$(System.ArtifactsDirectory)\bundle\$(BundleStemName)_$(TerminalTargetWindowsVersion)_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
displayName: Create WindowsTerminal*.msixbundle
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.msixbundle to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(System.ArtifactsDirectory)
|
||||
Pattern: Microsoft.WindowsTerminal*.msixbundle
|
||||
FolderPath: $(System.ArtifactsDirectory)\bundle
|
||||
Pattern: $(BundleStemName)*.msixbundle
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
@@ -394,7 +425,7 @@ jobs:
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: appxbundle-signed'
|
||||
inputs:
|
||||
PathtoPublish: $(System.ArtifactsDirectory)
|
||||
PathtoPublish: $(System.ArtifactsDirectory)\bundle
|
||||
ArtifactName: appxbundle-signed-$(TerminalTargetWindowsVersion)
|
||||
|
||||
- ${{ if eq(parameters.buildConPTY, true) }}:
|
||||
@@ -700,6 +731,7 @@ jobs:
|
||||
description: VPack for the Windows Terminal Application
|
||||
pushPkgName: WindowsTerminal.app
|
||||
owner: conhost
|
||||
githubToken: $(GitHubTokenForVpackProvenance)
|
||||
- task: PublishPipelineArtifact@1
|
||||
displayName: 'Copy VPack Manifest to Drop'
|
||||
inputs:
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
|
||||
This version should be tracked in all project packages.config files for projects that depend on Xaml.
|
||||
-->
|
||||
<TerminalMUXVersion>2.7.2-prerelease.220406002</TerminalMUXVersion>
|
||||
<TerminalMUXVersion>2.7.3-prerelease.220816001</TerminalMUXVersion>
|
||||
<!--
|
||||
For the Windows 11-specific build, we're targeting the public version of Microsoft.UI.Xaml.
|
||||
This version emits a package dependency instead of embedding the dependency in our own package.
|
||||
|
||||
This version should be tracked in build/packages.config.
|
||||
-->
|
||||
<TerminalMUXVersion Condition="'$(TerminalTargetWindowsVersion)'=='Win11'">2.7.1</TerminalMUXVersion>
|
||||
<TerminalMUXVersion Condition="'$(TerminalTargetWindowsVersion)'=='Win11'">2.7.3</TerminalMUXVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/CLIUtils/CLI11",
|
||||
"commitHash": "dd0d8e4fe729e5b1110232c7a5c9566dad884686"
|
||||
}
|
||||
}
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/CLIUtils/CLI11",
|
||||
"commitHash": "5cb3efabce007c3a0230e4cc2e27da491c646b6c"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
[Amalgamated](https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated)
|
||||
from source commit
|
||||
[6aba23f](https://github.com/open-source-parsers/jsoncpp/commit/6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2),
|
||||
release 1.9.3.
|
||||
[5defb4e](https://github.com/open-source-parsers/jsoncpp/commit/5defb4ed1a4293b8e2bf641e16b156fb9de498cc),
|
||||
release 1.9.5.
|
||||
|
||||
> Generating amalgamated source and header JsonCpp is provided with a script to
|
||||
> generate a single header and a single source file to ease inclusion into an
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/open-source-parsers/jsoncpp",
|
||||
"commitHash": "6aba23f4a8628d599a9ef7fa4811c4ff6e4070e2"
|
||||
}
|
||||
}
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/open-source-parsers/jsoncpp",
|
||||
"commitHash": "5defb4ed1a4293b8e2bf641e16b156fb9de498cc"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -7,28 +7,28 @@
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
tests and demonstration applications, are licensed under the following
|
||||
conditions...
|
||||
|
||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
this software is released into the Public Domain.
|
||||
|
||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
||||
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
||||
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
Public Domain/MIT License conditions described here, as they choose.
|
||||
|
||||
The MIT License is about as close to Public Domain as a license can get, and is
|
||||
described in clear, concise terms at:
|
||||
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
|
||||
The full text of the MIT License follows:
|
||||
|
||||
========================================================================
|
||||
@@ -94,10 +94,10 @@ license you like.
|
||||
// 3. /CMakeLists.txt
|
||||
// IMPORTANT: also update the SOVERSION!!
|
||||
|
||||
#define JSONCPP_VERSION_STRING "1.9.3"
|
||||
#define JSONCPP_VERSION_STRING "1.9.5"
|
||||
#define JSONCPP_VERSION_MAJOR 1
|
||||
#define JSONCPP_VERSION_MINOR 9
|
||||
#define JSONCPP_VERSION_PATCH 3
|
||||
#define JSONCPP_VERSION_PATCH 5
|
||||
#define JSONCPP_VERSION_QUALIFIER
|
||||
#define JSONCPP_VERSION_HEXA \
|
||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||
@@ -162,11 +162,10 @@ public:
|
||||
* Release memory which was allocated for N items at pointer P.
|
||||
*
|
||||
* The memory block is filled with zeroes before being released.
|
||||
* The pointer argument is tagged as "volatile" to prevent the
|
||||
* compiler optimizing out this critical step.
|
||||
*/
|
||||
void deallocate(volatile pointer p, size_type n) {
|
||||
std::memset(p, 0, n * sizeof(T));
|
||||
void deallocate(pointer p, size_type n) {
|
||||
// memset_s is used because memset may be optimized away by the compiler
|
||||
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
||||
// free using "global operator delete"
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
@@ -6,28 +6,28 @@
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
tests and demonstration applications, are licensed under the following
|
||||
conditions...
|
||||
|
||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
this software is released into the Public Domain.
|
||||
|
||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
||||
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
||||
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
Public Domain/MIT License conditions described here, as they choose.
|
||||
|
||||
The MIT License is about as close to Public Domain as a license can get, and is
|
||||
described in clear, concise terms at:
|
||||
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
|
||||
The full text of the MIT License follows:
|
||||
|
||||
========================================================================
|
||||
@@ -93,10 +93,10 @@ license you like.
|
||||
// 3. /CMakeLists.txt
|
||||
// IMPORTANT: also update the SOVERSION!!
|
||||
|
||||
#define JSONCPP_VERSION_STRING "1.9.3"
|
||||
#define JSONCPP_VERSION_STRING "1.9.5"
|
||||
#define JSONCPP_VERSION_MAJOR 1
|
||||
#define JSONCPP_VERSION_MINOR 9
|
||||
#define JSONCPP_VERSION_PATCH 3
|
||||
#define JSONCPP_VERSION_PATCH 5
|
||||
#define JSONCPP_VERSION_QUALIFIER
|
||||
#define JSONCPP_VERSION_HEXA \
|
||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||
@@ -161,11 +161,10 @@ public:
|
||||
* Release memory which was allocated for N items at pointer P.
|
||||
*
|
||||
* The memory block is filled with zeroes before being released.
|
||||
* The pointer argument is tagged as "volatile" to prevent the
|
||||
* compiler optimizing out this critical step.
|
||||
*/
|
||||
void deallocate(volatile pointer p, size_type n) {
|
||||
std::memset(p, 0, n * sizeof(T));
|
||||
void deallocate(pointer p, size_type n) {
|
||||
// memset_s is used because memset may be optimized away by the compiler
|
||||
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
||||
// free using "global operator delete"
|
||||
::operator delete(p);
|
||||
}
|
||||
@@ -575,7 +574,7 @@ public:
|
||||
// be used by...
|
||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4251)
|
||||
#pragma warning(disable : 4251 4275)
|
||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||
|
||||
#pragma pack(push, 8)
|
||||
@@ -788,10 +787,10 @@ private:
|
||||
CZString(ArrayIndex index);
|
||||
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
||||
CZString(CZString const& other);
|
||||
CZString(CZString&& other);
|
||||
CZString(CZString&& other) noexcept;
|
||||
~CZString();
|
||||
CZString& operator=(const CZString& other);
|
||||
CZString& operator=(CZString&& other);
|
||||
CZString& operator=(CZString&& other) noexcept;
|
||||
|
||||
bool operator<(CZString const& other) const;
|
||||
bool operator==(CZString const& other) const;
|
||||
@@ -867,14 +866,15 @@ public:
|
||||
Value(const StaticString& value);
|
||||
Value(const String& value);
|
||||
Value(bool value);
|
||||
Value(std::nullptr_t ptr) = delete;
|
||||
Value(const Value& other);
|
||||
Value(Value&& other);
|
||||
Value(Value&& other) noexcept;
|
||||
~Value();
|
||||
|
||||
/// \note Overwrite existing comments. To preserve comments, use
|
||||
/// #swapPayload().
|
||||
Value& operator=(const Value& other);
|
||||
Value& operator=(Value&& other);
|
||||
Value& operator=(Value&& other) noexcept;
|
||||
|
||||
/// Swap everything.
|
||||
void swap(Value& other);
|
||||
@@ -1159,9 +1159,9 @@ private:
|
||||
public:
|
||||
Comments() = default;
|
||||
Comments(const Comments& that);
|
||||
Comments(Comments&& that);
|
||||
Comments(Comments&& that) noexcept;
|
||||
Comments& operator=(const Comments& that);
|
||||
Comments& operator=(Comments&& that);
|
||||
Comments& operator=(Comments&& that) noexcept;
|
||||
bool has(CommentPlacement slot) const;
|
||||
String get(CommentPlacement slot) const;
|
||||
void set(CommentPlacement slot, String comment);
|
||||
@@ -1442,8 +1442,8 @@ public:
|
||||
* because the returned references/pointers can be used
|
||||
* to change state of the base class.
|
||||
*/
|
||||
reference operator*() { return deref(); }
|
||||
pointer operator->() { return &deref(); }
|
||||
reference operator*() const { return const_cast<reference>(deref()); }
|
||||
pointer operator->() const { return const_cast<pointer>(&deref()); }
|
||||
};
|
||||
|
||||
inline void swap(Value& a, Value& b) { a.swap(b); }
|
||||
@@ -1506,8 +1506,7 @@ namespace Json {
|
||||
* \deprecated Use CharReader and CharReaderBuilder.
|
||||
*/
|
||||
|
||||
class JSONCPP_DEPRECATED(
|
||||
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
|
||||
class JSON_API Reader {
|
||||
public:
|
||||
using Char = char;
|
||||
using Location = const Char*;
|
||||
@@ -1524,13 +1523,13 @@ public:
|
||||
};
|
||||
|
||||
/** \brief Constructs a Reader allowing all features for parsing.
|
||||
* \deprecated Use CharReader and CharReaderBuilder.
|
||||
*/
|
||||
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
|
||||
Reader();
|
||||
|
||||
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
||||
* \deprecated Use CharReader and CharReaderBuilder.
|
||||
*/
|
||||
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
|
||||
Reader(const Features& features);
|
||||
|
||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||
@@ -1797,6 +1796,9 @@ public:
|
||||
* - `"allowSpecialFloats": false or true`
|
||||
* - If true, special float values (NaNs and infinities) are allowed and
|
||||
* their values are lossfree restorable.
|
||||
* - `"skipBom": false or true`
|
||||
* - If true, if the input starts with the Unicode byte order mark (BOM),
|
||||
* it is skipped.
|
||||
*
|
||||
* You can examine 'settings_` yourself to see the defaults. You can also
|
||||
* write and read them just like any JSON Value.
|
||||
@@ -2000,6 +2002,8 @@ public:
|
||||
* - Number of precision digits for formatting of real values.
|
||||
* - "precisionType": "significant"(default) or "decimal"
|
||||
* - Type of precision for formatting of real values.
|
||||
* - "emitUTF8": false or true
|
||||
* - If true, outputs raw UTF8 strings instead of escaping them.
|
||||
|
||||
* You can examine 'settings_` yourself
|
||||
* to see the defaults. You can also write and read them just like any
|
||||
@@ -2035,7 +2039,7 @@ public:
|
||||
/** \brief Abstract class for writers.
|
||||
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
||||
*/
|
||||
class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
|
||||
class JSON_API Writer {
|
||||
public:
|
||||
virtual ~Writer();
|
||||
|
||||
@@ -2055,7 +2059,7 @@ public:
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||
#endif
|
||||
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
|
||||
class JSON_API FastWriter
|
||||
: public Writer {
|
||||
public:
|
||||
FastWriter();
|
||||
@@ -2115,7 +2119,7 @@ private:
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||
#endif
|
||||
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
|
||||
class JSON_API
|
||||
StyledWriter : public Writer {
|
||||
public:
|
||||
StyledWriter();
|
||||
@@ -2184,7 +2188,7 @@ private:
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||
#endif
|
||||
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
|
||||
class JSON_API
|
||||
StyledStreamWriter {
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -6,28 +6,28 @@
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
tests and demonstration applications, are licensed under the following
|
||||
conditions...
|
||||
|
||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
this software is released into the Public Domain.
|
||||
|
||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
||||
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
||||
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
Public Domain/MIT License conditions described here, as they choose.
|
||||
|
||||
The MIT License is about as close to Public Domain as a license can get, and is
|
||||
described in clear, concise terms at:
|
||||
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
|
||||
The full text of the MIT License follows:
|
||||
|
||||
========================================================================
|
||||
@@ -202,14 +202,18 @@ template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
|
||||
* Return iterator that would be the new end of the range [begin,end), if we
|
||||
* were to delete zeros in the end of string, but not the last zero before '.'.
|
||||
*/
|
||||
template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) {
|
||||
template <typename Iter>
|
||||
Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
|
||||
for (; begin != end; --end) {
|
||||
if (*(end - 1) != '0') {
|
||||
return end;
|
||||
}
|
||||
// Don't delete the last zero before the decimal point.
|
||||
if (begin != (end - 1) && *(end - 2) == '.') {
|
||||
return end;
|
||||
if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
|
||||
if (precision) {
|
||||
return end;
|
||||
}
|
||||
return end - 2;
|
||||
}
|
||||
}
|
||||
return end;
|
||||
@@ -338,8 +342,7 @@ bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
|
||||
|
||||
// Since String is reference-counted, this at least does not
|
||||
// create an extra copy.
|
||||
String doc;
|
||||
std::getline(is, doc, static_cast<char> EOF);
|
||||
String doc(std::istreambuf_iterator<char>(is), {});
|
||||
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
|
||||
}
|
||||
|
||||
@@ -1409,8 +1412,11 @@ bool OurReader::readToken(Token& token) {
|
||||
if (features_.allowSingleQuotes_) {
|
||||
token.type_ = tokenString;
|
||||
ok = readStringSingleQuote();
|
||||
break;
|
||||
} // else fall through
|
||||
} else {
|
||||
// If we don't allow single quotes, this is a failure case.
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
token.type_ = tokenComment;
|
||||
ok = readComment();
|
||||
@@ -2152,7 +2158,7 @@ bool CharReaderBuilder::validate(Json::Value* invalid) const {
|
||||
if (valid_keys.count(key))
|
||||
continue;
|
||||
if (invalid)
|
||||
(*invalid)[std::move(key)] = *si;
|
||||
(*invalid)[key] = *si;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -2667,7 +2673,7 @@ Value::CZString::CZString(const CZString& other) {
|
||||
storage_.length_ = other.storage_.length_;
|
||||
}
|
||||
|
||||
Value::CZString::CZString(CZString&& other)
|
||||
Value::CZString::CZString(CZString&& other) noexcept
|
||||
: cstr_(other.cstr_), index_(other.index_) {
|
||||
other.cstr_ = nullptr;
|
||||
}
|
||||
@@ -2693,7 +2699,7 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value::CZString& Value::CZString::operator=(CZString&& other) {
|
||||
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
|
||||
cstr_ = other.cstr_;
|
||||
index_ = other.index_;
|
||||
other.cstr_ = nullptr;
|
||||
@@ -2841,7 +2847,7 @@ Value::Value(const Value& other) {
|
||||
dupMeta(other);
|
||||
}
|
||||
|
||||
Value::Value(Value&& other) {
|
||||
Value::Value(Value&& other) noexcept {
|
||||
initBasic(nullValue);
|
||||
swap(other);
|
||||
}
|
||||
@@ -2856,7 +2862,7 @@ Value& Value::operator=(const Value& other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value& Value::operator=(Value&& other) {
|
||||
Value& Value::operator=(Value&& other) noexcept {
|
||||
other.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
@@ -3320,7 +3326,8 @@ void Value::resize(ArrayIndex newSize) {
|
||||
if (newSize == 0)
|
||||
clear();
|
||||
else if (newSize > oldSize)
|
||||
this->operator[](newSize - 1);
|
||||
for (ArrayIndex i = oldSize; i < newSize; ++i)
|
||||
(*this)[i];
|
||||
else {
|
||||
for (ArrayIndex index = newSize; index < oldSize; ++index) {
|
||||
value_.map_->erase(index);
|
||||
@@ -3781,14 +3788,15 @@ bool Value::isObject() const { return type() == objectValue; }
|
||||
Value::Comments::Comments(const Comments& that)
|
||||
: ptr_{cloneUnique(that.ptr_)} {}
|
||||
|
||||
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
|
||||
Value::Comments::Comments(Comments&& that) noexcept
|
||||
: ptr_{std::move(that.ptr_)} {}
|
||||
|
||||
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
||||
ptr_ = cloneUnique(that.ptr_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value::Comments& Value::Comments::operator=(Comments&& that) {
|
||||
Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
|
||||
ptr_ = std::move(that.ptr_);
|
||||
return *this;
|
||||
}
|
||||
@@ -3804,13 +3812,11 @@ String Value::Comments::get(CommentPlacement slot) const {
|
||||
}
|
||||
|
||||
void Value::Comments::set(CommentPlacement slot, String comment) {
|
||||
if (!ptr_) {
|
||||
if (slot >= CommentPlacement::numberOfCommentPlacement)
|
||||
return;
|
||||
if (!ptr_)
|
||||
ptr_ = std::unique_ptr<Array>(new Array());
|
||||
}
|
||||
// check comments array boundry.
|
||||
if (slot < CommentPlacement::numberOfCommentPlacement) {
|
||||
(*ptr_)[slot] = std::move(comment);
|
||||
}
|
||||
(*ptr_)[slot] = std::move(comment);
|
||||
}
|
||||
|
||||
void Value::setComment(String comment, CommentPlacement placement) {
|
||||
@@ -4124,7 +4130,7 @@ Value& Path::make(Value& root) const {
|
||||
|
||||
#if !defined(isnan)
|
||||
// IEEE standard states that NaN values will not compare to themselves
|
||||
#define isnan(x) (x != x)
|
||||
#define isnan(x) ((x) != (x))
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
@@ -4210,16 +4216,18 @@ String valueToString(double value, bool useSpecialFloats,
|
||||
|
||||
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
|
||||
|
||||
// strip the zero padding from the right
|
||||
if (precisionType == PrecisionType::decimalPlaces) {
|
||||
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
|
||||
}
|
||||
|
||||
// try to ensure we preserve the fact that this was given to us as a double on
|
||||
// input
|
||||
if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
|
||||
buffer += ".0";
|
||||
}
|
||||
|
||||
// strip the zero padding from the right
|
||||
if (precisionType == PrecisionType::decimalPlaces) {
|
||||
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision),
|
||||
buffer.end());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
} // namespace
|
||||
@@ -4231,11 +4239,11 @@ String valueToString(double value, unsigned int precision,
|
||||
|
||||
String valueToString(bool value) { return value ? "true" : "false"; }
|
||||
|
||||
static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
|
||||
static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
|
||||
assert(s || !n);
|
||||
|
||||
return std::any_of(s, s + n, [](unsigned char c) {
|
||||
return c == '\\' || c == '"' || !std::isprint(c);
|
||||
return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4326,12 +4334,12 @@ static void appendHex(String& result, unsigned ch) {
|
||||
result.append("\\u").append(toHex16Bit(ch));
|
||||
}
|
||||
|
||||
static String valueToQuotedStringN(const char* value, unsigned length,
|
||||
static String valueToQuotedStringN(const char* value, size_t length,
|
||||
bool emitUTF8 = false) {
|
||||
if (value == nullptr)
|
||||
return "";
|
||||
|
||||
if (!isAnyCharRequiredQuoting(value, length))
|
||||
if (!doesAnyCharRequireEscaping(value, length))
|
||||
return String("\"") + value + "\"";
|
||||
// We have to walk value and escape any special characters.
|
||||
// Appending to String is not efficient, but this should be rare.
|
||||
@@ -4404,7 +4412,7 @@ static String valueToQuotedStringN(const char* value, unsigned length,
|
||||
}
|
||||
|
||||
String valueToQuotedString(const char* value) {
|
||||
return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
|
||||
return valueToQuotedStringN(value, strlen(value));
|
||||
}
|
||||
|
||||
// Class Writer
|
||||
@@ -4453,7 +4461,7 @@ void FastWriter::writeValue(const Value& value) {
|
||||
char const* end;
|
||||
bool ok = value.getString(&str, &end);
|
||||
if (ok)
|
||||
document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
|
||||
document_ += valueToQuotedStringN(str, static_cast<size_t>(end - str));
|
||||
break;
|
||||
}
|
||||
case booleanValue:
|
||||
@@ -4476,8 +4484,7 @@ void FastWriter::writeValue(const Value& value) {
|
||||
const String& name = *it;
|
||||
if (it != members.begin())
|
||||
document_ += ',';
|
||||
document_ += valueToQuotedStringN(name.data(),
|
||||
static_cast<unsigned>(name.length()));
|
||||
document_ += valueToQuotedStringN(name.data(), name.length());
|
||||
document_ += yamlCompatibilityEnabled_ ? ": " : ":";
|
||||
writeValue(value[name]);
|
||||
}
|
||||
@@ -4522,7 +4529,7 @@ void StyledWriter::writeValue(const Value& value) {
|
||||
char const* end;
|
||||
bool ok = value.getString(&str, &end);
|
||||
if (ok)
|
||||
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
|
||||
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
|
||||
else
|
||||
pushValue("");
|
||||
break;
|
||||
@@ -4563,7 +4570,7 @@ void StyledWriter::writeValue(const Value& value) {
|
||||
}
|
||||
|
||||
void StyledWriter::writeArrayValue(const Value& value) {
|
||||
unsigned size = value.size();
|
||||
size_t size = value.size();
|
||||
if (size == 0)
|
||||
pushValue("[]");
|
||||
else {
|
||||
@@ -4572,7 +4579,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
|
||||
writeWithIndent("[");
|
||||
indent();
|
||||
bool hasChildValue = !childValues_.empty();
|
||||
unsigned index = 0;
|
||||
ArrayIndex index = 0;
|
||||
for (;;) {
|
||||
const Value& childValue = value[index];
|
||||
writeCommentBeforeValue(childValue);
|
||||
@@ -4595,7 +4602,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
|
||||
{
|
||||
assert(childValues_.size() == size);
|
||||
document_ += "[ ";
|
||||
for (unsigned index = 0; index < size; ++index) {
|
||||
for (size_t index = 0; index < size; ++index) {
|
||||
if (index > 0)
|
||||
document_ += ", ";
|
||||
document_ += childValues_[index];
|
||||
@@ -4740,7 +4747,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
||||
char const* end;
|
||||
bool ok = value.getString(&str, &end);
|
||||
if (ok)
|
||||
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
|
||||
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
|
||||
else
|
||||
pushValue("");
|
||||
break;
|
||||
@@ -5014,8 +5021,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||
char const* end;
|
||||
bool ok = value.getString(&str, &end);
|
||||
if (ok)
|
||||
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str),
|
||||
emitUTF8_));
|
||||
pushValue(
|
||||
valueToQuotedStringN(str, static_cast<size_t>(end - str), emitUTF8_));
|
||||
else
|
||||
pushValue("");
|
||||
break;
|
||||
@@ -5038,8 +5045,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||
String const& name = *it;
|
||||
Value const& childValue = value[name];
|
||||
writeCommentBeforeValue(childValue);
|
||||
writeWithIndent(valueToQuotedStringN(
|
||||
name.data(), static_cast<unsigned>(name.length()), emitUTF8_));
|
||||
writeWithIndent(
|
||||
valueToQuotedStringN(name.data(), name.length(), emitUTF8_));
|
||||
*sout_ << colonSymbol_;
|
||||
writeValue(childValue);
|
||||
if (++it == members.end()) {
|
||||
@@ -5273,7 +5280,7 @@ bool StreamWriterBuilder::validate(Json::Value* invalid) const {
|
||||
if (valid_keys.count(key))
|
||||
continue;
|
||||
if (invalid)
|
||||
(*invalid)[std::move(key)] = *si;
|
||||
(*invalid)[key] = *si;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<!-- The packages.config acts as the global version for all of the NuGet packages contained within. -->
|
||||
<packages>
|
||||
<!-- Native packages -->
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
@@ -10,7 +9,7 @@
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.6.220404001" targetFramework="native" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.2-prerelease.220406002" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3-prerelease.220816001" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" developmentDependency="true" />
|
||||
|
||||
<!-- Managed packages -->
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
"type": "string",
|
||||
"format": "color"
|
||||
},
|
||||
"ColorOrIndex": {
|
||||
"default": "#",
|
||||
"pattern": "^(?:#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?|i[A-Fa-f0-9]{2})$",
|
||||
"type": "string",
|
||||
"format": "color"
|
||||
},
|
||||
"Coordinates": {
|
||||
"pattern": "^(-?\\d+)?(,\\s?(-?\\d+)?)?$",
|
||||
"type": "string"
|
||||
@@ -58,20 +64,20 @@
|
||||
"default": "",
|
||||
"description": "Sets the file location of the sound played when the application emits a BEL character. If the path is invalid no sound will be played. This property also accepts an array of sounds and the terminal will pick one at random.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
{
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
"AppearanceConfig": {
|
||||
"properties": {
|
||||
"colorScheme": {
|
||||
@@ -197,7 +203,7 @@
|
||||
},
|
||||
"intenseTextStyle": {
|
||||
"default": "bright",
|
||||
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
|
||||
"description": "Controls how 'intense' text is rendered when unfocused. Values are \"bold\", \"bright\", \"all\" and \"none\"",
|
||||
"enum": [
|
||||
"none",
|
||||
"bold",
|
||||
@@ -238,7 +244,7 @@
|
||||
"default": 12,
|
||||
"description": "Size of the font in points.",
|
||||
"minimum": 1,
|
||||
"type": "integer"
|
||||
"type": "number"
|
||||
},
|
||||
"weight": {
|
||||
"default": "normal",
|
||||
@@ -306,6 +312,7 @@
|
||||
"enum": [
|
||||
"adjustFontSize",
|
||||
"clearBuffer",
|
||||
"closeOtherPanes",
|
||||
"closeOtherTabs",
|
||||
"closePane",
|
||||
"closeTab",
|
||||
@@ -314,6 +321,7 @@
|
||||
"commandPalette",
|
||||
"copy",
|
||||
"duplicateTab",
|
||||
"expandSelectionToWord",
|
||||
"exportBuffer",
|
||||
"find",
|
||||
"findMatch",
|
||||
@@ -376,6 +384,7 @@
|
||||
"scrollToMark",
|
||||
"clearMark",
|
||||
"clearAllMarks",
|
||||
"experimental.colorSelection",
|
||||
"unbound"
|
||||
],
|
||||
"type": "string"
|
||||
@@ -836,6 +845,43 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ColorSelectionAction": {
|
||||
"description": "Arguments corresponding to a Color Selection Action",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/$defs/ShortcutAction"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"const": "experimental.colorSelection"
|
||||
},
|
||||
"matchMode": {
|
||||
"type": "string",
|
||||
"default": "none",
|
||||
"description": "Specifies if only the selected text should be colored (0), or all instances of selected text (case-insensitive) (1).",
|
||||
"enum": [
|
||||
"none",
|
||||
"all"
|
||||
]
|
||||
},
|
||||
"foreground": {
|
||||
"$ref": "#/$defs/ColorOrIndex",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The foreground color to use, as an RGB value (\"#rrggbb\"), or color index (\"iNN\"). If left unspecified it falls back to the default text foreground color."
|
||||
},
|
||||
"background": {
|
||||
"$ref": "#/$defs/ColorOrIndex",
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"description": "The background color to use, as an RGB value (\"#rrggbb\"), or color index (\"iNN\"). If left unspecified it falls back to the default text background color."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"OpenSettingsAction": {
|
||||
"description": "Arguments corresponding to a Open Settings Action",
|
||||
"allOf": [
|
||||
@@ -1500,6 +1546,101 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ShowCloseButton": {
|
||||
"enum": [
|
||||
"always",
|
||||
"hover",
|
||||
"never"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThemeColor": {
|
||||
"description": "A special kind of color for use in themes. Can be an #rrggbb color, #rrggbbaa color, or a special value. 'accent' is evaluated as the user's selected Accent color in the OS, and 'terminalBackground' will be evaluated as the background color of the active terminal pane.",
|
||||
"oneOf": [
|
||||
{
|
||||
"pattern": "^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{2})?)?$",
|
||||
"type": "string",
|
||||
"format": "color",
|
||||
"default": "#000000ff"
|
||||
},
|
||||
{
|
||||
"const": "accent",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"const": "terminalBackground",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"TabTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the tabs",
|
||||
"properties": {
|
||||
"background": {
|
||||
"description": "The color of a tab when it is the active tab",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"unfocusedBackground": {
|
||||
"description": "The color of a tab when it is not the active tab",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"showCloseButton": {
|
||||
"description": "Controls the visibility of the close button on the tab",
|
||||
"$ref": "#/$defs/ShowCloseButton"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TabRowTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the tab row",
|
||||
"properties": {
|
||||
"background": {
|
||||
"description": "The color of the tab row when the window is the foreground window.",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"unfocusedBackground": {
|
||||
"description": "The color of the tab row when the window is inactive",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"WindowTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the window itself",
|
||||
"properties": {
|
||||
"applicationTheme": {
|
||||
"description": "Which UI theme the Terminal should use for controls",
|
||||
"enum": [ "light", "dark", "system" ],
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Theme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the window. This controls things like the titlebar, the tabs, the application theme.",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the theme. This will be displayed in the settings UI.",
|
||||
"not": {
|
||||
"enum": [ "light", "dark", "system" ]
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"$ref": "#/$defs/TabTheme"
|
||||
},
|
||||
"tabRow": {
|
||||
"$ref": "#/$defs/TabRowTheme"
|
||||
},
|
||||
"window": {
|
||||
"$ref": "#/$defs/WindowTheme"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Keybinding": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -1611,6 +1752,9 @@
|
||||
{
|
||||
"$ref": "#/$defs/AdjustOpacityAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/ColorSelectionAction"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
@@ -1733,6 +1877,11 @@
|
||||
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.enableColorSelection": {
|
||||
"default": false,
|
||||
"description": "When set to true, adds preset \"Color Selection\" actions (keybindings) to allow colorizing selected text via keystroke, similar to the legacy conhost EnableColorSelection feature (such as alt+6 to color the selection red).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"disableAnimations": {
|
||||
"default": false,
|
||||
"description": "When set to `true`, visual animations will be disabled across the application.",
|
||||
@@ -1876,15 +2025,17 @@
|
||||
"type": "string"
|
||||
},
|
||||
"theme": {
|
||||
"default": "system",
|
||||
"description": "Sets the theme of the application. The special value \"system\" refers to the active Windows system theme.",
|
||||
"enum": [
|
||||
"light",
|
||||
"dark",
|
||||
"system"
|
||||
],
|
||||
"default": "dark",
|
||||
"description": "Sets the theme of the application. This value should be the name of one of the themes defined in `themes`. The Terminal also includes the themes `dark`, `light`, and `system`.",
|
||||
"type": "string"
|
||||
},
|
||||
"themes": {
|
||||
"description": "The list of available themes",
|
||||
"items": {
|
||||
"$ref": "#/$defs/Theme"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"showTabsInTitlebar": {
|
||||
"default": true,
|
||||
"description": "When set to true, the tabs are moved into the titlebar and the titlebar disappears. When set to false, the titlebar sits above the tabs.",
|
||||
@@ -1972,7 +2123,7 @@
|
||||
"afterLastTab",
|
||||
"afterCurrentTab"
|
||||
],
|
||||
"type": "string"
|
||||
"type": "string"
|
||||
},
|
||||
"autoHideWindow": {
|
||||
"default": false,
|
||||
@@ -2183,10 +2334,10 @@
|
||||
"description": "Use to set a path to a pixel shader to use with the Terminal. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"type": "string"
|
||||
},
|
||||
"experimental.useAtlasEngine": {
|
||||
"description": "Enable using the experimental new rendering engine for this profile. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"useAtlasEngine": {
|
||||
"description": "Windows Terminal 1.16 and later ship with a new, performant text renderer. Set this to false to revert back to the old text renderer.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"default": true
|
||||
},
|
||||
"fontFace": {
|
||||
"default": "Cascadia Mono",
|
||||
@@ -2198,7 +2349,7 @@
|
||||
"default": 12,
|
||||
"description": "[deprecated] Define 'size' within the 'font' object instead.",
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"type": "number",
|
||||
"deprecated": true
|
||||
},
|
||||
"fontWeight": {
|
||||
@@ -2229,6 +2380,17 @@
|
||||
],
|
||||
"deprecated": true
|
||||
},
|
||||
"intenseTextStyle": {
|
||||
"default": "bright",
|
||||
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
|
||||
"enum": [
|
||||
"none",
|
||||
"bold",
|
||||
"bright",
|
||||
"all"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"foreground": {
|
||||
"$ref": "#/$defs/Color",
|
||||
"default": "#cccccc",
|
||||
@@ -2330,7 +2492,10 @@
|
||||
},
|
||||
"startingDirectory": {
|
||||
"description": "The directory the shell starts in when it is loaded.",
|
||||
"type": "string"
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"suppressApplicationTitle": {
|
||||
"description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal.",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/chromium/chromium",
|
||||
"commitHash": "d8710dd959da8e3be56f20af8cc94fbf560fbb6b"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/chromium/chromium",
|
||||
"commitHash": "d8710dd959da8e3be56f20af8cc94fbf560fbb6b"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/pinam45/dynamic_bitset",
|
||||
"commitHash": "00f2d066ce9deebf28b006636150e5a882beb83f"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/pinam45/dynamic_bitset",
|
||||
"commitHash": "00f2d066ce9deebf28b006636150e5a882beb83f"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/fmtlib/fmt",
|
||||
"commitHash": "7bdf0628b1276379886c7f6dda2cef2b3b374f0b"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/fmtlib/fmt",
|
||||
"commitHash": "7bdf0628b1276379886c7f6dda2cef2b3b374f0b"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#ifdef USE_INTERVAL_TREE_NAMESPACE
|
||||
namespace interval_tree
|
||||
|
||||
@@ -8,7 +8,7 @@ That provenance file is automatically read and inventoried by Microsoft systems
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
1. Go to ekg/intervaltreerepository on GitHub.
|
||||
1. Go to the ekg/intervaltree repository on GitHub.
|
||||
2. Take the file IntervalTree.h wholesale and drop it into the directory here.
|
||||
3. Don't change anything about it.
|
||||
4. Validate that the license in the root of the repository didn't change and update it if so. It is sitting in the same directory as this readme.
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/ekg/intervaltree",
|
||||
"commitHash": "b90527f9e6d51cd36ecbb50429e4524d3a418ea5"
|
||||
"commitHash": "aa5937755000f1cd007402d03b6f7ce4427c5d21"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/kimwalisch/libpopcnt",
|
||||
"commitHash": "043a99fba31121a70bcb2f589faa17f534ae6085"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/kimwalisch/libpopcnt",
|
||||
"commitHash": "c49987e90e56191c399cab881ab87b5daecc9b8e"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
|
||||
25
oss/wyhash/LICENSE
Normal file
25
oss/wyhash/LICENSE
Normal file
@@ -0,0 +1,25 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
4
oss/wyhash/MAINTAINER_README.md
Normal file
4
oss/wyhash/MAINTAINER_README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
### Notes for Future Maintainers
|
||||
|
||||
[wyhash](https://github.com/wangyi-fudan/wyhash) is used as the hash algorithm for `<til/hash.h>` and its `til::hasher`.
|
||||
The source code was directly integrated into that header file and can be found in `/src/inc/til/hash.h`.
|
||||
15
oss/wyhash/cgmanifest.json
Normal file
15
oss/wyhash/cgmanifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/wangyi-fudan/wyhash",
|
||||
"commitHash": "e77036ac1943369dc03e611cde52a8570f8ceefe"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://gitlab.freedesktop.org/xorg/app/rgb.git",
|
||||
"commitHash": "97820e748eb496a1f6d3fc3bf89688f0ce1f64f9"
|
||||
}
|
||||
}
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://gitlab.freedesktop.org/xorg/app/rgb.git",
|
||||
"commitHash": "97820e748eb496a1f6d3fc3bf89688f0ce1f64f9"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
|
||||
@@ -2,47 +2,46 @@
|
||||
Texture2D shaderTexture;
|
||||
SamplerState samplerState;
|
||||
|
||||
cbuffer PixelShaderSettings {
|
||||
float Time;
|
||||
float Scale;
|
||||
float2 Resolution;
|
||||
float4 Background;
|
||||
cbuffer PixelShaderSettings
|
||||
{
|
||||
float time;
|
||||
float scale;
|
||||
float2 resolution;
|
||||
float4 background;
|
||||
};
|
||||
|
||||
#define SCANLINE_FACTOR 0.5
|
||||
#define SCALED_SCANLINE_PERIOD Scale
|
||||
#define SCALED_GAUSSIAN_SIGMA (2.0*Scale)
|
||||
#define SCANLINE_FACTOR 0.5f
|
||||
#define SCALED_SCANLINE_PERIOD scale
|
||||
#define SCALED_GAUSSIAN_SIGMA (2.0f * scale)
|
||||
|
||||
static const float M_PI = 3.14159265f;
|
||||
|
||||
float Gaussian2D(float x, float y, float sigma)
|
||||
{
|
||||
return 1/(sigma*sqrt(2*M_PI)) * exp(-0.5*(x*x + y*y)/sigma/sigma);
|
||||
return 1 / (sigma * sqrt(2 * M_PI)) * exp(-0.5 * (x * x + y * y) / sigma / sigma);
|
||||
}
|
||||
|
||||
float4 Blur(Texture2D input, float2 tex_coord, float sigma)
|
||||
{
|
||||
uint width, height;
|
||||
float width, height;
|
||||
shaderTexture.GetDimensions(width, height);
|
||||
|
||||
float texelWidth = 1.0f/width;
|
||||
float texelHeight = 1.0f/height;
|
||||
float texelWidth = 1.0f / width;
|
||||
float texelHeight = 1.0f / height;
|
||||
|
||||
float4 color = { 0, 0, 0, 0 };
|
||||
|
||||
int sampleCount = 13;
|
||||
float sampleCount = 13;
|
||||
|
||||
for (int x = 0; x < sampleCount; x++)
|
||||
for (float x = 0; x < sampleCount; x++)
|
||||
{
|
||||
float2 samplePos = { 0, 0 };
|
||||
samplePos.x = tex_coord.x + (x - sampleCount / 2.0f) * texelWidth;
|
||||
|
||||
samplePos.x = tex_coord.x + (x - sampleCount/2) * texelWidth;
|
||||
for (int y = 0; y < sampleCount; y++)
|
||||
for (float y = 0; y < sampleCount; y++)
|
||||
{
|
||||
samplePos.y = tex_coord.y + (y - sampleCount/2) * texelHeight;
|
||||
if (samplePos.x <= 0 || samplePos.y <= 0 || samplePos.x >= width || samplePos.y >= height) continue;
|
||||
|
||||
color += input.Sample(samplerState, samplePos) * Gaussian2D((x - sampleCount/2), (y - sampleCount/2), sigma);
|
||||
samplePos.y = tex_coord.y + (y - sampleCount / 2.0f) * texelHeight;
|
||||
color += input.Sample(samplerState, samplePos) * Gaussian2D(x - sampleCount / 2.0f, y - sampleCount / 2.0f, sigma);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +50,7 @@ float4 Blur(Texture2D input, float2 tex_coord, float sigma)
|
||||
|
||||
float SquareWave(float y)
|
||||
{
|
||||
return 1 - (floor(y / SCALED_SCANLINE_PERIOD) % 2) * SCANLINE_FACTOR;
|
||||
return 1.0f - (floor(y / SCALED_SCANLINE_PERIOD) % 2.0f) * SCANLINE_FACTOR;
|
||||
}
|
||||
|
||||
float4 Scanline(float4 color, float4 pos)
|
||||
@@ -60,9 +59,9 @@ float4 Scanline(float4 color, float4 pos)
|
||||
|
||||
// TODO:GH#3929 make this configurable.
|
||||
// Remove the && false to draw scanlines everywhere.
|
||||
if (length(color.rgb) < 0.2 && false)
|
||||
if (length(color.rgb) < 0.2f && false)
|
||||
{
|
||||
return color + wave*0.1;
|
||||
return color + wave * 0.1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -70,14 +69,14 @@ float4 Scanline(float4 color, float4 pos)
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
|
||||
// clang-format on
|
||||
{
|
||||
Texture2D input = shaderTexture;
|
||||
|
||||
// TODO:GH#3930 Make these configurable in some way.
|
||||
float4 color = input.Sample(samplerState, tex);
|
||||
color += Blur(input, tex, SCALED_GAUSSIAN_SIGMA)*0.3;
|
||||
float4 color = shaderTexture.Sample(samplerState, tex);
|
||||
color += Blur(shaderTexture, tex, SCALED_GAUSSIAN_SIGMA) * 0.3f;
|
||||
color = Scanline(color, pos);
|
||||
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,17 +17,14 @@
|
||||
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
|
||||
<XamlComponentResourceLocation>nested</XamlComponentResourceLocation>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
<ClCompile>
|
||||
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
|
||||
on being compiled with RTTI (/GR). -->
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
@@ -147,14 +144,15 @@
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- DON'T PUT XAML FILES HERE! Put them in SampleAppLib.vcxproj -->
|
||||
@@ -79,15 +83,20 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ====================== Compiler & Linker Flags ===================== -->
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\ConTypes.lib;WindowsApp.lib;shell32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
@@ -102,4 +111,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.1" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -104,8 +104,6 @@ void SampleIslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam)
|
||||
|
||||
void SampleIslandWindow::Initialize()
|
||||
{
|
||||
const bool initialized = (_interopWindowHandle != nullptr);
|
||||
|
||||
_source = DesktopWindowXamlSource{};
|
||||
|
||||
auto interop = _source.as<IDesktopWindowXamlSourceNative>();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{b4427499-9fde-4208-b456-5bc580637633}</ProjectGuid>
|
||||
@@ -16,7 +15,15 @@
|
||||
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
<TerminalVCRTForwarders>true</TerminalVCRTForwarders>
|
||||
<TerminalThemeHelpers>true</TerminalThemeHelpers>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
@@ -138,16 +145,11 @@
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
|
||||
</Target>
|
||||
|
||||
<!-- Override GetPackagingOutputs to roll up all our dependencies.
|
||||
@@ -225,13 +227,24 @@
|
||||
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||
</PackagingOutputs>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Same thing AGAIN here, with OpenConsole.exe If you forget this, then
|
||||
the scratch app will use the inbox conpty with a newer conpty lib, causing
|
||||
us to send the inbox conhost messages that will make it explode. -->
|
||||
<ItemGroup>
|
||||
<_OpenConsoleExe Include="$(OpenConsoleCommonOutDir)\OpenConsole.exe" />
|
||||
|
||||
<PackagingOutputs Include="@(_OpenConsoleExe)">
|
||||
<ProjectName>$(ProjectName)</ProjectName>
|
||||
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
|
||||
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||
</PackagingOutputs>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
|
||||
<Import Project="..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" />
|
||||
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.1" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.7.3" targetFramework="native" />
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
#include "MidiAudio.hpp"
|
||||
#include "../terminal/parser/stateMachine.hpp"
|
||||
|
||||
#include <dsound.h>
|
||||
|
||||
#pragma comment(lib, "dxguid.lib")
|
||||
#pragma comment(lib, "dsound.lib")
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
@@ -18,66 +13,48 @@ using namespace std::chrono_literals;
|
||||
constexpr auto WAVE_SIZE = 16u;
|
||||
constexpr auto WAVE_DATA = std::array<byte, WAVE_SIZE>{ 128, 159, 191, 223, 255, 223, 191, 159, 128, 96, 64, 32, 0, 32, 64, 96 };
|
||||
|
||||
MidiAudio::MidiAudio(HWND windowHandle)
|
||||
void MidiAudio::_initialize(HWND windowHandle) noexcept
|
||||
{
|
||||
if (SUCCEEDED(DirectSoundCreate8(nullptr, &_directSound, nullptr)))
|
||||
_hwnd = windowHandle;
|
||||
_directSoundModule.reset(LoadLibraryExW(L"dsound.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32));
|
||||
if (_directSoundModule)
|
||||
{
|
||||
if (SUCCEEDED(_directSound->SetCooperativeLevel(windowHandle, DSSCL_NORMAL)))
|
||||
if (const auto createFunction = GetProcAddressByFunctionDeclaration(_directSoundModule.get(), DirectSoundCreate8))
|
||||
{
|
||||
_createBuffers();
|
||||
if (SUCCEEDED(createFunction(nullptr, &_directSound, nullptr)))
|
||||
{
|
||||
if (SUCCEEDED(_directSound->SetCooperativeLevel(windowHandle, DSSCL_NORMAL)))
|
||||
{
|
||||
_createBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MidiAudio::~MidiAudio() noexcept
|
||||
void MidiAudio::BeginSkip() noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
#pragma warning(suppress : 26447)
|
||||
// We acquire the lock here so the class isn't destroyed while in use.
|
||||
// If this throws, we'll catch it, so the C26447 warning is bogus.
|
||||
const auto lock = std::unique_lock{ _inUseMutex };
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// If the lock fails, we'll just have to live with the consequences.
|
||||
}
|
||||
_skip.SetEvent();
|
||||
}
|
||||
|
||||
void MidiAudio::Initialize()
|
||||
void MidiAudio::EndSkip() noexcept
|
||||
{
|
||||
_shutdownFuture = _shutdownPromise.get_future();
|
||||
_skip.ResetEvent();
|
||||
}
|
||||
|
||||
void MidiAudio::Shutdown()
|
||||
{
|
||||
// Once the shutdown promise is set, any note that is playing will stop
|
||||
// immediately, and the Unlock call will exit the thread ASAP.
|
||||
_shutdownPromise.set_value();
|
||||
}
|
||||
|
||||
void MidiAudio::Lock()
|
||||
{
|
||||
_inUseMutex.lock();
|
||||
}
|
||||
|
||||
void MidiAudio::Unlock()
|
||||
{
|
||||
// We need to check the shutdown status before releasing the mutex,
|
||||
// because after that the class could be destroyed.
|
||||
const auto shutdownStatus = _shutdownFuture.wait_for(0s);
|
||||
_inUseMutex.unlock();
|
||||
// If the wait didn't timeout, that means the shutdown promise was set,
|
||||
// so we need to exit the thread ASAP by throwing an exception.
|
||||
if (shutdownStatus != std::future_status::timeout)
|
||||
{
|
||||
throw Microsoft::Console::VirtualTerminal::StateMachine::ShutdownException{};
|
||||
}
|
||||
}
|
||||
|
||||
void MidiAudio::PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept
|
||||
void MidiAudio::PlayNote(HWND windowHandle, const int noteNumber, const int velocity, const std::chrono::milliseconds duration) noexcept
|
||||
try
|
||||
{
|
||||
if (_skip.is_signaled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hwnd != windowHandle)
|
||||
{
|
||||
_initialize(windowHandle);
|
||||
}
|
||||
|
||||
const auto& buffer = _buffers.at(_activeBufferIndex);
|
||||
if (velocity && buffer)
|
||||
{
|
||||
@@ -100,10 +77,10 @@ try
|
||||
buffer->SetCurrentPosition((_lastBufferPosition + 12) % WAVE_SIZE);
|
||||
}
|
||||
|
||||
// By waiting on the shutdown future with the duration of the note, we'll
|
||||
// either be paused for the appropriate amount of time, or we'll break out
|
||||
// of the wait early if we've been shutdown.
|
||||
_shutdownFuture.wait_for(duration);
|
||||
// By waiting on the skip event with a maximum duration of the note, we'll
|
||||
// either be paused for the appropriate amount of time, or we'll break out early
|
||||
// because BeginSkip() was called. This happens for Ctrl+C or during shutdown.
|
||||
_skip.wait(::base::saturated_cast<DWORD>(duration.count()));
|
||||
|
||||
if (velocity && buffer)
|
||||
{
|
||||
|
||||
@@ -12,8 +12,6 @@ Abstract:
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
|
||||
struct IDirectSound8;
|
||||
struct IDirectSoundBuffer;
|
||||
@@ -21,26 +19,20 @@ struct IDirectSoundBuffer;
|
||||
class MidiAudio
|
||||
{
|
||||
public:
|
||||
MidiAudio(HWND windowHandle);
|
||||
MidiAudio(const MidiAudio&) = delete;
|
||||
MidiAudio(MidiAudio&&) = delete;
|
||||
MidiAudio& operator=(const MidiAudio&) = delete;
|
||||
MidiAudio& operator=(MidiAudio&&) = delete;
|
||||
~MidiAudio() noexcept;
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
void Lock();
|
||||
void Unlock();
|
||||
void PlayNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration) noexcept;
|
||||
void BeginSkip() noexcept;
|
||||
void EndSkip() noexcept;
|
||||
void PlayNote(HWND windowHandle, const int noteNumber, const int velocity, const std::chrono::milliseconds duration) noexcept;
|
||||
|
||||
private:
|
||||
void _initialize(HWND windowHandle) noexcept;
|
||||
void _createBuffers() noexcept;
|
||||
|
||||
Microsoft::WRL::ComPtr<IDirectSound8> _directSound;
|
||||
std::array<Microsoft::WRL::ComPtr<IDirectSoundBuffer>, 2> _buffers;
|
||||
wil::slim_event_manual_reset _skip;
|
||||
|
||||
HWND _hwnd = nullptr;
|
||||
wil::unique_hmodule _directSoundModule;
|
||||
wil::com_ptr<IDirectSound8> _directSound;
|
||||
std::array<wil::com_ptr<IDirectSoundBuffer>, 2> _buffers;
|
||||
size_t _activeBufferIndex = 0;
|
||||
DWORD _lastBufferPosition = 0;
|
||||
std::promise<void> _shutdownPromise;
|
||||
std::future<void> _shutdownFuture;
|
||||
std::mutex _inUseMutex;
|
||||
};
|
||||
|
||||
@@ -25,7 +25,9 @@ Abstract:
|
||||
#endif
|
||||
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#include <mmeapi.h>
|
||||
#include <dsound.h>
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -28,6 +28,13 @@ constexpr til::inclusive_rect ScreenToBufferLine(const til::inclusive_rect& line
|
||||
return { line.Left >> scale, line.Top, line.Right >> scale, line.Bottom };
|
||||
}
|
||||
|
||||
constexpr til::point ScreenToBufferLine(const til::point& line, const LineRendition lineRendition)
|
||||
{
|
||||
// Use shift right to quickly divide the Left and Right by 2 for double width lines.
|
||||
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
|
||||
return { line.X >> scale, line.Y };
|
||||
}
|
||||
|
||||
constexpr til::inclusive_rect BufferToScreenLine(const til::inclusive_rect& line, const LineRendition lineRendition)
|
||||
{
|
||||
// Use shift left to quickly multiply the Left and Right by 2 for double width lines.
|
||||
|
||||
@@ -17,7 +17,6 @@ Author(s):
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <til/bit.h>
|
||||
#include <til/hash.h>
|
||||
|
||||
// std::unordered_map needs help to know how to hash a til::point
|
||||
@@ -33,9 +32,9 @@ namespace std
|
||||
// - coord - the coord to hash
|
||||
// Return Value:
|
||||
// - the hashed coord
|
||||
constexpr size_t operator()(const til::point coord) const noexcept
|
||||
size_t operator()(const til::point coord) const noexcept
|
||||
{
|
||||
return til::hash(til::bit_cast<uint64_t>(coord));
|
||||
return til::hash(coord);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ using namespace Microsoft::Console::Types;
|
||||
// - direction - The direction to search (upward or downward)
|
||||
// - sensitivity - Whether or not you care about case
|
||||
Search::Search(IUiaData& uiaData,
|
||||
const std::wstring& str,
|
||||
const std::wstring_view str,
|
||||
const Direction direction,
|
||||
const Sensitivity sensitivity) :
|
||||
_direction(direction),
|
||||
@@ -47,7 +47,7 @@ Search::Search(IUiaData& uiaData,
|
||||
// - sensitivity - Whether or not you care about case
|
||||
// - anchor - starting search location in screenInfo
|
||||
Search::Search(IUiaData& uiaData,
|
||||
const std::wstring& str,
|
||||
const std::wstring_view str,
|
||||
const Direction direction,
|
||||
const Sensitivity sensitivity,
|
||||
const til::point anchor) :
|
||||
@@ -106,14 +106,13 @@ void Search::Select() const
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - In console host, we take the found word and apply the given color to it in the screen buffer
|
||||
// - In Windows Terminal, we just select the found word, but we do not modify the buffer
|
||||
// - Applies the supplied TextAttribute to the current search result.
|
||||
// Arguments:
|
||||
// - ulAttr - The legacy color attribute to apply to the word
|
||||
// - attr - The attribute to apply to the result
|
||||
void Search::Color(const TextAttribute attr) const
|
||||
{
|
||||
// Only select if we've found something.
|
||||
if (_coordSelStart != _coordSelEnd)
|
||||
if (_coordSelEnd >= _coordSelStart)
|
||||
{
|
||||
_uiaData.ColorSelection(_coordSelStart, _coordSelEnd, attr);
|
||||
}
|
||||
@@ -330,7 +329,7 @@ void Search::_UpdateNextPosition()
|
||||
// - wstr - String that will be our search term
|
||||
// Return Value:
|
||||
// - Structured text data for comparison to screen buffer text data.
|
||||
std::vector<std::vector<wchar_t>> Search::s_CreateNeedleFromString(const std::wstring& wstr)
|
||||
std::vector<std::vector<wchar_t>> Search::s_CreateNeedleFromString(const std::wstring_view wstr)
|
||||
{
|
||||
const auto charData = Utf16Parser::Parse(wstr);
|
||||
std::vector<std::vector<wchar_t>> cells;
|
||||
|
||||
@@ -41,12 +41,12 @@ public:
|
||||
};
|
||||
|
||||
Search(Microsoft::Console::Types::IUiaData& uiaData,
|
||||
const std::wstring& str,
|
||||
const std::wstring_view str,
|
||||
const Direction dir,
|
||||
const Sensitivity sensitivity);
|
||||
|
||||
Search(Microsoft::Console::Types::IUiaData& uiaData,
|
||||
const std::wstring& str,
|
||||
const std::wstring_view str,
|
||||
const Direction dir,
|
||||
const Sensitivity sensitivity,
|
||||
const til::point anchor);
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
|
||||
static til::point s_GetInitialAnchor(const Microsoft::Console::Types::IUiaData& uiaData, const Direction dir);
|
||||
|
||||
static std::vector<std::vector<wchar_t>> s_CreateNeedleFromString(const std::wstring& wstr);
|
||||
static std::vector<std::vector<wchar_t>> s_CreateNeedleFromString(const std::wstring_view wstr);
|
||||
|
||||
bool _reachedEnd = false;
|
||||
til::point _coordNext;
|
||||
|
||||
@@ -30,7 +30,7 @@ using PointTree = interval_tree::IntervalTree<til::point, size_t>;
|
||||
// Return Value:
|
||||
// - constructed object
|
||||
// Note: may throw exception
|
||||
TextBuffer::TextBuffer(const til::size screenBufferSize,
|
||||
TextBuffer::TextBuffer(til::size screenBufferSize,
|
||||
const TextAttribute defaultAttributes,
|
||||
const UINT cursorSize,
|
||||
const bool isActiveBuffer,
|
||||
@@ -46,6 +46,10 @@ TextBuffer::TextBuffer(const til::size screenBufferSize,
|
||||
_currentHyperlinkId{ 1 },
|
||||
_currentPatternId{ 0 }
|
||||
{
|
||||
// Guard against resizing the text buffer to 0 columns/rows, which would break being able to insert text.
|
||||
screenBufferSize.width = std::max(screenBufferSize.width, 1);
|
||||
screenBufferSize.height = std::max(screenBufferSize.height, 1);
|
||||
|
||||
// initialize ROWs
|
||||
_storage.reserve(gsl::narrow<size_t>(screenBufferSize.Y));
|
||||
for (til::CoordType i = 0; i < screenBufferSize.Y; ++i)
|
||||
@@ -896,9 +900,11 @@ void TextBuffer::Reset()
|
||||
// - newSize - new size of screen.
|
||||
// Return Value:
|
||||
// - Success if successful. Invalid parameter if screen buffer size is unexpected. No memory if allocation failed.
|
||||
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(const til::size newSize) noexcept
|
||||
[[nodiscard]] NTSTATUS TextBuffer::ResizeTraditional(til::size newSize) noexcept
|
||||
{
|
||||
RETURN_HR_IF(E_INVALIDARG, newSize.X < 0 || newSize.Y < 0);
|
||||
// Guard against resizing the text buffer to 0 columns/rows, which would break being able to insert text.
|
||||
newSize.width = std::max(newSize.width, 1);
|
||||
newSize.height = std::max(newSize.height, 1);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1032,6 +1038,7 @@ void TextBuffer::_RefreshRowIDs(std::optional<til::CoordType> newRowWidth)
|
||||
{
|
||||
std::unordered_map<til::CoordType, til::CoordType> rowMap;
|
||||
til::CoordType i = 0;
|
||||
til::CoordType newWidth = newRowWidth.value_or(_storage.at(0).size());
|
||||
for (auto& it : _storage)
|
||||
{
|
||||
// Build a map so we can update Unicode Storage
|
||||
@@ -1043,12 +1050,13 @@ void TextBuffer::_RefreshRowIDs(std::optional<til::CoordType> newRowWidth)
|
||||
// Also update the char row parent pointers as they can get shuffled up in the rotates.
|
||||
it.GetCharRow().UpdateParent(&it);
|
||||
|
||||
// Resize the rows in the X dimension if we have a new width
|
||||
if (newRowWidth.has_value())
|
||||
{
|
||||
// Realloc in the X direction
|
||||
THROW_IF_FAILED(it.Resize(newRowWidth.value()));
|
||||
}
|
||||
// Realloc in the X direction
|
||||
// BODGY: We unpack the optional early and resize here unconditionally
|
||||
// due to a codegen issue in LKG14. We used to check the optional in
|
||||
// every iteration of the loop, but that resulted in the optimizer
|
||||
// emitting a copy of the loop, used when the optional was empty, that
|
||||
// never exited. Oops.
|
||||
THROW_IF_FAILED(it.Resize(newWidth));
|
||||
}
|
||||
|
||||
// Give the new mapping to Unicode Storage
|
||||
@@ -1138,7 +1146,7 @@ til::point TextBuffer::GetWordStart(const til::point target, const std::wstring_
|
||||
// that it actually points to a space in the buffer
|
||||
copy = bufferSize.BottomRightInclusive();
|
||||
}
|
||||
else if (target >= limit)
|
||||
else if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
// if at/past the limit --> clamp to limit
|
||||
copy = limitOptional.value_or(bufferSize.BottomRightInclusive());
|
||||
@@ -1254,7 +1262,7 @@ til::point TextBuffer::GetWordEnd(const til::point target, const std::wstring_vi
|
||||
// Already at/past the limit. Can't move forward.
|
||||
const auto bufferSize{ GetSize() };
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
if (target >= limit)
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
@@ -1282,7 +1290,7 @@ til::point TextBuffer::_GetWordEndForAccessibility(const til::point target, cons
|
||||
const auto bufferSize{ GetSize() };
|
||||
auto result{ target };
|
||||
|
||||
if (target >= limit)
|
||||
if (bufferSize.CompareInBounds(target, limit, true) >= 0)
|
||||
{
|
||||
// if we're already on/past the last RegularChar,
|
||||
// clamp result to that position
|
||||
@@ -1419,7 +1427,7 @@ bool TextBuffer::MoveToNextWord(til::point& pos, const std::wstring_view wordDel
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
const auto copy{ _GetWordEndForAccessibility(pos, wordDelimiters, limit) };
|
||||
|
||||
if (copy >= limit)
|
||||
if (bufferSize.CompareInBounds(copy, limit, true) >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1466,7 +1474,7 @@ til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional<til::po
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (resultPos > limit)
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
resultPos = limit;
|
||||
}
|
||||
@@ -1494,7 +1502,7 @@ til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode,
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
// Clamp pos to limit
|
||||
if (resultPos > limit)
|
||||
if (bufferSize.CompareInBounds(resultPos, limit, true) > 0)
|
||||
{
|
||||
resultPos = limit;
|
||||
}
|
||||
@@ -1524,19 +1532,9 @@ til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode,
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::optional<til::point> limitOptional) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
bool pastEndInclusive;
|
||||
til::point limit;
|
||||
{
|
||||
// if the limit is past the end of the buffer,
|
||||
// 1) clamp limit to end of buffer
|
||||
// 2) set pastEndInclusive
|
||||
const auto endInclusive{ bufferSize.BottomRightInclusive() };
|
||||
const auto val = limitOptional.value_or(endInclusive);
|
||||
pastEndInclusive = val > endInclusive;
|
||||
limit = pastEndInclusive ? endInclusive : val;
|
||||
}
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit) + (pastEndInclusive ? 1 : 0) };
|
||||
const auto distanceToLimit{ bufferSize.CompareInBounds(pos, limit, true) };
|
||||
if (distanceToLimit >= 0)
|
||||
{
|
||||
// Corner Case: we're on/past the limit
|
||||
@@ -1579,7 +1577,7 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point>
|
||||
const auto bufferSize = GetSize();
|
||||
const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) };
|
||||
|
||||
if (pos > limit)
|
||||
if (bufferSize.CompareInBounds(pos, limit, true) > 0)
|
||||
{
|
||||
// we're past the end
|
||||
// clamp us to the limit
|
||||
@@ -1611,7 +1609,7 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional<til::point>
|
||||
// - bufferCoordinates: when enabled, treat the coordinates as relative to
|
||||
// the buffer rather than the screen.
|
||||
// Return Value:
|
||||
// - the delimiter class for the given char
|
||||
// - One or more rects corresponding to the selection area
|
||||
const std::vector<til::inclusive_rect> TextBuffer::GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const
|
||||
{
|
||||
std::vector<til::inclusive_rect> textRects;
|
||||
@@ -1621,7 +1619,7 @@ const std::vector<til::inclusive_rect> TextBuffer::GetTextRects(til::point start
|
||||
// (0,0) is the top-left of the screen
|
||||
// the physically "higher" coordinate is closer to the top-left
|
||||
// the physically "lower" coordinate is closer to the bottom-right
|
||||
const auto [higherCoord, lowerCoord] = start <= end ?
|
||||
const auto [higherCoord, lowerCoord] = bufferSize.CompareInBounds(start, end) <= 0 ?
|
||||
std::make_tuple(start, end) :
|
||||
std::make_tuple(end, start);
|
||||
|
||||
@@ -1660,6 +1658,69 @@ const std::vector<til::inclusive_rect> TextBuffer::GetTextRects(til::point start
|
||||
return textRects;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Computes the span(s) for the given selection
|
||||
// - If not a blockSelection, returns a single span (start - end)
|
||||
// - Else if a blockSelection, returns spans corresponding to each line in the block selection
|
||||
// Arguments:
|
||||
// - start: beginning of the text region of interest (inclusive)
|
||||
// - end: the other end of the text region of interest (inclusive)
|
||||
// - blockSelection: when enabled, get spans for each line covered by the block
|
||||
// - bufferCoordinates: when enabled, treat the coordinates as relative to
|
||||
// the buffer rather than the screen.
|
||||
// Return Value:
|
||||
// - one or more sets of start-end coordinates, representing spans of text in the buffer
|
||||
std::vector<til::point_span> TextBuffer::GetTextSpans(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const
|
||||
{
|
||||
std::vector<til::point_span> textSpans;
|
||||
if (blockSelection)
|
||||
{
|
||||
// If blockSelection, this is effectively the same operation as GetTextRects, but
|
||||
// expressed in til::point coordinates.
|
||||
const auto rects = GetTextRects(start, end, /*blockSelection*/ true, bufferCoordinates);
|
||||
textSpans.reserve(rects.size());
|
||||
|
||||
for (auto rect : rects)
|
||||
{
|
||||
const til::point first = { rect.Left, rect.Top };
|
||||
const til::point second = { rect.Right, rect.Bottom };
|
||||
textSpans.emplace_back(first, second);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
|
||||
// (0,0) is the top-left of the screen
|
||||
// the physically "higher" coordinate is closer to the top-left
|
||||
// the physically "lower" coordinate is closer to the bottom-right
|
||||
auto [higherCoord, lowerCoord] = start <= end ?
|
||||
std::make_tuple(start, end) :
|
||||
std::make_tuple(end, start);
|
||||
|
||||
textSpans.reserve(1);
|
||||
|
||||
// If we were passed screen coordinates, convert the given range into
|
||||
// equivalent buffer offsets, taking line rendition into account.
|
||||
if (!bufferCoordinates)
|
||||
{
|
||||
higherCoord = ScreenToBufferLine(higherCoord, GetLineRendition(higherCoord.Y));
|
||||
lowerCoord = ScreenToBufferLine(lowerCoord, GetLineRendition(lowerCoord.Y));
|
||||
}
|
||||
|
||||
til::inclusive_rect asRect = { higherCoord.X, higherCoord.Y, lowerCoord.X, lowerCoord.Y };
|
||||
_ExpandTextRow(asRect);
|
||||
higherCoord.X = asRect.Left;
|
||||
higherCoord.Y = asRect.Top;
|
||||
lowerCoord.X = asRect.Right;
|
||||
lowerCoord.Y = asRect.Bottom;
|
||||
|
||||
textSpans.emplace_back(higherCoord, lowerCoord);
|
||||
}
|
||||
|
||||
return textSpans;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Expand the selection row according to include wide glyphs fully
|
||||
// - this is particularly useful for box selections (ALT + selection)
|
||||
@@ -1774,9 +1835,8 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning(suppress : 26444)
|
||||
// TODO GH 2675: figure out why there's custom construction/destruction happening here
|
||||
it++;
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
// We apply formatting to rows if the row was NOT wrapped or formatting of wrapped rows is allowed
|
||||
@@ -1832,6 +1892,43 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t TextBuffer::SpanLength(const til::point coordStart, const til::point coordEnd) const
|
||||
{
|
||||
const auto bufferSize = GetSize();
|
||||
// The coords are inclusive, so to get the (inclusive) length we add 1.
|
||||
const auto length = bufferSize.CompareInBounds(coordEnd, coordStart) + 1;
|
||||
return gsl::narrow<size_t>(length);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Retrieves the plain text data between the specified coordinates.
|
||||
// Arguments:
|
||||
// - trimTrailingWhitespace - remove the trailing whitespace at the end of the result.
|
||||
// - start - where to start getting text (should be at or prior to "end")
|
||||
// - end - where to end getting text
|
||||
// Return Value:
|
||||
// - Just the text.
|
||||
std::wstring TextBuffer::GetPlainText(const til::point& start, const til::point& end) const
|
||||
{
|
||||
std::wstring text;
|
||||
auto spanLength = SpanLength(start, end);
|
||||
text.reserve(spanLength);
|
||||
|
||||
auto it = GetCellDataAt(start);
|
||||
|
||||
for (; it && spanLength > 0; ++it, --spanLength)
|
||||
{
|
||||
const auto& cell = *it;
|
||||
if (!cell.DbcsAttr().IsTrailing())
|
||||
{
|
||||
const auto chars = cell.Chars();
|
||||
text.append(chars);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Generates a CF_HTML compliant structure based on the passed in text and color data
|
||||
// Arguments:
|
||||
|
||||
@@ -166,6 +166,7 @@ public:
|
||||
bool MoveToPreviousGlyph(til::point& pos, std::optional<til::point> limitOptional = std::nullopt) const;
|
||||
|
||||
const std::vector<til::inclusive_rect> GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const;
|
||||
std::vector<til::point_span> GetTextSpans(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const;
|
||||
|
||||
void AddHyperlinkToMap(std::wstring_view uri, uint16_t id);
|
||||
std::wstring GetHyperlinkUriFromId(uint16_t id) const;
|
||||
@@ -182,12 +183,16 @@ public:
|
||||
std::vector<std::vector<COLORREF>> BkAttr;
|
||||
};
|
||||
|
||||
size_t SpanLength(const til::point coordStart, const til::point coordEnd) const;
|
||||
|
||||
const TextAndColor GetText(const bool includeCRLF,
|
||||
const bool trimTrailingWhitespace,
|
||||
const std::vector<til::inclusive_rect>& textRects,
|
||||
std::function<std::pair<COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors = nullptr,
|
||||
const bool formatWrappedRows = false) const;
|
||||
|
||||
std::wstring GetPlainText(const til::point& start, const til::point& end) const;
|
||||
|
||||
static std::string GenHTML(const TextAndColor& rows,
|
||||
const int fontHeightPoints,
|
||||
const std::wstring_view fontFaceName,
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalMUX>true</TerminalMUX>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(OpenConsoleDir)src\wap-common.build.pre.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<!--
|
||||
These two properties are very important!
|
||||
@@ -160,13 +165,7 @@
|
||||
</Target>
|
||||
|
||||
<!-- This is required to get the package dependency in the AppXManifest. -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -99,7 +99,8 @@
|
||||
<com:ComInterface>
|
||||
<com:ProxyStub Id="DEC4804D-56D1-4F73-9FBE-6828E7C85C56" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/> <!-- ITerminalHandoff -->
|
||||
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/> <!-- ITerminalHandoff2 -->
|
||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
|
||||
</com:ComInterface>
|
||||
</com:Extension>
|
||||
|
||||
@@ -188,7 +188,8 @@
|
||||
<com:ComInterface>
|
||||
<com:ProxyStub Id="1833E661-CC81-4DD0-87C6-C2F74BD39EFA" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff -->
|
||||
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff2 -->
|
||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
|
||||
</com:ComInterface>
|
||||
</com:Extension>
|
||||
|
||||
@@ -188,7 +188,8 @@
|
||||
<com:ComInterface>
|
||||
<com:ProxyStub Id="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/> <!-- ITerminalHandoff -->
|
||||
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/> <!-- ITerminalHandoff2 -->
|
||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
</com:ComInterface>
|
||||
</com:Extension>
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
#include <wil/stl.h>
|
||||
#include <wil/resource.h>
|
||||
#include <wil/win32_helpers.h>
|
||||
#include <gsl/gsl_util>
|
||||
#include <gsl/pointers>
|
||||
#include <shellapi.h>
|
||||
#include <appmodel.h>
|
||||
|
||||
// BODGY
|
||||
//
|
||||
@@ -25,18 +28,68 @@
|
||||
// process can successfully elevate.
|
||||
|
||||
#pragma warning(suppress : 26461) // we can't change the signature of wWinMain
|
||||
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int)
|
||||
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
{
|
||||
// All of the args passed to us (something like `new-tab -p {guid}`) are in
|
||||
// pCmdLine
|
||||
// This will invoke an elevated terminal in two possible ways. See GH#14501
|
||||
// In both scenarios, it passes the entire cmdline as-is to the new process.
|
||||
//
|
||||
// #1 discover and invoke the app using the GetCurrentApplicationUserModelId
|
||||
// api using shell:AppsFolder\package!appid
|
||||
// cmd: shell:AppsFolder\WindowsTerminalDev_8wekyb3d8bbwe!App
|
||||
// params: new-tab -p {guid}
|
||||
//
|
||||
// #2 find and execute WindowsTerminal.exe
|
||||
// cmd: {same path as this binary}\WindowsTerminal.exe
|
||||
// params: new-tab -p {guid}
|
||||
|
||||
// Get the path to WindowsTerminal.exe, which should live next to us.
|
||||
std::filesystem::path module{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
||||
// Swap elevate-shim.exe for WindowsTerminal.exe
|
||||
module.replace_filename(L"WindowsTerminal.exe");
|
||||
// see if we're a store app we can invoke with shell:AppsFolder
|
||||
std::wstring appUserModelId;
|
||||
const auto result = wil::AdaptFixedSizeToAllocatedResult<std::wstring, APPLICATION_USER_MODEL_ID_MAX_LENGTH>(
|
||||
appUserModelId, [&](PWSTR value, size_t valueLength, gsl::not_null<size_t*> valueLengthNeededWithNull) noexcept -> HRESULT {
|
||||
UINT32 length = gsl::narrow_cast<UINT32>(valueLength);
|
||||
const LONG rc = GetCurrentApplicationUserModelId(&length, value);
|
||||
switch (rc)
|
||||
{
|
||||
case ERROR_SUCCESS:
|
||||
*valueLengthNeededWithNull = length;
|
||||
return S_OK;
|
||||
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
*valueLengthNeededWithNull = length;
|
||||
return S_FALSE; // trigger allocation loop
|
||||
|
||||
case APPMODEL_ERROR_NO_APPLICATION:
|
||||
return E_FAIL; // we are not running as a store app
|
||||
|
||||
default:
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
});
|
||||
LOG_IF_FAILED(result);
|
||||
|
||||
std::wstring cmd = {};
|
||||
if (result == S_OK && appUserModelId.length() > 0)
|
||||
{
|
||||
// scenario #1
|
||||
cmd = L"shell:AppsFolder\\" + appUserModelId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// scenario #2
|
||||
// Get the path to WindowsTerminal.exe, which should live next to us.
|
||||
std::filesystem::path module{
|
||||
wil::GetModuleFileNameW<std::wstring>(nullptr)
|
||||
};
|
||||
// Swap elevate-shim.exe for WindowsTerminal.exe
|
||||
module.replace_filename(L"WindowsTerminal.exe");
|
||||
cmd = module;
|
||||
}
|
||||
|
||||
// Go!
|
||||
|
||||
// The cmdline argument passed to WinMain is stripping the first argument.
|
||||
// Using GetCommandLine() instead for lParameters
|
||||
|
||||
// disable warnings from SHELLEXECUTEINFOW struct. We can't fix that.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26476) // Macro uses naked union over variant.
|
||||
@@ -46,8 +99,10 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int)
|
||||
seInfo.cbSize = sizeof(seInfo);
|
||||
seInfo.fMask = SEE_MASK_DEFAULT;
|
||||
seInfo.lpVerb = L"runas"; // This asks the shell to elevate the process
|
||||
seInfo.lpFile = module.c_str(); // This is `...\WindowsTerminal.exe`
|
||||
seInfo.lpParameters = pCmdLine; // This is `new-tab -p {guid}`
|
||||
seInfo.lpFile = cmd.c_str(); // This is `shell:AppsFolder\...` or `...\WindowsTerminal.exe`
|
||||
seInfo.lpParameters = GetCommandLine(); // This is `new-tab -p {guid}`
|
||||
seInfo.nShow = SW_SHOWNORMAL;
|
||||
LOG_IF_WIN32_BOOL_FALSE(ShellExecuteExW(&seInfo));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -64,8 +64,7 @@ namespace SettingsModelLocalTests
|
||||
},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
"applicationTheme": "light"
|
||||
}
|
||||
})" };
|
||||
|
||||
@@ -81,7 +80,6 @@ namespace SettingsModelLocalTests
|
||||
|
||||
VERIFY_IS_NOT_NULL(theme->Window());
|
||||
VERIFY_ARE_EQUAL(winrt::Windows::UI::Xaml::ElementTheme::Light, theme->Window().RequestedTheme());
|
||||
VERIFY_ARE_EQUAL(true, theme->Window().UseMica());
|
||||
}
|
||||
|
||||
void ThemeTests::ParseEmptyTheme()
|
||||
@@ -163,8 +161,7 @@ namespace SettingsModelLocalTests
|
||||
},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
"applicationTheme": "light"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -175,16 +172,14 @@ namespace SettingsModelLocalTests
|
||||
},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
"applicationTheme": "light"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "backgroundOmittedEntirely",
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
"applicationTheme": "light"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -239,8 +234,7 @@ namespace SettingsModelLocalTests
|
||||
"tabRow": {},
|
||||
"window":
|
||||
{
|
||||
"applicationTheme": "light",
|
||||
"useMica": true
|
||||
"applicationTheme": "light"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -349,6 +349,21 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL("wt.exe", commandlines.at(3).Args().at(0));
|
||||
VERIFY_ARE_EQUAL("baz", commandlines.at(3).Args().at(1));
|
||||
}
|
||||
{
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", L"-p", L"u;", L"nt", L"-p", L"u" };
|
||||
|
||||
auto commandlines = AppCommandlineArgs::BuildCommands(rawCommands);
|
||||
VERIFY_ARE_EQUAL(2u, commandlines.size());
|
||||
VERIFY_ARE_EQUAL(3u, commandlines.at(0).Argc());
|
||||
VERIFY_ARE_EQUAL("wt.exe", commandlines.at(0).Args().at(0));
|
||||
VERIFY_ARE_EQUAL("-p", commandlines.at(0).Args().at(1));
|
||||
VERIFY_ARE_EQUAL("u", commandlines.at(0).Args().at(2));
|
||||
VERIFY_ARE_EQUAL(4u, commandlines.at(1).Argc());
|
||||
VERIFY_ARE_EQUAL("wt.exe", commandlines.at(1).Args().at(0));
|
||||
VERIFY_ARE_EQUAL("nt", commandlines.at(1).Args().at(1));
|
||||
VERIFY_ARE_EQUAL("-p", commandlines.at(1).Args().at(2));
|
||||
VERIFY_ARE_EQUAL("u", commandlines.at(1).Args().at(3));
|
||||
}
|
||||
}
|
||||
|
||||
void CommandlineTest::TestEscapeDelimiters()
|
||||
|
||||
@@ -503,7 +503,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
@@ -521,7 +521,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
page->_SplitPane(SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
@@ -843,7 +843,7 @@ namespace TerminalAppLocalTests
|
||||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
page->_SplitPane(SplitDirection::Right, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
secondId = tab->_activePane->Id().value();
|
||||
});
|
||||
Sleep(250);
|
||||
@@ -861,7 +861,7 @@ namespace TerminalAppLocalTests
|
||||
// | 3 | |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
// Split again to make the 3rd tab
|
||||
thirdId = tab->_activePane->Id().value();
|
||||
@@ -881,7 +881,7 @@ namespace TerminalAppLocalTests
|
||||
// | 3 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, true, nullptr));
|
||||
page->_SplitPane(SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
fourthId = tab->_activePane->Id().value();
|
||||
});
|
||||
|
||||
@@ -23,21 +23,12 @@
|
||||
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<!-- TerminalCppWinrt is intentionally not set -->
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SolutionDir)\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)\src\cppwinrt.build.pre.props" />
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
|
||||
on being compiled with RTTI (/GR). -->
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
#include "pch.h"
|
||||
#include "HwndTerminal.hpp"
|
||||
#include <windowsx.h>
|
||||
#include "../../types/TermControlUiaProvider.hpp"
|
||||
#include <DefaultSettings.h>
|
||||
#include "../../renderer/base/Renderer.hpp"
|
||||
#include "../../renderer/dx/DxRenderer.hpp"
|
||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||
#include "../../types/viewport.cpp"
|
||||
#include "../../types/inc/GlyphWidth.hpp"
|
||||
|
||||
@@ -54,6 +50,17 @@ LRESULT CALLBACK HwndTerminal::HwndTerminalWndProc(
|
||||
LPARAM lParam) noexcept
|
||||
try
|
||||
{
|
||||
if (WM_NCCREATE == uMsg)
|
||||
{
|
||||
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
|
||||
auto cs = reinterpret_cast<CREATESTRUCT*>(lParam);
|
||||
HwndTerminal* that = static_cast<HwndTerminal*>(cs->lpCreateParams);
|
||||
that->_hwnd = wil::unique_hwnd(hwnd);
|
||||
|
||||
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
|
||||
return DefWindowProc(hwnd, WM_NCCREATE, wParam, lParam);
|
||||
}
|
||||
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
|
||||
auto terminal = reinterpret_cast<HwndTerminal*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
|
||||
@@ -114,11 +121,11 @@ try
|
||||
}
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
if (terminal->_terminal->IsSelectionActive())
|
||||
if (const auto& termCore{ terminal->_terminal }; termCore && termCore->IsSelectionActive())
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto bufferData = terminal->_terminal->RetrieveSelectedTextFromBuffer(false);
|
||||
const auto bufferData = termCore->RetrieveSelectedTextFromBuffer(false);
|
||||
LOG_IF_FAILED(terminal->_CopyTextToSystemClipboard(bufferData, true));
|
||||
TerminalClearSelection(terminal);
|
||||
}
|
||||
@@ -169,7 +176,7 @@ static bool RegisterTermClass(HINSTANCE hInstance) noexcept
|
||||
}
|
||||
|
||||
HwndTerminal::HwndTerminal(HWND parentHwnd) :
|
||||
_desiredFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, { 0, 14 }, CP_UTF8 },
|
||||
_desiredFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, 14, CP_UTF8 },
|
||||
_actualFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, { 0, 14 }, CP_UTF8, false },
|
||||
_uiaProvider{ nullptr },
|
||||
_currentDpi{ USER_DEFAULT_SCREEN_DPI },
|
||||
@@ -182,7 +189,7 @@ HwndTerminal::HwndTerminal(HWND parentHwnd) :
|
||||
|
||||
if (RegisterTermClass(hInstance))
|
||||
{
|
||||
_hwnd = wil::unique_hwnd(CreateWindowExW(
|
||||
CreateWindowExW(
|
||||
0,
|
||||
term_window_class,
|
||||
nullptr,
|
||||
@@ -197,10 +204,7 @@ HwndTerminal::HwndTerminal(HWND parentHwnd) :
|
||||
parentHwnd,
|
||||
nullptr,
|
||||
hInstance,
|
||||
nullptr));
|
||||
|
||||
#pragma warning(suppress : 26490) // Win32 APIs can only store void*, have to use reinterpret_cast
|
||||
SetWindowLongPtr(_hwnd.get(), GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,6 +281,10 @@ CATCH_LOG();
|
||||
|
||||
void HwndTerminal::RegisterScrollCallback(std::function<void(int, int, int)> callback)
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_terminal->SetScrollPositionChangedCallback(callback);
|
||||
}
|
||||
|
||||
@@ -312,6 +320,10 @@ HWND HwndTerminal::GetHwnd() const noexcept
|
||||
|
||||
void HwndTerminal::_UpdateFont(int newDpi)
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_currentDpi = newDpi;
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
||||
@@ -324,14 +336,19 @@ IRawElementProviderSimple* HwndTerminal::_GetUiaProvider() noexcept
|
||||
{
|
||||
// If TermControlUiaProvider throws during construction,
|
||||
// we don't want to try constructing an instance again and again.
|
||||
// _uiaProviderInitialized helps us prevent this.
|
||||
if (!_uiaProviderInitialized)
|
||||
if (!_uiaProvider)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
auto lock = _terminal->LockForWriting();
|
||||
LOG_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, this->GetUiaData(), this));
|
||||
_uiaProviderInitialized = true;
|
||||
LOG_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<HwndTerminalAutomationPeer>(&_uiaProvider, this->GetUiaData(), this));
|
||||
_uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(_uiaProvider.Get());
|
||||
LOG_IF_FAILED(_uiaEngine->Enable());
|
||||
_renderer->AddRenderEngine(_uiaEngine.get());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -345,6 +362,7 @@ IRawElementProviderSimple* HwndTerminal::_GetUiaProvider() noexcept
|
||||
|
||||
HRESULT HwndTerminal::Refresh(const til::size windowSize, _Out_ til::size* dimensions)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, dimensions);
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
@@ -360,49 +378,39 @@ HRESULT HwndTerminal::Refresh(const til::size windowSize, _Out_ til::size* dimen
|
||||
const auto viewInPixels = Viewport::FromDimensions(windowSize);
|
||||
const auto vp = _renderEngine->GetViewportInCharacters(viewInPixels);
|
||||
|
||||
// Guard against resizing the window to 0 columns/rows, which the text buffer classes don't really support.
|
||||
auto size = vp.Dimensions();
|
||||
size.width = std::max(size.width, 1);
|
||||
size.height = std::max(size.height, 1);
|
||||
|
||||
// If this function succeeds with S_FALSE, then the terminal didn't
|
||||
// actually change size. No need to notify the connection of this
|
||||
// no-op.
|
||||
// TODO: MSFT:20642295 Resizing the buffer will corrupt it
|
||||
// I believe we'll need support for CSI 2J, and additionally I think
|
||||
// we're resetting the viewport to the top
|
||||
RETURN_IF_FAILED(_terminal->UserResize({ vp.Width(), vp.Height() }));
|
||||
dimensions->X = vp.Width();
|
||||
dimensions->Y = vp.Height();
|
||||
RETURN_IF_FAILED(_terminal->UserResize(size));
|
||||
dimensions->width = size.width;
|
||||
dimensions->height = size.height;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void HwndTerminal::SendOutput(std::wstring_view data)
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_terminal->Write(data);
|
||||
}
|
||||
|
||||
HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ void** terminal)
|
||||
{
|
||||
// In order for UIA to hook up properly there needs to be a "static" window hosting the
|
||||
// inner win32 control. If the static window is not present then WM_GETOBJECT messages
|
||||
// will not reach the child control, and the uia element will not be present in the tree.
|
||||
auto _hostWindow = CreateWindowEx(
|
||||
0,
|
||||
L"static",
|
||||
nullptr,
|
||||
WS_CHILD |
|
||||
WS_CLIPCHILDREN |
|
||||
WS_CLIPSIBLINGS |
|
||||
WS_VISIBLE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
parentHwnd,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
auto _terminal = std::make_unique<HwndTerminal>(_hostWindow);
|
||||
auto _terminal = std::make_unique<HwndTerminal>(parentHwnd);
|
||||
RETURN_IF_FAILED(_terminal->Initialize());
|
||||
|
||||
*hwnd = _hostWindow;
|
||||
*hwnd = _terminal->GetHwnd();
|
||||
*terminal = _terminal.release();
|
||||
|
||||
return S_OK;
|
||||
@@ -487,7 +495,7 @@ HRESULT _stdcall TerminalCalculateResize(_In_ void* terminal, _In_ til::CoordTyp
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
|
||||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, { width, height });
|
||||
const auto viewInPixels = Viewport::FromDimensions({ width, height });
|
||||
const auto viewInCharacters = publicTerminal->_renderEngine->GetViewportInCharacters(viewInPixels);
|
||||
|
||||
dimensions->X = viewInCharacters.Width();
|
||||
@@ -504,8 +512,10 @@ void _stdcall TerminalDpiChanged(void* terminal, int newDpi)
|
||||
|
||||
void _stdcall TerminalUserScroll(void* terminal, int viewTop)
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
publicTerminal->_terminal->UserScrollViewport(viewTop);
|
||||
if (const auto publicTerminal = static_cast<const HwndTerminal*>(terminal); publicTerminal && publicTerminal->_terminal)
|
||||
{
|
||||
publicTerminal->_terminal->UserScrollViewport(viewTop);
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int HwndTerminal::_NumberOfClicks(til::point point, std::chrono::steady_clock::time_point timestamp) noexcept
|
||||
@@ -527,6 +537,7 @@ const unsigned int HwndTerminal::_NumberOfClicks(til::point point, std::chrono::
|
||||
HRESULT HwndTerminal::_StartSelection(LPARAM lParam) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
|
||||
const til::point cursorPosition{
|
||||
GET_X_LPARAM(lParam),
|
||||
GET_Y_LPARAM(lParam),
|
||||
@@ -570,6 +581,7 @@ CATCH_RETURN();
|
||||
HRESULT HwndTerminal::_MoveSelection(LPARAM lParam) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
|
||||
const til::point cursorPosition{
|
||||
GET_X_LPARAM(lParam),
|
||||
GET_Y_LPARAM(lParam),
|
||||
@@ -608,6 +620,10 @@ CATCH_RETURN();
|
||||
void HwndTerminal::_ClearSelection() noexcept
|
||||
try
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto lock{ _terminal->LockForWriting() };
|
||||
_terminal->ClearSelection();
|
||||
_renderer->TriggerSelection();
|
||||
@@ -622,15 +638,21 @@ void _stdcall TerminalClearSelection(void* terminal)
|
||||
|
||||
bool _stdcall TerminalIsSelectionActive(void* terminal)
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
const auto selectionActive = publicTerminal->_terminal->IsSelectionActive();
|
||||
return selectionActive;
|
||||
if (const auto publicTerminal = static_cast<const HwndTerminal*>(terminal); publicTerminal && publicTerminal->_terminal)
|
||||
{
|
||||
return publicTerminal->_terminal->IsSelectionActive();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the selected text in the terminal.
|
||||
const wchar_t* _stdcall TerminalGetSelection(void* terminal)
|
||||
{
|
||||
auto publicTerminal = static_cast<HwndTerminal*>(terminal);
|
||||
if (!publicTerminal || !publicTerminal->_terminal)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto bufferData = publicTerminal->_terminal->RetrieveSelectedTextFromBuffer(false);
|
||||
publicTerminal->_ClearSelection();
|
||||
@@ -682,12 +704,17 @@ bool HwndTerminal::_CanSendVTMouseInput() const noexcept
|
||||
{
|
||||
// Only allow the transit of mouse events if shift isn't pressed.
|
||||
const auto shiftPressed = GetKeyState(VK_SHIFT) < 0;
|
||||
return !shiftPressed && _focused && _terminal->IsTrackingMouseInput();
|
||||
return !shiftPressed && _focused && _terminal && _terminal->IsTrackingMouseInput();
|
||||
}
|
||||
|
||||
bool HwndTerminal::_SendMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam) noexcept
|
||||
try
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
til::point cursorPosition{
|
||||
GET_X_LPARAM(lParam),
|
||||
GET_Y_LPARAM(lParam),
|
||||
@@ -720,11 +747,20 @@ catch (...)
|
||||
void HwndTerminal::_SendKeyEvent(WORD vkey, WORD scanCode, WORD flags, bool keyDown) noexcept
|
||||
try
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto modifiers = getControlKeyState();
|
||||
if (WI_IsFlagSet(flags, ENHANCED_KEY))
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
if (vkey && keyDown && _uiaProvider)
|
||||
{
|
||||
_uiaProvider->RecordKeyEvent(vkey);
|
||||
}
|
||||
_terminal->SendKeyEvent(vkey, scanCode, modifiers, keyDown);
|
||||
}
|
||||
CATCH_LOG();
|
||||
@@ -732,7 +768,11 @@ CATCH_LOG();
|
||||
void HwndTerminal::_SendCharEvent(wchar_t ch, WORD scanCode, WORD flags) noexcept
|
||||
try
|
||||
{
|
||||
if (_terminal->IsSelectionActive())
|
||||
if (!_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (_terminal->IsSelectionActive())
|
||||
{
|
||||
_ClearSelection();
|
||||
if (ch == UNICODE_ESC)
|
||||
@@ -780,6 +820,10 @@ void _stdcall DestroyTerminal(void* terminal)
|
||||
void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, til::CoordType fontSize, int newDpi)
|
||||
{
|
||||
const auto publicTerminal = static_cast<HwndTerminal*>(terminal);
|
||||
if (!publicTerminal || !publicTerminal->_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto lock = publicTerminal->_terminal->LockForWriting();
|
||||
|
||||
@@ -799,7 +843,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
||||
|
||||
publicTerminal->_terminal->SetCursorStyle(static_cast<DispatchTypes::CursorStyle>(theme.CursorStyle));
|
||||
|
||||
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, { 0, fontSize }, CP_UTF8 };
|
||||
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, static_cast<float>(fontSize), CP_UTF8 };
|
||||
publicTerminal->_UpdateFont(newDpi);
|
||||
|
||||
// When the font changes the terminal dimensions need to be recalculated since the available row and column
|
||||
@@ -815,7 +859,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
||||
void _stdcall TerminalBlinkCursor(void* terminal)
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
if (!publicTerminal->_terminal->IsCursorBlinkingAllowed() && publicTerminal->_terminal->IsCursorVisible())
|
||||
if (!publicTerminal || !publicTerminal->_terminal || (!publicTerminal->_terminal->IsCursorBlinkingAllowed() && publicTerminal->_terminal->IsCursorVisible()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -826,6 +870,10 @@ void _stdcall TerminalBlinkCursor(void* terminal)
|
||||
void _stdcall TerminalSetCursorVisible(void* terminal, const bool visible)
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
if (!publicTerminal || !publicTerminal->_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
publicTerminal->_terminal->SetCursorOn(visible);
|
||||
}
|
||||
|
||||
@@ -833,12 +881,20 @@ void __stdcall TerminalSetFocus(void* terminal)
|
||||
{
|
||||
auto publicTerminal = static_cast<HwndTerminal*>(terminal);
|
||||
publicTerminal->_focused = true;
|
||||
if (auto uiaEngine = publicTerminal->_uiaEngine.get())
|
||||
{
|
||||
LOG_IF_FAILED(uiaEngine->Enable());
|
||||
}
|
||||
}
|
||||
|
||||
void __stdcall TerminalKillFocus(void* terminal)
|
||||
{
|
||||
auto publicTerminal = static_cast<HwndTerminal*>(terminal);
|
||||
publicTerminal->_focused = false;
|
||||
if (auto uiaEngine = publicTerminal->_uiaEngine.get())
|
||||
{
|
||||
LOG_IF_FAILED(uiaEngine->Disable());
|
||||
}
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -849,6 +905,7 @@ void __stdcall TerminalKillFocus(void* terminal)
|
||||
HRESULT HwndTerminal::_CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, const bool fAlsoCopyFormatting)
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _terminal);
|
||||
std::wstring finalString;
|
||||
|
||||
// Concatenate strings into one giant string to put onto the clipboard.
|
||||
@@ -1005,6 +1062,10 @@ double HwndTerminal::GetScaleFactor() const noexcept
|
||||
|
||||
void HwndTerminal::ChangeViewport(const til::inclusive_rect& NewWindow)
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_terminal->UserScrollViewport(NewWindow.Top);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
#include "../../renderer/base/Renderer.hpp"
|
||||
#include "../../renderer/dx/DxRenderer.hpp"
|
||||
#include "../../renderer/uia/UiaRenderer.hpp"
|
||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||
#include <UIAutomationCore.h>
|
||||
#include "../../types/IControlAccessibilityInfo.h"
|
||||
#include "../../types/TermControlUiaProvider.hpp"
|
||||
#include "HwndTerminalAutomationPeer.hpp"
|
||||
|
||||
using namespace Microsoft::Console::VirtualTerminal;
|
||||
|
||||
@@ -74,15 +74,15 @@ private:
|
||||
FontInfo _actualFont;
|
||||
int _currentDpi;
|
||||
std::function<void(wchar_t*)> _pfnWriteCallback;
|
||||
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
|
||||
::Microsoft::WRL::ComPtr<HwndTerminalAutomationPeer> _uiaProvider;
|
||||
|
||||
std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal;
|
||||
|
||||
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer;
|
||||
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine;
|
||||
std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine;
|
||||
|
||||
bool _focused{ false };
|
||||
bool _uiaProviderInitialized{ false };
|
||||
|
||||
std::chrono::milliseconds _multiClickTime;
|
||||
unsigned int _multiClickCounter{};
|
||||
|
||||
159
src/cascadia/PublicTerminalCore/HwndTerminalAutomationPeer.cpp
Normal file
159
src/cascadia/PublicTerminalCore/HwndTerminalAutomationPeer.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "HwndTerminalAutomationPeer.hpp"
|
||||
#include "../../types/UiaTracing.h"
|
||||
#include <UIAutomationCoreApi.h>
|
||||
|
||||
#pragma warning(suppress : 4471) // We don't control UIAutomationClient
|
||||
#include <UIAutomationClient.h>
|
||||
|
||||
using namespace Microsoft::Console::Types;
|
||||
|
||||
static constexpr wchar_t UNICODE_NEWLINE{ L'\n' };
|
||||
|
||||
// Method Description:
|
||||
// - creates a copy of the provided text with all of the control characters removed
|
||||
// Arguments:
|
||||
// - text: the string we're sanitizing
|
||||
// Return Value:
|
||||
// - a copy of "sanitized" with all of the control characters removed
|
||||
static std::wstring Sanitize(std::wstring_view text)
|
||||
{
|
||||
std::wstring sanitized{ text };
|
||||
sanitized.erase(std::remove_if(sanitized.begin(), sanitized.end(), [](wchar_t c) {
|
||||
return (c < UNICODE_SPACE && c != UNICODE_NEWLINE) || c == 0x7F /*DEL*/;
|
||||
}),
|
||||
sanitized.end());
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - verifies if a given string has text that would be read by a screen reader.
|
||||
// - a string of control characters, for example, would not be read.
|
||||
// Arguments:
|
||||
// - text: the string we're validating
|
||||
// Return Value:
|
||||
// - true, if the text is readable. false, otherwise.
|
||||
static constexpr bool IsReadable(std::wstring_view text)
|
||||
{
|
||||
for (const auto c : text)
|
||||
{
|
||||
if (c > UNICODE_SPACE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HwndTerminalAutomationPeer::RecordKeyEvent(const WORD vkey)
|
||||
{
|
||||
if (const auto charCode{ MapVirtualKey(vkey, MAPVK_VK_TO_CHAR) })
|
||||
{
|
||||
if (const auto keyEventChar{ gsl::narrow_cast<wchar_t>(charCode) }; IsReadable({ &keyEventChar, 1 }))
|
||||
{
|
||||
_keyEvents.emplace_back(keyEventChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of IRawElementProviderSimple::get_PropertyValue.
|
||||
// Gets custom properties.
|
||||
IFACEMETHODIMP HwndTerminalAutomationPeer::GetPropertyValue(_In_ PROPERTYID propertyId,
|
||||
_Out_ VARIANT* pVariant) noexcept
|
||||
{
|
||||
pVariant->vt = VT_EMPTY;
|
||||
|
||||
// Returning the default will leave the property as the default
|
||||
// so we only really need to touch it for the properties we want to implement
|
||||
if (propertyId == UIA_ClassNamePropertyId)
|
||||
{
|
||||
// IMPORTANT: Do NOT change the name. Screen readers like may be dependent on this being "WpfTermControl".
|
||||
pVariant->bstrVal = SysAllocString(L"WPFTermControl");
|
||||
if (pVariant->bstrVal != nullptr)
|
||||
{
|
||||
pVariant->vt = VT_BSTR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// fall back to shared implementation
|
||||
return TermControlUiaProvider::GetPropertyValue(propertyId, pVariant);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Signals the ui automation client that the terminal's selection has changed and should be updated
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void HwndTerminalAutomationPeer::SignalSelectionChanged()
|
||||
{
|
||||
UiaTracing::Signal::SelectionChanged();
|
||||
LOG_IF_FAILED(UiaRaiseAutomationEvent(this, UIA_Text_TextSelectionChangedEventId));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Signals the ui automation client that the terminal's output has changed and should be updated
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void HwndTerminalAutomationPeer::SignalTextChanged()
|
||||
{
|
||||
UiaTracing::Signal::TextChanged();
|
||||
LOG_IF_FAILED(UiaRaiseAutomationEvent(this, UIA_Text_TextChangedEventId));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Signals the ui automation client that the cursor's state has changed and should be updated
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void HwndTerminalAutomationPeer::SignalCursorChanged()
|
||||
{
|
||||
UiaTracing::Signal::CursorChanged();
|
||||
LOG_IF_FAILED(UiaRaiseAutomationEvent(this, UIA_Text_TextSelectionChangedEventId));
|
||||
}
|
||||
|
||||
void HwndTerminalAutomationPeer::NotifyNewOutput(std::wstring_view newOutput)
|
||||
{
|
||||
// Try to suppress any events (or event data)
|
||||
// that is just the keypress the user made
|
||||
auto sanitized{ Sanitize(newOutput) };
|
||||
while (!_keyEvents.empty() && IsReadable(sanitized))
|
||||
{
|
||||
if (til::toupper_ascii(sanitized.front()) == _keyEvents.front())
|
||||
{
|
||||
// the key event's character (i.e. the "A" key) matches
|
||||
// the output character (i.e. "a" or "A" text).
|
||||
// We can assume that the output character resulted from
|
||||
// the pressed key, so we can ignore it.
|
||||
sanitized = sanitized.substr(1);
|
||||
_keyEvents.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The output doesn't match,
|
||||
// so clear the input stack and
|
||||
// move on to fire the event.
|
||||
_keyEvents.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Suppress event if the remaining text is not readable
|
||||
if (!IsReadable(sanitized))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto sanitizedBstr = wil::make_bstr_nothrow(sanitized.c_str());
|
||||
static auto activityId = wil::make_bstr_nothrow(L"TerminalTextOutput");
|
||||
LOG_IF_FAILED(UiaRaiseNotificationEvent(this, NotificationKind_ActionCompleted, NotificationProcessing_All, sanitizedBstr.get(), activityId.get()));
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- HwndTerminalAutomationPeer.hpp
|
||||
|
||||
Abstract:
|
||||
- This module provides UI Automation access to the HwndTerminal
|
||||
to support both automation tests and accessibility (screen
|
||||
reading) applications. This mainly interacts with TermControlUiaProvider
|
||||
to allow for shared code with Windows Terminal accessibility providers.
|
||||
|
||||
Author(s):
|
||||
- Carlos Zamora (CaZamor) 2022
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../types/TermControlUiaProvider.hpp"
|
||||
#include "../types/IUiaEventDispatcher.h"
|
||||
#include "../types/IControlAccessibilityInfo.h"
|
||||
|
||||
class HwndTerminalAutomationPeer :
|
||||
public ::Microsoft::Console::Types::IUiaEventDispatcher,
|
||||
public ::Microsoft::Terminal::TermControlUiaProvider
|
||||
{
|
||||
public:
|
||||
void RecordKeyEvent(const WORD vkey);
|
||||
|
||||
IFACEMETHODIMP GetPropertyValue(_In_ PROPERTYID idProp,
|
||||
_Out_ VARIANT* pVariant) noexcept override;
|
||||
|
||||
#pragma region IUiaEventDispatcher
|
||||
void SignalSelectionChanged() override;
|
||||
void SignalTextChanged() override;
|
||||
void SignalCursorChanged() override;
|
||||
void NotifyNewOutput(std::wstring_view newOutput) override;
|
||||
#pragma endregion
|
||||
private:
|
||||
std::deque<wchar_t> _keyEvents;
|
||||
};
|
||||
@@ -15,9 +15,11 @@
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HwndTerminal.cpp" />
|
||||
<ClCompile Include="HwndTerminalAutomationPeer.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="HwndTerminal.hpp" />
|
||||
<ClInclude Include="HwndTerminalAutomationPeer.hpp" />
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -39,6 +41,9 @@
|
||||
<ProjectReference Include="$(SolutionDir)src\renderer\dx\lib\dx.vcxproj">
|
||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\renderer\uia\lib\uia.vcxproj">
|
||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf63}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
@@ -55,4 +60,4 @@
|
||||
<AdditionalDependencies>Uiautomationcore.lib;onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -24,6 +24,9 @@
|
||||
<ClCompile Include="HwndTerminal.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HwndTerminalAutomationPeer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
@@ -32,5 +35,8 @@
|
||||
<ClInclude Include="HwndTerminal.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HwndTerminalAutomationPeer.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -9,3 +9,4 @@
|
||||
#endif
|
||||
|
||||
#include <LibraryIncludes.h>
|
||||
#include <UIAutomationCore.h>
|
||||
@@ -25,37 +25,25 @@ static constexpr std::wstring_view VerbName{ L"WindowsTerminalOpenHere" };
|
||||
// failure from an earlier HRESULT.
|
||||
HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
|
||||
IBindCtx* /*pBindContext*/)
|
||||
try
|
||||
{
|
||||
wil::com_ptr_nothrow<IShellItem> psi;
|
||||
RETURN_IF_FAILED(GetBestLocationFromSelectionOrSite(psiItemArray, psi.put()));
|
||||
if (!psi)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
wil::unique_cotaskmem_string pszName;
|
||||
|
||||
if (psiItemArray == nullptr)
|
||||
{
|
||||
// get the current path from explorer.exe
|
||||
const auto path = this->_GetPathFromExplorer();
|
||||
|
||||
// no go, unable to get a reasonable path
|
||||
if (path.empty())
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
pszName = wil::make_cotaskmem_string(path.c_str(), path.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD count;
|
||||
psiItemArray->GetCount(&count);
|
||||
|
||||
winrt::com_ptr<IShellItem> psi;
|
||||
RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put()));
|
||||
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
|
||||
}
|
||||
RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
|
||||
|
||||
{
|
||||
wil::unique_process_information _piClient;
|
||||
STARTUPINFOEX siEx{ 0 };
|
||||
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
|
||||
|
||||
auto cmdline{ wil::str_printf<std::wstring>(LR"-("%s" -d %s)-", GetWtExePath().c_str(), QuoteAndEscapeCommandlineArg(pszName.get()).c_str()) };
|
||||
std::wstring cmdline;
|
||||
RETURN_IF_FAILED(wil::str_printf_nothrow(cmdline, LR"-("%s" -d %s)-", GetWtExePath().c_str(), QuoteAndEscapeCommandlineArg(pszName.get()).c_str()));
|
||||
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
|
||||
nullptr, // lpApplicationName
|
||||
cmdline.data(),
|
||||
@@ -72,6 +60,7 @@ HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN()
|
||||
|
||||
HRESULT OpenTerminalHere::GetToolTip(IShellItemArray* /*psiItemArray*/,
|
||||
LPWSTR* ppszInfoTip)
|
||||
@@ -109,21 +98,14 @@ HRESULT OpenTerminalHere::GetState(IShellItemArray* psiItemArray,
|
||||
// We however don't need to bother with any of that.
|
||||
|
||||
// If no item was selected when the context menu was opened and Explorer
|
||||
// is not at a valid path (e.g. This PC or Quick Access), we should hide
|
||||
// is not at a valid location (e.g. This PC or Quick Access), we should hide
|
||||
// the verb from the context menu.
|
||||
if (psiItemArray == nullptr)
|
||||
{
|
||||
const auto path = this->_GetPathFromExplorer();
|
||||
*pCmdState = path.empty() ? ECS_HIDDEN : ECS_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
winrt::com_ptr<IShellItem> psi;
|
||||
psiItemArray->GetItemAt(0, psi.put());
|
||||
SFGAOF attributes;
|
||||
const bool isFileSystemItem = (psi->GetAttributes(SFGAO_FILESYSTEM, &attributes) == S_OK);
|
||||
*pCmdState = isFileSystemItem ? ECS_ENABLED : ECS_HIDDEN;
|
||||
}
|
||||
wil::com_ptr_nothrow<IShellItem> psi;
|
||||
RETURN_IF_FAILED(GetBestLocationFromSelectionOrSite(psiItemArray, psi.put()));
|
||||
|
||||
SFGAOF attributes;
|
||||
const bool isFileSystemItem = psi && (psi->GetAttributes(SFGAO_FILESYSTEM, &attributes) == S_OK);
|
||||
*pCmdState = isFileSystemItem ? ECS_ENABLED : ECS_HIDDEN;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -160,102 +142,54 @@ HRESULT OpenTerminalHere::EnumSubCommands(IEnumExplorerCommand** ppEnum)
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
std::wstring OpenTerminalHere::_GetPathFromExplorer() const
|
||||
IFACEMETHODIMP OpenTerminalHere::SetSite(IUnknown* site) noexcept
|
||||
{
|
||||
using namespace std;
|
||||
using namespace winrt;
|
||||
|
||||
wstring path;
|
||||
HRESULT hr = NOERROR;
|
||||
|
||||
auto hwnd = ::GetForegroundWindow();
|
||||
if (hwnd == nullptr)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
TCHAR szName[MAX_PATH] = { 0 };
|
||||
::GetClassName(hwnd, szName, MAX_PATH);
|
||||
if (0 == StrCmp(szName, L"WorkerW") ||
|
||||
0 == StrCmp(szName, L"Progman"))
|
||||
{
|
||||
//special folder: desktop
|
||||
hr = ::SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, szName);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
path = szName;
|
||||
return path;
|
||||
}
|
||||
|
||||
if (0 != StrCmp(szName, L"CabinetWClass"))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
com_ptr<IShellWindows> shell;
|
||||
try
|
||||
{
|
||||
shell = create_instance<IShellWindows>(CLSID_ShellWindows, CLSCTX_ALL);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
//look like try_create_instance is not available no more
|
||||
}
|
||||
|
||||
if (shell == nullptr)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
com_ptr<IDispatch> disp;
|
||||
wil::unique_variant variant;
|
||||
variant.vt = VT_I4;
|
||||
|
||||
com_ptr<IWebBrowserApp> browser;
|
||||
// look for correct explorer window
|
||||
for (variant.intVal = 0;
|
||||
shell->Item(variant, disp.put()) == S_OK;
|
||||
variant.intVal++)
|
||||
{
|
||||
com_ptr<IWebBrowserApp> tmp;
|
||||
if (FAILED(disp->QueryInterface(tmp.put())))
|
||||
{
|
||||
disp = nullptr; // get rid of DEBUG non-nullptr warning
|
||||
continue;
|
||||
}
|
||||
|
||||
HWND tmpHWND = NULL;
|
||||
hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&tmpHWND));
|
||||
if (hwnd == tmpHWND)
|
||||
{
|
||||
browser = tmp;
|
||||
disp = nullptr; // get rid of DEBUG non-nullptr warning
|
||||
break; //found
|
||||
}
|
||||
|
||||
disp = nullptr; // get rid of DEBUG non-nullptr warning
|
||||
}
|
||||
|
||||
if (browser != nullptr)
|
||||
{
|
||||
wil::unique_bstr url;
|
||||
hr = browser->get_LocationURL(&url);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
wstring sUrl(url.get(), SysStringLen(url.get()));
|
||||
DWORD size = MAX_PATH;
|
||||
hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
path = szName;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
site_ = site;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP OpenTerminalHere::GetSite(REFIID riid, void** site) noexcept
|
||||
{
|
||||
RETURN_IF_FAILED(site_.query_to(riid, site));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT OpenTerminalHere::GetLocationFromSite(IShellItem** location) const noexcept
|
||||
{
|
||||
wil::assign_null_to_opt_param(location);
|
||||
|
||||
if (!site_)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<IServiceProvider> serviceProvider;
|
||||
RETURN_IF_FAILED(site_.query_to(serviceProvider.put()));
|
||||
wil::com_ptr_nothrow<IFolderView> folderView;
|
||||
RETURN_IF_FAILED(serviceProvider->QueryService(SID_SFolderView, IID_PPV_ARGS(folderView.put())));
|
||||
RETURN_IF_FAILED(folderView->GetFolder(IID_PPV_ARGS(location)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT OpenTerminalHere::GetBestLocationFromSelectionOrSite(IShellItemArray* psiArray, IShellItem** location) const noexcept
|
||||
{
|
||||
wil::com_ptr_nothrow<IShellItem> psi;
|
||||
if (psiArray)
|
||||
{
|
||||
DWORD count{};
|
||||
RETURN_IF_FAILED(psiArray->GetCount(&count));
|
||||
if (count) // Sometimes we get an array with a count of 0. Fall back to the site chain.
|
||||
{
|
||||
RETURN_IF_FAILED(psiArray->GetItemAt(0, psi.put()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!psi)
|
||||
{
|
||||
RETURN_IF_FAILED(GetLocationFromSite(psi.put()));
|
||||
}
|
||||
|
||||
RETURN_HR_IF(S_FALSE, !psi);
|
||||
RETURN_IF_FAILED(psi.copy_to(location));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ Author(s):
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include <conattrs.hpp>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
struct
|
||||
@@ -34,7 +32,7 @@ struct
|
||||
#else // DEV
|
||||
__declspec(uuid("52065414-e077-47ec-a3ac-1cc5455e1b54"))
|
||||
#endif
|
||||
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand>
|
||||
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand, IObjectWithSite>
|
||||
{
|
||||
#pragma region IExplorerCommand
|
||||
STDMETHODIMP Invoke(IShellItemArray* psiItemArray,
|
||||
@@ -52,9 +50,16 @@ struct
|
||||
STDMETHODIMP GetCanonicalName(GUID* pguidCommandName);
|
||||
STDMETHODIMP EnumSubCommands(IEnumExplorerCommand** ppEnum);
|
||||
#pragma endregion
|
||||
#pragma region IObjectWithSite
|
||||
IFACEMETHODIMP SetSite(IUnknown* site) noexcept;
|
||||
IFACEMETHODIMP GetSite(REFIID riid, void** site) noexcept;
|
||||
#pragma endregion
|
||||
|
||||
private:
|
||||
std::wstring _GetPathFromExplorer() const;
|
||||
HRESULT GetLocationFromSite(IShellItem** location) const noexcept;
|
||||
HRESULT GetBestLocationFromSelectionOrSite(IShellItemArray* psiArray, IShellItem** location) const noexcept;
|
||||
|
||||
wil::com_ptr_nothrow<IUnknown> site_;
|
||||
};
|
||||
|
||||
CoCreatableClass(OpenTerminalHere);
|
||||
|
||||
@@ -12,19 +12,12 @@ using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Xaml::Navigation;
|
||||
|
||||
namespace xaml = ::winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
App::App()
|
||||
{
|
||||
// This is the same trick that Initialize() is about to use to figure out whether we're coming
|
||||
// from a UWP context or from a Win32 context
|
||||
// See https://github.com/windows-toolkit/Microsoft.Toolkit.Win32/blob/52611c57d89554f357f281d0c79036426a7d9257/Microsoft.Toolkit.Win32.UI.XamlApplication/XamlApplication.cpp#L42
|
||||
const auto dispatcherQueue = ::winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
||||
if (dispatcherQueue)
|
||||
{
|
||||
_isUwp = true;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
|
||||
// Disable XAML's automatic backplating of text when in High Contrast
|
||||
@@ -33,12 +26,50 @@ namespace winrt::TerminalApp::implementation
|
||||
HighContrastAdjustment(::winrt::Windows::UI::Xaml::ApplicationHighContrastAdjustment::None);
|
||||
}
|
||||
|
||||
void App::Initialize()
|
||||
{
|
||||
const auto dispatcherQueue = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
||||
if (!dispatcherQueue)
|
||||
{
|
||||
_windowsXamlManager = xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
_isUwp = true;
|
||||
}
|
||||
}
|
||||
|
||||
AppLogic App::Logic()
|
||||
{
|
||||
static AppLogic logic;
|
||||
return logic;
|
||||
}
|
||||
|
||||
void App::Close()
|
||||
{
|
||||
if (_bIsClosed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_bIsClosed = true;
|
||||
|
||||
if (_windowsXamlManager)
|
||||
{
|
||||
_windowsXamlManager.Close();
|
||||
}
|
||||
_windowsXamlManager = nullptr;
|
||||
|
||||
Exit();
|
||||
{
|
||||
MSG msg = {};
|
||||
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
|
||||
{
|
||||
::DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched normally by the end user. Other entry points
|
||||
/// will be used such as when the application is launched to open a specific file.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "App.g.h"
|
||||
#include "App.base.h"
|
||||
#include <winrt/Windows.UI.Xaml.Hosting.h>
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
@@ -13,11 +14,22 @@ namespace winrt::TerminalApp::implementation
|
||||
public:
|
||||
App();
|
||||
void OnLaunched(const Windows::ApplicationModel::Activation::LaunchActivatedEventArgs&);
|
||||
void Initialize();
|
||||
|
||||
TerminalApp::AppLogic Logic();
|
||||
|
||||
void Close();
|
||||
|
||||
bool IsDisposed() const
|
||||
{
|
||||
return _bIsClosed;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _isUwp = false;
|
||||
winrt::Windows::UI::Xaml::Hosting::WindowsXamlManager _windowsXamlManager = nullptr;
|
||||
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider> _providers = winrt::single_threaded_vector<Windows::UI::Xaml::Markup::IXamlMetadataProvider>();
|
||||
bool _bIsClosed = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace TerminalApp
|
||||
{
|
||||
// ADD ARBITRARY APP LOGIC TO AppLogic.idl, NOT HERE.
|
||||
// This is for XAML platform setup only.
|
||||
[default_interface] runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
|
||||
[default_interface] runtimeclass App : Windows.UI.Xaml.Application, Windows.Foundation.IClosable
|
||||
{
|
||||
App();
|
||||
|
||||
AppLogic Logic { get; };
|
||||
|
||||
Boolean IsDisposed { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<Toolkit:XamlApplication x:Class="TerminalApp.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:TA="using:TerminalApp"
|
||||
xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<Application x:Class="TerminalApp.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:TA="using:TerminalApp"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<!--
|
||||
If you want to prove this works, then add `RequestedTheme="Light"` to
|
||||
the properties on the XamlApplication
|
||||
-->
|
||||
<Toolkit:XamlApplication.Resources>
|
||||
<Application.Resources>
|
||||
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
@@ -47,6 +46,7 @@
|
||||
|
||||
<!-- Suppress top padding -->
|
||||
<Thickness x:Key="TabViewHeaderPadding">9,0,5,0</Thickness>
|
||||
<Thickness x:Key="TabViewItemBorderThickness">1,1,1,0</Thickness>
|
||||
|
||||
<!-- Shadow that can be used by any control. -->
|
||||
<ThemeShadow x:Name="SharedShadow" />
|
||||
@@ -149,10 +149,13 @@
|
||||
See GH #12356 for more history on the subject.
|
||||
-->
|
||||
<SolidColorBrush x:Key="TabViewBackground"
|
||||
Color="#0a0a0a" />
|
||||
Color="#2e2e2e" />
|
||||
|
||||
<StaticResource x:Key="UnfocusedBorderBrush"
|
||||
ResourceKey="ApplicationPageBackgroundThemeBrush" />
|
||||
|
||||
<SolidColorBrush x:Key="SettingsUiTabBrush"
|
||||
Color="#0c0c0c" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
@@ -162,10 +165,13 @@
|
||||
GH #12398 has more history on this value, as well as GH #12400
|
||||
-->
|
||||
<SolidColorBrush x:Key="TabViewBackground"
|
||||
Color="#dadada" />
|
||||
Color="#e8e8e8" />
|
||||
|
||||
<StaticResource x:Key="UnfocusedBorderBrush"
|
||||
ResourceKey="ApplicationPageBackgroundThemeBrush" />
|
||||
|
||||
<SolidColorBrush x:Key="SettingsUiTabBrush"
|
||||
Color="#ffffff" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
@@ -183,6 +189,9 @@
|
||||
-->
|
||||
<StaticResource x:Key="TabViewBackground"
|
||||
ResourceKey="SystemColorButtonFaceColorBrush" />
|
||||
|
||||
<StaticResource x:Key="SettingsUiTabBrush"
|
||||
ResourceKey="SystemControlBackgroundBaseLowBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
@@ -192,5 +201,5 @@
|
||||
</ResourceDictionary>
|
||||
|
||||
|
||||
</Toolkit:XamlApplication.Resources>
|
||||
</Toolkit:XamlApplication>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@@ -166,6 +166,40 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleCloseOtherPanes(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto terminalTab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
const auto activePane = terminalTab->GetActivePane();
|
||||
if (terminalTab->GetRootPane() != activePane)
|
||||
{
|
||||
_UnZoomIfNeeded();
|
||||
|
||||
// Accumulate list of all unfocused leaf panes, ignore read-only panes
|
||||
std::vector<uint32_t> unfocusedPaneIds;
|
||||
const auto activePaneId = activePane->Id();
|
||||
terminalTab->GetRootPane()->WalkTree([&](auto&& p) {
|
||||
const auto id = p->Id();
|
||||
if (id.has_value() && id != activePaneId && !p->ContainsReadOnly())
|
||||
{
|
||||
unfocusedPaneIds.push_back(id.value());
|
||||
}
|
||||
});
|
||||
|
||||
if (!empty(unfocusedPaneIds))
|
||||
{
|
||||
// Start by removing the panes that were least recently added
|
||||
sort(begin(unfocusedPaneIds), end(unfocusedPaneIds), std::less<uint32_t>());
|
||||
_ClosePanes(terminalTab->get_weak(), std::move(unfocusedPaneIds));
|
||||
args.Handled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
args.Handled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleMovePane(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
@@ -201,10 +235,11 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
const auto& duplicateFromTab{ realArgs.SplitMode() == SplitType::Duplicate ? _GetFocusedTab() : nullptr };
|
||||
_SplitPane(realArgs.SplitDirection(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
::base::saturated_cast<float>(realArgs.SplitSize()),
|
||||
_MakePane(realArgs.TerminalArgs(), realArgs.SplitMode() == SplitType::Duplicate));
|
||||
_MakePane(realArgs.TerminalArgs(), duplicateFromTab));
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
@@ -1122,4 +1157,29 @@ namespace winrt::TerminalApp::implementation
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleColorSelection(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<ColorSelectionArgs>())
|
||||
{
|
||||
const auto res = _ApplyToActiveControls([&](auto& control) {
|
||||
control.ColorSelection(realArgs.Foreground(), realArgs.Background(), realArgs.MatchMode());
|
||||
});
|
||||
args.Handled(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleExpandSelectionToWord(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
const auto handled = control.ExpandSelectionToWord();
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,7 +809,11 @@ void AppCommandlineArgs::_addCommandsForArg(std::vector<Commandline>& commands,
|
||||
else
|
||||
{
|
||||
// Harder case: There was a match.
|
||||
const auto matchedFirstChar = match.position(0) == 0;
|
||||
|
||||
// Regex will include the last character of the string before the delimiter. (see _commandDelimiterRegex)
|
||||
// If the match was at the beginning of the string then there is no last character
|
||||
// so we can use the length of the match to determine if it was at the beginning.
|
||||
const auto matchedFirstChar = match[0].length() == 1;
|
||||
// If the match was at the beginning of the string, then the
|
||||
// next arg should be "", since there was no content before the
|
||||
// delimiter. Otherwise, add one, since the regex will include
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include <WtExeUtils.h>
|
||||
#include <wil/token_helpers.h >
|
||||
#include <wil/token_helpers.h>
|
||||
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
@@ -297,6 +297,37 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_root->SetFullscreen(true);
|
||||
}
|
||||
|
||||
// Both LoadSettings and ReloadSettings are supposed to call this function,
|
||||
// but LoadSettings skips it, so that the UI starts up faster.
|
||||
// Now that the UI is present we can do them with a less significant UX impact.
|
||||
_ProcessLazySettingsChanges();
|
||||
|
||||
FILETIME creationTime, exitTime, kernelTime, userTime, now;
|
||||
if (GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime, &userTime))
|
||||
{
|
||||
static constexpr auto asInteger = [](const FILETIME& f) {
|
||||
ULARGE_INTEGER i;
|
||||
i.LowPart = f.dwLowDateTime;
|
||||
i.HighPart = f.dwHighDateTime;
|
||||
return i.QuadPart;
|
||||
};
|
||||
static constexpr auto asSeconds = [](uint64_t v) {
|
||||
return v * 1e-7f;
|
||||
};
|
||||
|
||||
GetSystemTimeAsFileTime(&now);
|
||||
|
||||
const auto latency = asSeconds(asInteger(now) - asInteger(creationTime));
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"AppInitialized",
|
||||
TraceLoggingDescription("Event emitted once the app is initialized"),
|
||||
TraceLoggingFloat32(latency, "latency"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
});
|
||||
_root->Create();
|
||||
|
||||
@@ -313,7 +344,7 @@ namespace winrt::TerminalApp::implementation
|
||||
TraceLoggingDescription("Event emitted when the application is started"),
|
||||
TraceLoggingBool(_settings.GlobalSettings().ShowTabsInTitlebar(), "TabsInTitlebar"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
|
||||
void AppLogic::Quit()
|
||||
@@ -506,26 +537,8 @@ namespace winrt::TerminalApp::implementation
|
||||
if (keyboardServiceIsDisabled)
|
||||
{
|
||||
_root->ShowKeyboardServiceWarning();
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"KeyboardServiceWasDisabled",
|
||||
TraceLoggingDescription("Event emitted when the keyboard service is disabled, and we warned them about it"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For when the warning was disabled in the settings
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"KeyboardServiceWarningWasDisabledBySetting",
|
||||
TraceLoggingDescription("Event emitted when the user has disabled the KB service warning"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
}
|
||||
|
||||
if (FAILED(_settingsLoadedResult))
|
||||
{
|
||||
@@ -559,7 +572,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// not be noisy with this dialog if we failed for some reason.
|
||||
|
||||
// Open the service manager. This will return 0 if it failed.
|
||||
wil::unique_schandle hManager{ OpenSCManager(nullptr, nullptr, 0) };
|
||||
wil::unique_schandle hManager{ OpenSCManagerW(nullptr, nullptr, 0) };
|
||||
|
||||
if (LOG_LAST_ERROR_IF(!hManager.is_valid()))
|
||||
{
|
||||
@@ -567,8 +580,12 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// Get a handle to the keyboard service
|
||||
wil::unique_schandle hService{ OpenService(hManager.get(), TabletInputServiceKey.data(), SERVICE_QUERY_STATUS) };
|
||||
if (LOG_LAST_ERROR_IF(!hService.is_valid()))
|
||||
wil::unique_schandle hService{ OpenServiceW(hManager.get(), TabletInputServiceKey.data(), SERVICE_QUERY_STATUS) };
|
||||
|
||||
// Windows 11 doesn't have a TabletInputService.
|
||||
// (It was renamed to TextInputManagementService, because people kept thinking that a
|
||||
// service called "tablet-something" is system-irrelevant on PCs and can be disabled.)
|
||||
if (!hService.is_valid())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -847,15 +864,6 @@ namespace winrt::TerminalApp::implementation
|
||||
// happening during startup, it'll need to happen on a background thread.
|
||||
void AppLogic::LoadSettings()
|
||||
{
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"SettingsLoadStarted",
|
||||
TraceLoggingDescription("Event emitted before loading the settings"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
// Attempt to load the settings.
|
||||
// If it fails,
|
||||
// - use Default settings,
|
||||
@@ -871,23 +879,31 @@ namespace winrt::TerminalApp::implementation
|
||||
_settings = CascadiaSettings::LoadDefaults();
|
||||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> delta = end - start;
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"SettingsLoadComplete",
|
||||
TraceLoggingDescription("Event emitted when loading the settings is finished"),
|
||||
TraceLoggingFloat64(delta.count(), "Duration"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
_loadedInitialSettings = true;
|
||||
|
||||
// Register for directory change notification.
|
||||
_RegisterSettingsChange();
|
||||
}
|
||||
|
||||
// Call this function after loading your _settings.
|
||||
// It handles any CPU intensive settings updates (like updating the Jumplist)
|
||||
// which should thus only occur if the settings file actually changed.
|
||||
void AppLogic::_ProcessLazySettingsChanges()
|
||||
{
|
||||
const auto hash = _settings.Hash();
|
||||
const auto applicationState = ApplicationState::SharedInstance();
|
||||
const auto cachedHash = applicationState.SettingsHash();
|
||||
|
||||
// The hash might be empty if LoadAll() failed and we're dealing with the defaults settings object.
|
||||
// In that case we can just wait until the user fixed their settings or CascadiaSettings fixed
|
||||
// itself and either will soon trigger a settings reload.
|
||||
if (hash.empty() || hash == cachedHash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Jumplist::UpdateJumplist(_settings);
|
||||
applicationState.SettingsHash(hash);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1058,8 +1074,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_ApplyLanguageSettingChange();
|
||||
_RefreshThemeRoutine();
|
||||
_ApplyStartupTaskStateChange();
|
||||
|
||||
Jumplist::UpdateJumplist(_settings);
|
||||
_ProcessLazySettingsChanges();
|
||||
|
||||
_SettingsChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
@@ -192,6 +192,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void _OnLoaded(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
|
||||
[[nodiscard]] HRESULT _TryLoadSettings() noexcept;
|
||||
void _ProcessLazySettingsChanges();
|
||||
void _RegisterSettingsChange();
|
||||
fire_and_forget _DispatchReloadSettings();
|
||||
void _ReloadSettings();
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace winrt::TerminalApp::implementation
|
||||
TraceLoggingDescription("Event emitted when the Command Palette is opened"),
|
||||
TraceLoggingWideString(L"Action", "Mode", "which mode the palette was opened in"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -474,7 +474,13 @@ namespace winrt::TerminalApp::implementation
|
||||
return;
|
||||
}
|
||||
|
||||
auto focusedElementOrAncestor = Input::FocusManager::GetFocusedElement(this->XamlRoot()).try_as<DependencyObject>();
|
||||
auto root = this->XamlRoot();
|
||||
if (!root)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto focusedElementOrAncestor = Input::FocusManager::GetFocusedElement(root).try_as<DependencyObject>();
|
||||
while (focusedElementOrAncestor)
|
||||
{
|
||||
if (focusedElementOrAncestor == *this)
|
||||
@@ -524,6 +530,34 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void CommandPalette::_listItemSelectionChanged(const Windows::Foundation::IInspectable& /*sender*/, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& e)
|
||||
{
|
||||
// We don't care about...
|
||||
// - CommandlineMode: it doesn't have any selectable items in the list view
|
||||
// - TabSwitchMode: focus and selected item are in sync
|
||||
if (_currentMode == CommandPaletteMode::ActionMode || _currentMode == CommandPaletteMode::TabSearchMode)
|
||||
{
|
||||
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(_searchBox()) })
|
||||
{
|
||||
if (const auto selectedList = e.AddedItems(); selectedList.Size() > 0)
|
||||
{
|
||||
const auto selectedCommand = selectedList.GetAt(0);
|
||||
if (const auto filteredCmd = selectedCommand.try_as<TerminalApp::FilteredCommand>())
|
||||
{
|
||||
if (const auto paletteItem = filteredCmd.Item().try_as<TerminalApp::PaletteItem>())
|
||||
{
|
||||
automationPeer.RaiseNotificationEvent(
|
||||
Automation::Peers::AutomationNotificationKind::ItemAdded,
|
||||
Automation::Peers::AutomationNotificationProcessing::MostRecent,
|
||||
paletteItem.Name() + L" " + paletteItem.KeyChordText(),
|
||||
L"CommandPaletteSelectedItemChanged" /* unique name for this notification category */);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// This event is called when the user clicks on a ChevronLeft button right
|
||||
// next to the ParentCommandName (e.g. New Tab...) above the subcommands list.
|
||||
@@ -690,7 +724,7 @@ namespace winrt::TerminalApp::implementation
|
||||
TraceLoggingUInt32(searchTextLength, "SearchTextLength", "Number of characters in the search string"),
|
||||
TraceLoggingUInt32(nestedCommandDepth, "NestedCommandDepth", "the depth in the tree of commands for the dispatched action"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -758,7 +792,7 @@ namespace winrt::TerminalApp::implementation
|
||||
"CommandPaletteDispatchedCommandline",
|
||||
TraceLoggingDescription("Event emitted when the user runs a commandline in the Command Palette"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
if (const auto commandLinePaletteItem{ filteredCommand.value().Item().try_as<winrt::TerminalApp::CommandLinePaletteItem>() })
|
||||
{
|
||||
@@ -796,7 +830,7 @@ namespace winrt::TerminalApp::implementation
|
||||
"CommandPaletteDismissed",
|
||||
TraceLoggingDescription("Event emitted when the user dismisses the Command Palette without selecting an action"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -92,6 +92,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _listItemClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::ItemClickEventArgs& e);
|
||||
|
||||
void _listItemSelectionChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& e);
|
||||
|
||||
void _moveBackButtonClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs&);
|
||||
|
||||
void _updateFilteredActions();
|
||||
|
||||
@@ -402,6 +402,7 @@
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="_listItemClicked"
|
||||
ItemsSource="{x:Bind FilteredActions}"
|
||||
SelectionChanged="_listItemSelectionChanged"
|
||||
SelectionMode="Single" />
|
||||
|
||||
</Grid>
|
||||
|
||||
@@ -1764,6 +1764,9 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
|
||||
remainingChild->_firstChild = nullptr;
|
||||
remainingChild->_secondChild = nullptr;
|
||||
}
|
||||
|
||||
// Notify the discarded child that it was closed by its parent
|
||||
closedChild->_ClosedByParentHandlers();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst)
|
||||
|
||||
@@ -195,6 +195,7 @@ public:
|
||||
|
||||
void CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states);
|
||||
|
||||
WINRT_CALLBACK(ClosedByParent, winrt::delegate<>);
|
||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
|
||||
using gotFocusArgs = winrt::delegate<std::shared_ptr<Pane>, winrt::Windows::UI::Xaml::FocusState>;
|
||||
|
||||
@@ -23,9 +23,11 @@ namespace winrt
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
SettingsTab::SettingsTab(MainPage settingsUI)
|
||||
SettingsTab::SettingsTab(MainPage settingsUI,
|
||||
winrt::Windows::UI::Xaml::ElementTheme requestedTheme)
|
||||
{
|
||||
Content(settingsUI);
|
||||
_requestedTheme = requestedTheme;
|
||||
|
||||
_MakeTabViewItem();
|
||||
_CreateContextMenu();
|
||||
@@ -36,6 +38,10 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
auto settingsUI{ Content().as<MainPage>() };
|
||||
settingsUI.UpdateSettings(settings);
|
||||
|
||||
// Stash away the current requested theme of the app. We'll need that in
|
||||
// _BackgroundBrush() to do a theme-aware resource lookup
|
||||
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -105,4 +111,16 @@ namespace winrt::TerminalApp::implementation
|
||||
TabViewItem().IconSource(IconPathConverter::IconSourceMUX(glyph));
|
||||
}
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush()
|
||||
{
|
||||
// Look up the color we should use for the settings tab item from our
|
||||
// resources. This should only be used for when "terminalBackground" is
|
||||
// requested.
|
||||
static const auto key = winrt::box_value(L"SettingsUiTabBrush");
|
||||
// You can't just do a Application::Current().Resources().TryLookup
|
||||
// lookup, cause the app theme never changes! Do the hacky version
|
||||
// instead.
|
||||
return ThemeLookup(Application::Current().Resources(), _requestedTheme, key).try_as<winrt::Windows::UI::Xaml::Media::Brush>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace winrt::TerminalApp::implementation
|
||||
struct SettingsTab : SettingsTabT<SettingsTab, TabBase>
|
||||
{
|
||||
public:
|
||||
SettingsTab(winrt::Microsoft::Terminal::Settings::Editor::MainPage settingsUI);
|
||||
SettingsTab(winrt::Microsoft::Terminal::Settings::Editor::MainPage settingsUI,
|
||||
winrt::Windows::UI::Xaml::ElementTheme requestedTheme);
|
||||
|
||||
void UpdateSettings(Microsoft::Terminal::Settings::Model::CascadiaSettings settings);
|
||||
void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override;
|
||||
@@ -32,7 +33,11 @@ namespace winrt::TerminalApp::implementation
|
||||
std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions() const override;
|
||||
|
||||
private:
|
||||
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
|
||||
|
||||
void _MakeTabViewItem() override;
|
||||
winrt::fire_and_forget _CreateIcon();
|
||||
|
||||
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <LibraryResources.h>
|
||||
#include "TabBase.h"
|
||||
#include "TabBase.g.cpp"
|
||||
#include "Utils.h"
|
||||
#include "ColorHelper.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
@@ -252,4 +254,301 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
}
|
||||
|
||||
std::optional<winrt::Windows::UI::Color> TabBase::GetTabColor()
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void TabBase::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused,
|
||||
const til::color& tabRowColor)
|
||||
{
|
||||
_themeColor = focused;
|
||||
_unfocusedThemeColor = unfocused;
|
||||
_tabRowColor = tabRowColor;
|
||||
_RecalculateAndApplyTabColor();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This function dispatches a function to the UI thread to recalculate
|
||||
// what this tab's current background color should be. If a color is set,
|
||||
// it will apply the given color to the tab's background. Otherwise, it
|
||||
// will clear the tab's background color.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_RecalculateAndApplyTabColor()
|
||||
{
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
TabViewItem().Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [weakThis]() {
|
||||
auto ptrTab = weakThis.get();
|
||||
if (!ptrTab)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto tab{ ptrTab };
|
||||
|
||||
// GetTabColor will return the color set by the color picker, or the
|
||||
// color specified in the profile. If neither of those were set,
|
||||
// then look to _themeColor to see if there's a value there.
|
||||
// Otherwise, clear our color, falling back to the TabView defaults.
|
||||
const auto currentColor = tab->GetTabColor();
|
||||
if (currentColor.has_value())
|
||||
{
|
||||
tab->_ApplyTabColorOnUIThread(currentColor.value());
|
||||
}
|
||||
else if (tab->_themeColor != nullptr)
|
||||
{
|
||||
// Safely get the active control's brush.
|
||||
const Media::Brush terminalBrush{ tab->_BackgroundBrush() };
|
||||
|
||||
if (const auto themeBrush{ tab->_themeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) })
|
||||
{
|
||||
// ThemeColor.Evaluate will get us a Brush (because the
|
||||
// TermControl could have an acrylic BG, for example). Take
|
||||
// that brush, and get the color out of it. We don't really
|
||||
// want to have the tab items themselves be acrylic.
|
||||
tab->_ApplyTabColorOnUIThread(til::color{ ThemeColor::ColorFromBrush(themeBrush) });
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->_ClearTabBackgroundColor();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tab->_ClearTabBackgroundColor();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Applies the given color to the background of this tab's TabViewItem.
|
||||
// - Sets the tab foreground color depending on the luminance of
|
||||
// the background color
|
||||
// - This method should only be called on the UI thread.
|
||||
// Arguments:
|
||||
// - color: the color the user picked for their tab
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& color)
|
||||
{
|
||||
Media::SolidColorBrush selectedTabBrush{};
|
||||
Media::SolidColorBrush deselectedTabBrush{};
|
||||
Media::SolidColorBrush fontBrush{};
|
||||
Media::SolidColorBrush deselectedFontBrush{};
|
||||
Media::SolidColorBrush secondaryFontBrush{};
|
||||
Media::SolidColorBrush hoverTabBrush{};
|
||||
Media::SolidColorBrush subtleFillColorSecondaryBrush;
|
||||
Media::SolidColorBrush subtleFillColorTertiaryBrush;
|
||||
|
||||
// calculate the luminance of the current color and select a font
|
||||
// color based on that
|
||||
// see https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
||||
if (TerminalApp::ColorHelper::IsBrightColor(color))
|
||||
{
|
||||
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::Black();
|
||||
subtleFillColorSecondary.A = 0x09;
|
||||
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
|
||||
auto subtleFillColorTertiary = winrt::Windows::UI::Colors::Black();
|
||||
subtleFillColorTertiary.A = 0x06;
|
||||
subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto subtleFillColorSecondary = winrt::Windows::UI::Colors::White();
|
||||
subtleFillColorSecondary.A = 0x0F;
|
||||
subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary);
|
||||
auto subtleFillColorTertiary = winrt::Windows::UI::Colors::White();
|
||||
subtleFillColorTertiary.A = 0x0A;
|
||||
subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary);
|
||||
}
|
||||
|
||||
// The tab font should be based on the evaluated appearance of the tab color layered on tab row.
|
||||
const auto layeredTabColor = til::color{ color }.layer_over(_tabRowColor);
|
||||
if (TerminalApp::ColorHelper::IsBrightColor(layeredTabColor))
|
||||
{
|
||||
fontBrush.Color(winrt::Windows::UI::Colors::Black());
|
||||
auto secondaryFontColor = winrt::Windows::UI::Colors::Black();
|
||||
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L269
|
||||
secondaryFontColor.A = 0x9E;
|
||||
secondaryFontBrush.Color(secondaryFontColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
fontBrush.Color(winrt::Windows::UI::Colors::White());
|
||||
auto secondaryFontColor = winrt::Windows::UI::Colors::White();
|
||||
// For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L14
|
||||
secondaryFontColor.A = 0xC5;
|
||||
secondaryFontBrush.Color(secondaryFontColor);
|
||||
}
|
||||
|
||||
selectedTabBrush.Color(color);
|
||||
|
||||
// Start with the current tab color, set to Opacity=.3
|
||||
til::color deselectedTabColor{ color };
|
||||
deselectedTabColor = deselectedTabColor.with_alpha(77); // 255 * .3 = 77
|
||||
|
||||
// If we DON'T have a color set from the color picker, or the profile's
|
||||
// tabColor, but we do have a unfocused color in the theme, use the
|
||||
// unfocused theme color here instead.
|
||||
if (!GetTabColor().has_value() &&
|
||||
_unfocusedThemeColor != nullptr)
|
||||
{
|
||||
// Safely get the active control's brush.
|
||||
const Media::Brush terminalBrush{ _BackgroundBrush() };
|
||||
|
||||
// Get the color of the brush.
|
||||
if (const auto themeBrush{ _unfocusedThemeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) })
|
||||
{
|
||||
// We did figure out the brush. Get the color out of it. If it
|
||||
// was "accent" or "terminalBackground", then we're gonna set
|
||||
// the alpha to .3 manually here.
|
||||
// (ThemeColor::UnfocusedTabOpacity will do this for us). If the
|
||||
// user sets both unfocused and focused tab.background to
|
||||
// terminalBackground, this will allow for some differentiation
|
||||
// (and is generally just sensible).
|
||||
deselectedTabColor = til::color{ ThemeColor::ColorFromBrush(themeBrush) }.with_alpha(_unfocusedThemeColor.UnfocusedTabOpacity());
|
||||
}
|
||||
}
|
||||
|
||||
// currently if a tab has a custom color, a deselected state is
|
||||
// signified by using the same color with a bit of transparency
|
||||
deselectedTabBrush.Color(deselectedTabColor.with_alpha(255));
|
||||
deselectedTabBrush.Opacity(deselectedTabColor.a / 255.f);
|
||||
|
||||
hoverTabBrush.Color(color);
|
||||
hoverTabBrush.Opacity(0.6);
|
||||
|
||||
// Account for the color of the tab row when setting the color of text
|
||||
// on inactive tabs. Consider:
|
||||
// * black active tabs
|
||||
// * on a white tab row
|
||||
// * with a transparent inactive tab color
|
||||
//
|
||||
// We don't want that to result in white text on a white tab row for
|
||||
// inactive tabs.
|
||||
const auto deselectedActualColor = deselectedTabColor.layer_over(_tabRowColor);
|
||||
if (TerminalApp::ColorHelper::IsBrightColor(deselectedActualColor))
|
||||
{
|
||||
deselectedFontBrush.Color(winrt::Windows::UI::Colors::Black());
|
||||
}
|
||||
else
|
||||
{
|
||||
deselectedFontBrush.Color(winrt::Windows::UI::Colors::White());
|
||||
}
|
||||
|
||||
// Prior to MUX 2.7, we set TabViewItemHeaderBackground, but now we can
|
||||
// use TabViewItem().Background() for that. HOWEVER,
|
||||
// TabViewItem().Background() only sets the color of the tab background
|
||||
// when the TabViewItem is unselected. So we still need to set the other
|
||||
// properties ourselves.
|
||||
//
|
||||
// In GH#11294 we thought we'd still need to set
|
||||
// TabViewItemHeaderBackground manually, but GH#11382 discovered that
|
||||
// Background() was actually okay after all.
|
||||
TabViewItem().Background(deselectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush);
|
||||
|
||||
// Similarly, TabViewItem().Foreground() sets the color for the text
|
||||
// when the TabViewItem isn't selected, but not when it is hovered,
|
||||
// pressed, dragged, or selected, so we'll need to just set them all
|
||||
// anyways.
|
||||
TabViewItem().Foreground(deselectedFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForeground"), deselectedFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPressed"), fontBrush);
|
||||
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForeground"), deselectedFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPressed"), secondaryFontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPointerOver"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderPressedCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderPointerOverCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderSelectedCloseButtonForeground"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPressed"), subtleFillColorTertiaryBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPointerOver"), subtleFillColorSecondaryBrush);
|
||||
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundActiveTab"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundPressed"), fontBrush);
|
||||
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewButtonForegroundPointerOver"), fontBrush);
|
||||
|
||||
_RefreshVisualState();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Clear out any color we've set for the TabViewItem.
|
||||
// - This method should only be called on the UI thread.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_ClearTabBackgroundColor()
|
||||
{
|
||||
static const winrt::hstring keys[] = {
|
||||
L"TabViewItemHeaderBackground",
|
||||
L"TabViewItemHeaderBackgroundSelected",
|
||||
L"TabViewItemHeaderBackgroundPointerOver",
|
||||
L"TabViewItemHeaderBackgroundPressed",
|
||||
L"TabViewItemHeaderForeground",
|
||||
L"TabViewItemHeaderForegroundSelected",
|
||||
L"TabViewItemHeaderForegroundPointerOver",
|
||||
L"TabViewItemHeaderForegroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonForeground",
|
||||
L"TabViewItemHeaderCloseButtonForegroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonForegroundPointerOver",
|
||||
L"TabViewItemHeaderPressedCloseButtonForeground",
|
||||
L"TabViewItemHeaderPointerOverCloseButtonForeground",
|
||||
L"TabViewItemHeaderSelectedCloseButtonForeground",
|
||||
L"TabViewItemHeaderCloseButtonBackgroundPressed",
|
||||
L"TabViewItemHeaderCloseButtonBackgroundPointerOver",
|
||||
L"TabViewButtonForegroundActiveTab",
|
||||
L"TabViewButtonForegroundPressed",
|
||||
L"TabViewButtonForegroundPointerOver"
|
||||
};
|
||||
|
||||
// simply clear any of the colors in the tab's dict
|
||||
for (const auto& keyString : keys)
|
||||
{
|
||||
auto key = winrt::box_value(keyString);
|
||||
if (TabViewItem().Resources().HasKey(key))
|
||||
{
|
||||
TabViewItem().Resources().Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// GH#11382 DON'T set the background to null. If you do that, then the
|
||||
// tab won't be hit testable at all. Transparent, however, is a totally
|
||||
// valid hit test target. That makes sense.
|
||||
TabViewItem().Background(WUX::Media::SolidColorBrush{ Windows::UI::Colors::Transparent() });
|
||||
|
||||
_RefreshVisualState();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Toggles the visual state of the tab view item,
|
||||
// so that changes to the tab color are reflected immediately
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabBase::_RefreshVisualState()
|
||||
{
|
||||
if (TabViewItem().IsSelected())
|
||||
{
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
|
||||
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ namespace winrt::TerminalApp::implementation
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap);
|
||||
virtual std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions() const = 0;
|
||||
|
||||
virtual std::optional<winrt::Windows::UI::Color> GetTabColor();
|
||||
void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused,
|
||||
const til::color& tabRowColor);
|
||||
|
||||
WINRT_CALLBACK(RequestFocusActiveControl, winrt::delegate<void()>);
|
||||
|
||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
@@ -51,6 +56,10 @@ namespace winrt::TerminalApp::implementation
|
||||
Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr };
|
||||
winrt::hstring _keyChord{};
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::ThemeColor _themeColor{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::ThemeColor _unfocusedThemeColor{ nullptr };
|
||||
til::color _tabRowColor;
|
||||
|
||||
virtual void _CreateContextMenu();
|
||||
virtual winrt::hstring _CreateToolTipTitle();
|
||||
|
||||
@@ -63,6 +72,12 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::fire_and_forget _UpdateSwitchToTabKeyChord();
|
||||
void _UpdateToolTip();
|
||||
|
||||
void _RecalculateAndApplyTabColor();
|
||||
void _ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& color);
|
||||
void _ClearTabBackgroundColor();
|
||||
void _RefreshVisualState();
|
||||
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() = 0;
|
||||
|
||||
friend class ::TerminalAppLocalTests::TabTests;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,16 +20,11 @@
|
||||
Height="15"
|
||||
MinWidth="0"
|
||||
MinHeight="0"
|
||||
Margin="-7.5,0,8,0"
|
||||
Margin="3,0,8,0"
|
||||
IsActive="{x:Bind TabStatus.IsProgressRingActive, Mode=OneWay}"
|
||||
IsIndeterminate="{x:Bind TabStatus.IsProgressRingIndeterminate, Mode=OneWay}"
|
||||
Visibility="{x:Bind TabStatus.IsProgressRingActive, Mode=OneWay}"
|
||||
Value="{x:Bind TabStatus.ProgressValue, Mode=OneWay}" />
|
||||
<!--
|
||||
We want the progress ring to 'replace' the tab icon, but we don't have control
|
||||
over the tab icon here (the tab view item does) - so we hide the tab icon there
|
||||
and use a negative margin for the progress ring here to put it where the icon would be
|
||||
-->
|
||||
<FontIcon x:Name="HeaderBellIndicator"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "TerminalPage.h"
|
||||
#include "Utils.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../../inc/til/string.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
|
||||
@@ -85,34 +86,7 @@ namespace winrt::TerminalApp::implementation
|
||||
//
|
||||
// This call to _MakePane won't return nullptr, we already checked that
|
||||
// case above with the _maybeElevate call.
|
||||
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, existingConnection));
|
||||
|
||||
const auto tabCount = _tabs.Size();
|
||||
const auto usedManualProfile = (newTerminalArgs != nullptr) &&
|
||||
(newTerminalArgs.ProfileIndex() != nullptr ||
|
||||
newTerminalArgs.Profile().empty());
|
||||
|
||||
// Lookup the name of the color scheme used by this profile.
|
||||
const auto scheme = _settings.GetColorSchemeForProfile(profile);
|
||||
// If they explicitly specified `null` as the scheme (indicating _no_ scheme), log
|
||||
// that as the empty string.
|
||||
const auto schemeName = scheme ? scheme.Name() : L"\0";
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
|
||||
"TabInformation",
|
||||
TraceLoggingDescription("Event emitted upon new tab creation in TerminalApp"),
|
||||
TraceLoggingUInt32(1u, "EventVer", "Version of this event"),
|
||||
TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"),
|
||||
TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"),
|
||||
TraceLoggingGuid(profile.Guid(), "ProfileGuid", "The GUID of the profile spawned in the new tab"),
|
||||
TraceLoggingBool(settings.DefaultSettings().UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"),
|
||||
TraceLoggingFloat64(settings.DefaultSettings().Opacity(), "TintOpacity", "Opacity preference from the settings"),
|
||||
TraceLoggingWideString(settings.DefaultSettings().FontFace().c_str(), "FontFace", "Font face chosen in the settings"),
|
||||
TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
_CreateNewTabFromPane(_MakePane(newTerminalArgs, nullptr, existingConnection));
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
@@ -363,7 +337,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// In the future, it may be preferable to just duplicate the
|
||||
// current control's live settings (which will include changes
|
||||
// made through VT).
|
||||
_CreateNewTabFromPane(_MakePane(nullptr, true, nullptr));
|
||||
_CreateNewTabFromPane(_MakePane(nullptr, tab, nullptr));
|
||||
|
||||
const auto runtimeTabText{ tab.GetTabText() };
|
||||
if (!runtimeTabText.empty())
|
||||
@@ -386,7 +360,7 @@ namespace winrt::TerminalApp::implementation
|
||||
try
|
||||
{
|
||||
_SetFocusedTab(tab);
|
||||
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, true));
|
||||
_SplitPane(tab, SplitDirection::Automatic, 0.5f, _MakePane(nullptr, tab));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -419,7 +393,9 @@ namespace winrt::TerminalApp::implementation
|
||||
// GH#11356 - we can't use the UWP apis for writing the file,
|
||||
// because they don't work elevated (shocker) So just use the
|
||||
// shell32 file picker manually.
|
||||
path = co_await SaveFilePicker(*_hostingHwnd, [control](auto&& dialog) {
|
||||
std::wstring filename{ tab.Title() };
|
||||
filename = til::clean_filename(filename);
|
||||
path = co_await SaveFilePicker(*_hostingHwnd, [filename = std::move(filename)](auto&& dialog) {
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidExportFile));
|
||||
try
|
||||
{
|
||||
@@ -433,7 +409,7 @@ namespace winrt::TerminalApp::implementation
|
||||
THROW_IF_FAILED(dialog->SetDefaultExtension(L"txt"));
|
||||
|
||||
// Default to using the tab title as the file name
|
||||
THROW_IF_FAILED(dialog->SetFileName((control.Title() + L".txt").c_str()));
|
||||
THROW_IF_FAILED(dialog->SetFileName((filename + L".txt").c_str()));
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -763,6 +739,65 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Disables read-only mode on pane if the user wishes to close it and read-only mode is enabled.
|
||||
// Arguments:
|
||||
// - pane: the pane that is about to be closed.
|
||||
// Return Value:
|
||||
// - bool indicating whether the (read-only) pane can be closed.
|
||||
winrt::Windows::Foundation::IAsyncOperation<bool> TerminalPage::_PaneConfirmCloseReadOnly(std::shared_ptr<Pane> pane)
|
||||
{
|
||||
if (pane->ContainsReadOnly())
|
||||
{
|
||||
auto warningResult = co_await _ShowCloseReadOnlyDialog();
|
||||
|
||||
// If the user didn't explicitly click on close tab - leave
|
||||
if (warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
// Clean read-only mode to prevent additional prompt if closing the pane triggers closing of a hosting tab
|
||||
pane->WalkTree([](auto p) {
|
||||
if (const auto control{ p->GetTerminalControl() })
|
||||
{
|
||||
if (control.ReadOnly())
|
||||
{
|
||||
control.ToggleReadOnly();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
co_return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Removes the pane from the tab it belongs to.
|
||||
// Arguments:
|
||||
// - pane: the pane to close.
|
||||
void TerminalPage::_HandleClosePaneRequested(std::shared_ptr<Pane> pane)
|
||||
{
|
||||
// Build the list of actions to recreate the closed pane,
|
||||
// BuildStartupActions returns the "first" pane and the rest of
|
||||
// its actions are assuming that first pane has been created first.
|
||||
// This doesn't handle refocusing anything in particular, the
|
||||
// result will be that the last pane created is focused. In the
|
||||
// case of a single pane that is the desired behavior anyways.
|
||||
auto state = pane->BuildStartupActions(0, 1);
|
||||
{
|
||||
ActionAndArgs splitPaneAction{};
|
||||
splitPaneAction.Action(ShortcutAction::SplitPane);
|
||||
SplitPaneArgs splitPaneArgs{ SplitDirection::Automatic, state.firstPane->GetTerminalArgsForPane() };
|
||||
splitPaneAction.Args(splitPaneArgs);
|
||||
|
||||
state.args.emplace(state.args.begin(), std::move(splitPaneAction));
|
||||
}
|
||||
_AddPreviouslyClosedPaneOrTab(std::move(state.args));
|
||||
|
||||
// If specified, detach before closing to directly update the pane structure
|
||||
pane->Close();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Close the currently focused pane. If the pane is the last pane in the
|
||||
// tab, the tab will also be closed. This will happen when we handle the
|
||||
@@ -775,46 +810,10 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (const auto pane{ terminalTab->GetActivePane() })
|
||||
{
|
||||
if (pane->ContainsReadOnly())
|
||||
if (co_await _PaneConfirmCloseReadOnly(pane))
|
||||
{
|
||||
auto warningResult = co_await _ShowCloseReadOnlyDialog();
|
||||
|
||||
// If the user didn't explicitly click on close tab - leave
|
||||
if (warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
// Clean read-only mode to prevent additional prompt if closing the pane triggers closing of a hosting tab
|
||||
pane->WalkTree([](auto p) {
|
||||
if (const auto control{ p->GetTerminalControl() })
|
||||
{
|
||||
if (control.ReadOnly())
|
||||
{
|
||||
control.ToggleReadOnly();
|
||||
}
|
||||
}
|
||||
});
|
||||
_HandleClosePaneRequested(pane);
|
||||
}
|
||||
|
||||
// Build the list of actions to recreate the closed pane,
|
||||
// BuildStartupActions returns the "first" pane and the rest of
|
||||
// its actions are assuming that first pane has been created first.
|
||||
// This doesn't handle refocusing anything in particular, the
|
||||
// result will be that the last pane created is focused. In the
|
||||
// case of a single pane that is the desired behavior anyways.
|
||||
auto state = pane->BuildStartupActions(0, 1);
|
||||
{
|
||||
ActionAndArgs splitPaneAction{};
|
||||
splitPaneAction.Action(ShortcutAction::SplitPane);
|
||||
SplitPaneArgs splitPaneArgs{ SplitDirection::Automatic, state.firstPane->GetTerminalArgsForPane() };
|
||||
splitPaneAction.Args(splitPaneArgs);
|
||||
|
||||
state.args.emplace(state.args.begin(), std::move(splitPaneAction));
|
||||
}
|
||||
_AddPreviouslyClosedPaneOrTab(std::move(state.args));
|
||||
|
||||
pane->Close();
|
||||
}
|
||||
}
|
||||
else if (auto index{ _GetFocusedTabIndex() })
|
||||
@@ -827,6 +826,38 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Close all panes with the given IDs sequentially.
|
||||
// Arguments:
|
||||
// - weakTab: weak reference to the tab that the pane belongs to.
|
||||
// - paneIds: collection of the IDs of the panes that are marked for removal.
|
||||
void TerminalPage::_ClosePanes(weak_ref<TerminalTab> weakTab, std::vector<uint32_t> paneIds)
|
||||
{
|
||||
if (auto strongTab{ weakTab.get() })
|
||||
{
|
||||
// Close all unfocused panes one by one
|
||||
while (!paneIds.empty())
|
||||
{
|
||||
const auto id = paneIds.back();
|
||||
paneIds.pop_back();
|
||||
|
||||
if (const auto pane{ strongTab->GetRootPane()->FindPane(id) })
|
||||
{
|
||||
pane->ClosedByParent([ids{ std::move(paneIds) }, weakThis{ get_weak() }, weakTab]() {
|
||||
if (auto strongThis{ weakThis.get() })
|
||||
{
|
||||
strongThis->_ClosePanes(weakTab, std::move(ids));
|
||||
}
|
||||
});
|
||||
|
||||
// Close the pane which will eventually trigger the closed by parent event
|
||||
_HandleClosePaneRequested(pane);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Close the tab at the given index.
|
||||
void TerminalPage::_CloseTabAtIndex(uint32_t index)
|
||||
|
||||
@@ -19,18 +19,11 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
|
||||
<TerminalMUX>true</TerminalMUX>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
|
||||
on being compiled with RTTI (/GR). -->
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- HERE BE DRAGONS:
|
||||
@@ -388,6 +381,14 @@
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
</Reference>
|
||||
<Reference Include="$(WindowsSDK_MetadataPathVersioned)\Windows.UI.Xaml.Hosting.HostingContract\*\*.winmd">
|
||||
<WinMDFile>true</WinMDFile>
|
||||
<CopyLocal>false</CopyLocal>
|
||||
<ReferenceGrouping>$(TargetPlatformMoniker)</ReferenceGrouping>
|
||||
<ReferenceGroupingDisplayName>$(TargetPlatformDisplayName)</ReferenceGroupingDisplayName>
|
||||
<ResolvedFrom>CppWinRTImplicitlyExpandTargetPlatform</ResolvedFrom>
|
||||
<IsSystemReference>True</IsSystemReference>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<!-- ====================== Compiler & Linker Flags ===================== -->
|
||||
<ItemDefinitionGroup>
|
||||
@@ -407,13 +408,6 @@
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.$(TerminalMUXVersion)\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<!--
|
||||
By default, the PRI file will contain resource paths beginning with the
|
||||
project name. Since we enabled XBF embedding, this *also* includes App.xbf.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user