mirror of
https://github.com/microsoft/terminal.git
synced 2026-05-19 13:06:47 +00:00
Compare commits
34 Commits
niels9001/
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a665ae533 | ||
|
|
479c6c9f08 | ||
|
|
0d349df21d | ||
|
|
43ecfb7e7b | ||
|
|
e59afac7c5 | ||
|
|
b742e93285 | ||
|
|
b777c51340 | ||
|
|
5923cf3261 | ||
|
|
5b618711eb | ||
|
|
5f8546ed0e | ||
|
|
f4ce6939a0 | ||
|
|
2438ef4135 | ||
|
|
71d5845195 | ||
|
|
23cf44e81f | ||
|
|
7a987d6b69 | ||
|
|
5a8b769097 | ||
|
|
4bca00645d | ||
|
|
542a70905c | ||
|
|
1a8494f969 | ||
|
|
f4dc55df29 | ||
|
|
a419898e60 | ||
|
|
c36ec70b1c | ||
|
|
584767ada6 | ||
|
|
63d35d513f | ||
|
|
da8775b766 | ||
|
|
4f06371278 | ||
|
|
687cdda756 | ||
|
|
9c67d94016 | ||
|
|
3d1ad436aa | ||
|
|
9ab0c75fb7 | ||
|
|
48e37a518b | ||
|
|
8d24f236d2 | ||
|
|
861683c6d3 | ||
|
|
24fe6103e0 |
15
.github/actions/spelling/README.md
vendored
Normal file
15
.github/actions/spelling/README.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# check-spelling/check-spelling configuration
|
||||
|
||||
File | Purpose | Format | Info
|
||||
-|-|-|-
|
||||
[allow/*.txt](allow/) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow)
|
||||
[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)
|
||||
|
||||
Note: you can replace any of these files with a directory by the same name (minus the suffix)
|
||||
and then include multiple files inside that directory (with that suffix) to merge multiple files together.
|
||||
38
.github/actions/spelling/advice.md
vendored
38
.github/actions/spelling/advice.md
vendored
@@ -1,4 +1,4 @@
|
||||
<!-- markdownlint-disable MD033 MD041 -->
|
||||
<!-- See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice --> <!-- markdownlint-disable MD033 MD041 -->
|
||||
<details>
|
||||
<summary>
|
||||
:pencil2: Contributor please read this
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
|
||||
|
||||
:warning: The command is written for posix shells. You can copy the contents of each `perl` command excluding the outer `'` marks and dropping any `'"`/`"'` quotation mark pairs into a file and then run `perl file.pl` from the root of the repository to run the code. Alternatively, you can manually insert the items...
|
||||
:warning: The command is written for posix shells. If it doesn't work for you, you can manually _add_ (one word per line) / _remove_ items to `expect.txt` and the `excludes.txt` files.
|
||||
|
||||
If the listed items are:
|
||||
|
||||
@@ -20,31 +20,29 @@ 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 you see a bunch of garbage</summary>
|
||||
|
||||
If it relates to a ...
|
||||
<details><summary>well-formed pattern</summary>
|
||||
<details><summary>If the flagged items are :exploding_head: false positives</summary>
|
||||
|
||||
See if there's a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it.
|
||||
If items relate to a ...
|
||||
* binary file (or some other file you wouldn't want to check at all).
|
||||
|
||||
If not, try writing one and adding it to a `patterns/{file}.txt`.
|
||||
Please add a file path to the `excludes.txt` file matching the containing file.
|
||||
|
||||
Patterns are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
|
||||
|
||||
Note that patterns can't match multiline strings.
|
||||
</details>
|
||||
<details><summary>binary-ish string</summary>
|
||||
|
||||
Please add a file path to the `excludes.txt` file instead of just accepting the garbage.
|
||||
|
||||
File paths are Perl 5 Regular Expressions - you can [test](
|
||||
File paths are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files.
|
||||
|
||||
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
|
||||
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
|
||||
../tree/HEAD/README.md) (on whichever branch you're using).
|
||||
</details>
|
||||
|
||||
|
||||
* well-formed pattern.
|
||||
|
||||
If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it,
|
||||
try adding it to the `patterns.txt` file.
|
||||
|
||||
Patterns are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
|
||||
|
||||
Note that patterns can't match multiline strings.
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
24
.github/actions/spelling/allow/allow.txt
vendored
24
.github/actions/spelling/allow/allow.txt
vendored
@@ -1,20 +1,21 @@
|
||||
admins
|
||||
apc
|
||||
allcolors
|
||||
Apc
|
||||
bsd
|
||||
apc
|
||||
breadcrumb
|
||||
breadcrumbs
|
||||
bsd
|
||||
calt
|
||||
CMMI
|
||||
ccmp
|
||||
changelog
|
||||
clickable
|
||||
clig
|
||||
CMMI
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
dcs
|
||||
Dcs
|
||||
dcs
|
||||
dialytika
|
||||
dje
|
||||
downside
|
||||
@@ -26,36 +27,43 @@ EDDC
|
||||
Enum'd
|
||||
Fitt
|
||||
formattings
|
||||
FTCS
|
||||
ftp
|
||||
fvar
|
||||
gantt
|
||||
gcc
|
||||
geeksforgeeks
|
||||
ghe
|
||||
github
|
||||
gje
|
||||
godbolt
|
||||
hostname
|
||||
hostnames
|
||||
https
|
||||
hyperlink
|
||||
hyperlinking
|
||||
hyperlinks
|
||||
iconify
|
||||
img
|
||||
inlined
|
||||
It'd
|
||||
kje
|
||||
libfuzzer
|
||||
libuv
|
||||
liga
|
||||
lje
|
||||
Llast
|
||||
llvm
|
||||
Lmid
|
||||
locl
|
||||
lol
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
minimalistic
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
noreply
|
||||
nje
|
||||
noreply
|
||||
ogonek
|
||||
@@ -76,13 +84,16 @@ runtimes
|
||||
shcha
|
||||
slnt
|
||||
Sos
|
||||
ssh
|
||||
timeline
|
||||
timelines
|
||||
timestamped
|
||||
TLDR
|
||||
tokenizes
|
||||
tonos
|
||||
toolset
|
||||
tshe
|
||||
ubuntu
|
||||
uiatextrange
|
||||
UIs
|
||||
und
|
||||
@@ -91,6 +102,7 @@ versioned
|
||||
vsdevcmd
|
||||
We'd
|
||||
wildcards
|
||||
XBox
|
||||
YBox
|
||||
yeru
|
||||
zhe
|
||||
allcolors
|
||||
|
||||
21
.github/actions/spelling/allow/apis.txt
vendored
21
.github/actions/spelling/allow/apis.txt
vendored
@@ -5,6 +5,7 @@ aclapi
|
||||
alignas
|
||||
alignof
|
||||
APPLYTOSUBMENUS
|
||||
appxrecipe
|
||||
bitfield
|
||||
bitfields
|
||||
BUILDBRANCH
|
||||
@@ -14,6 +15,7 @@ BYCOMMAND
|
||||
BYPOSITION
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
CLOSEAPP
|
||||
cmdletbinding
|
||||
COLORPROPERTY
|
||||
colspan
|
||||
@@ -28,9 +30,14 @@ dataobject
|
||||
dcomp
|
||||
DERR
|
||||
dlldata
|
||||
DNE
|
||||
DONTADDTORECENT
|
||||
DWMSBT
|
||||
DWMWA
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
endfor
|
||||
ENDSESSION
|
||||
enumset
|
||||
environstrings
|
||||
EXPCMDFLAGS
|
||||
@@ -70,6 +77,7 @@ IDirect
|
||||
IExplorer
|
||||
IFACEMETHOD
|
||||
IFile
|
||||
IGraphics
|
||||
IInheritable
|
||||
IMap
|
||||
IMonarch
|
||||
@@ -84,6 +92,7 @@ istream
|
||||
IStringable
|
||||
ITab
|
||||
ITaskbar
|
||||
itow
|
||||
IUri
|
||||
IVirtual
|
||||
KEYSELECT
|
||||
@@ -95,11 +104,15 @@ lround
|
||||
Lsa
|
||||
lsass
|
||||
LSHIFT
|
||||
LTGRAY
|
||||
MAINWINDOW
|
||||
memchr
|
||||
memicmp
|
||||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
mmeapi
|
||||
MOUSELEAVE
|
||||
mov
|
||||
mptt
|
||||
@@ -135,14 +148,17 @@ OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PATINVERT
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
ptstr
|
||||
QUERYENDSESSION
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
ROOTOWNER
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
@@ -152,6 +168,7 @@ serializer
|
||||
SETVERSION
|
||||
SHELLEXECUTEINFOW
|
||||
shobjidl
|
||||
SHOWHIDE
|
||||
SHOWMINIMIZED
|
||||
SHOWTIP
|
||||
SINGLEUSE
|
||||
@@ -172,6 +189,8 @@ Stubless
|
||||
Subheader
|
||||
Subpage
|
||||
syscall
|
||||
SYSTEMBACKDROP
|
||||
TABROW
|
||||
TASKBARCREATED
|
||||
TBPF
|
||||
THEMECHANGED
|
||||
@@ -191,6 +210,8 @@ UOI
|
||||
UPDATEINIFILE
|
||||
userenv
|
||||
USEROBJECTFLAGS
|
||||
Viewbox
|
||||
virtualalloc
|
||||
wcsstr
|
||||
wcstoui
|
||||
winmain
|
||||
|
||||
8
.github/actions/spelling/allow/names.txt
vendored
8
.github/actions/spelling/allow/names.txt
vendored
@@ -1,8 +1,10 @@
|
||||
Anup
|
||||
austdi
|
||||
arkthur
|
||||
Ballmer
|
||||
bhoj
|
||||
Bhojwani
|
||||
Bluloco
|
||||
carlos
|
||||
dhowett
|
||||
Diviness
|
||||
@@ -22,6 +24,7 @@ Hernan
|
||||
Howett
|
||||
Illhardt
|
||||
iquilezles
|
||||
italo
|
||||
jantari
|
||||
jerrysh
|
||||
Kaiyu
|
||||
@@ -35,7 +38,9 @@ leonmsft
|
||||
Lepilleur
|
||||
lhecker
|
||||
lukesampson
|
||||
Macbook
|
||||
Manandhar
|
||||
masserano
|
||||
mbadolato
|
||||
Mehrain
|
||||
menger
|
||||
@@ -64,10 +69,13 @@ Rincewind
|
||||
rprichard
|
||||
Schoonover
|
||||
shadertoy
|
||||
Shomnipotence
|
||||
simioni
|
||||
Somuah
|
||||
sonph
|
||||
sonpham
|
||||
stakx
|
||||
talo
|
||||
thereses
|
||||
Walisch
|
||||
WDX
|
||||
|
||||
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-)/
|
||||
46
.github/actions/spelling/excludes.txt
vendored
46
.github/actions/spelling/excludes.txt
vendored
@@ -1,28 +1,39 @@
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
|
||||
(?:(?i)\.png$)
|
||||
(?:^|/)(?i)COPYRIGHT
|
||||
(?:^|/)(?i)LICEN[CS]E
|
||||
(?:^|/)3rdparty/
|
||||
(?:^|/)dirs$
|
||||
(?:^|/)go\.mod$
|
||||
(?:^|/)go\.sum$
|
||||
(?:^|/)package-lock\.json$
|
||||
(?:^|/)package(?:-lock|)\.json$
|
||||
(?:^|/)sources(?:|\.dep)$
|
||||
SUMS$
|
||||
(?:^|/)vendor/
|
||||
\.a$
|
||||
\.ai$
|
||||
\.avi$
|
||||
\.bmp$
|
||||
\.bz2$
|
||||
\.cer$
|
||||
\.class$
|
||||
\.crl$
|
||||
\.crt$
|
||||
\.csr$
|
||||
\.dll$
|
||||
\.docx?$
|
||||
\.drawio$
|
||||
\.DS_Store$
|
||||
\.eot$
|
||||
\.eps$
|
||||
\.exe$
|
||||
\.gif$
|
||||
\.gitattributes$
|
||||
\.graffle$
|
||||
\.gz$
|
||||
\.icns$
|
||||
\.ico$
|
||||
\.jar$
|
||||
\.jks$
|
||||
\.jpeg$
|
||||
\.jpg$
|
||||
\.key$
|
||||
@@ -30,28 +41,53 @@ SUMS$
|
||||
\.lock$
|
||||
\.map$
|
||||
\.min\..
|
||||
\.mod$
|
||||
\.mp3$
|
||||
\.mp4$
|
||||
\.o$
|
||||
\.ocf$
|
||||
\.otf$
|
||||
\.pbxproj$
|
||||
\.pdf$
|
||||
\.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/
|
||||
^doc/reference/master-sequence-list.csv$
|
||||
@@ -76,6 +112,6 @@ SUMS$
|
||||
^src/tools/texttests/fira\.txt$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^\.github/actions/spelling/
|
||||
^\.gitignore$
|
||||
^\XamlStyler.json$
|
||||
^tools/ReleaseEngineering/ServicingPipeline.ps1$
|
||||
ignore$
|
||||
SUMS$
|
||||
|
||||
8
.github/actions/spelling/expect/alphabet.txt
vendored
8
.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
|
||||
@@ -33,7 +26,6 @@ QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
||||
qrstuvwxyz
|
||||
qwerty
|
||||
QWERTYUIOP
|
||||
qwertyuiopasdfg
|
||||
YYYYYYYDDDDDDDDDDD
|
||||
ZAAZZ
|
||||
|
||||
888
.github/actions/spelling/expect/expect.txt
vendored
888
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
23
.github/actions/spelling/expect/web.txt
vendored
23
.github/actions/spelling/expect/web.txt
vendored
@@ -1,29 +1,6 @@
|
||||
http
|
||||
www
|
||||
easyrgb
|
||||
php
|
||||
ecma
|
||||
rapidtables
|
||||
WCAG
|
||||
freedesktop
|
||||
ycombinator
|
||||
robertelder
|
||||
kovidgoyal
|
||||
leonerd
|
||||
fixterms
|
||||
winui
|
||||
appshellintegration
|
||||
mdtauk
|
||||
cppreference
|
||||
gfycat
|
||||
Guake
|
||||
azurewebsites
|
||||
askubuntu
|
||||
dostips
|
||||
viewtopic
|
||||
rosettacode
|
||||
Rexx
|
||||
tldp
|
||||
HOWTO
|
||||
uwspace
|
||||
uwaterloo
|
||||
|
||||
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# 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
|
||||
|
||||
# s.b. GitLab
|
||||
\bGitlab\b
|
||||
|
||||
# s.b. JavaScript
|
||||
\bJavascript\b
|
||||
|
||||
# s.b. Microsoft
|
||||
\bMicroSoft\b
|
||||
|
||||
# s.b. another
|
||||
\ban[- ]other\b
|
||||
|
||||
# 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
|
||||
|
||||
# s.b. otherwise
|
||||
\bother[- ]wise\b
|
||||
|
||||
# s.b. nonexistent
|
||||
\bnon existing\b
|
||||
\b[Nn]o[nt][- ]existent\b
|
||||
|
||||
# s.b. preexisting
|
||||
[Pp]re[- ]existing
|
||||
|
||||
# s.b. preempt
|
||||
[Pp]re[- ]empt\b
|
||||
|
||||
# s.b. preemptively
|
||||
[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
|
||||
82
.github/actions/spelling/patterns/patterns.txt
vendored
82
.github/actions/spelling/patterns/patterns.txt
vendored
@@ -1,11 +1,6 @@
|
||||
https://(?:(?:[-a-zA-Z0-9?&=]*\.|)microsoft\.com)/[-a-zA-Z0-9?&=_#\/.]*
|
||||
https://aka\.ms/[-a-zA-Z0-9?&=\/_]*
|
||||
https://www\.itscj\.ipsj\.or\.jp/iso-ir/[-0-9]+\.pdf
|
||||
https://www\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]*
|
||||
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
|
||||
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.+]*
|
||||
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
|
||||
|
||||
https?://\S+
|
||||
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
|
||||
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)
|
||||
(?:0[Xx]|\\x|U\+|#)[a-f0-9A-FGgRr]{2,}[Uu]?[Ll]{0,2}\b
|
||||
@@ -28,3 +23,74 @@ vcvars\w*
|
||||
ROY\sG\.\sBIV
|
||||
!(?:(?i)ESC)!\[
|
||||
!(?:(?i)CSI)!(?:\d+(?:;\d+|)m|[ABCDF])
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
|
||||
28
.github/actions/spelling/reject.txt
vendored
28
.github/actions/spelling/reject.txt
vendored
@@ -1,22 +1,12 @@
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
^spae$
|
||||
^spaebook$
|
||||
^spaecraft$
|
||||
^spaed$
|
||||
^spaedom$
|
||||
^spaeing$
|
||||
^spaeings$
|
||||
^spae-man$
|
||||
^spaeman$
|
||||
^spaer$
|
||||
^Spaerobee$
|
||||
^spaes$
|
||||
^spaewife$
|
||||
^spaewoman$
|
||||
^spaework$
|
||||
^spaewright$
|
||||
^wether$
|
||||
^wethers$
|
||||
^wetherteg$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^oer$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether.*
|
||||
|
||||
132
.github/workflows/spelling2.yml
vendored
132
.github/workflows/spelling2.yml
vendored
@@ -1,20 +1,134 @@
|
||||
# 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:
|
||||
- "**"
|
||||
pull_request_target:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
- 'synchronize'
|
||||
issue_comment:
|
||||
types:
|
||||
- 'created'
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
name: Spell checking
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
actions: read
|
||||
outputs:
|
||||
followup: ${{ steps.spelling.outputs.followup }}
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event_name, 'pull_request') || github.event_name == 'push'"
|
||||
concurrency:
|
||||
group: spelling-${{ github.event.pull_request.number || github.ref }}
|
||||
# note: If you use only_check_changed_files, you do not want cancel-in-progress
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: checkout-merge
|
||||
if: "contains(github.event_name, 'pull_request')"
|
||||
uses: actions/checkout@v2
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
ref: refs/pull/${{github.event.pull_request.number}}/merge
|
||||
- name: checkout
|
||||
if: "!contains(github.event_name, 'pull_request')"
|
||||
uses: actions/checkout@v2
|
||||
- uses: check-spelling/check-spelling@v0.0.19
|
||||
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-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
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
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 }}
|
||||
|
||||
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 }}
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
---
|
||||
author: Michael Niksa @miniksa
|
||||
created on: 2022-02-24
|
||||
last updated: 2022-02-24
|
||||
issue id: 12570
|
||||
---
|
||||
|
||||
# Show Hide operations on GetConsoleWindow via PTY
|
||||
|
||||
## Abstract
|
||||
|
||||
To maintain compatibility with command-line tools, utilities, and tests that desire to
|
||||
manipulate the final presentation window of their output through retrieving the raw
|
||||
console window handle and performing `user32` operations against it like [ShowWindow](https://docs.microsoft.com//windows/win32/api/winuser/nf-winuser-showwindow),
|
||||
we will create a compatibility layer that captures this intent and translates it into
|
||||
the nearest equivalent in the cross-platform virtual terminal language and implement the
|
||||
understanding of these sequences in our own Windows Terminal.
|
||||
|
||||
## Inspiration
|
||||
|
||||
When attempting to enable the Windows Terminal as the default terminal application on Windows
|
||||
(to supersede the execution of command-line utilities inside the classic console host window),
|
||||
we discovered that there were a bunch of automated tests, tools, and utilities that relied on
|
||||
showing and hiding the console window using the `::GetConsoleWindow()` API in conjunction with
|
||||
`::ShowWindow()`.
|
||||
|
||||
When we initially invented the ConPTY, we worked to ensure that we built to the common
|
||||
denominator that would work cross-platform in all scenarios, avoiding situations that were
|
||||
dependent on Windows-isms like `user32k` including the full knowledge of how windowing occurs
|
||||
specific to the Windows platform.
|
||||
|
||||
We also understood that on Windows, the [**CreateProcess**](https://docs.microsoft.com/windows/win32/procthread/process-creation-flags) API provides ample flags specifically
|
||||
for command-line applications to command the need for (or lack thereof) a window on startup
|
||||
such as `CREATE_NEW_CONSOLE`, `CREATE_NO_WINDOW`, and `DETACHED_PROCESS`. The understanding
|
||||
was that people who didn't need or want a window, or otherwise needed to manipulate the
|
||||
console session, would use those flags on process creation to dictate the session. Additionally,
|
||||
the `::CreateProcess` call will accept information in `STARTUPINFO` or `STARTUPINFOEX` that
|
||||
can dictate the placement, size, and visibility of a window... including some fields specific
|
||||
to console sessions. We had accepted those as ways applications would specify their intent.
|
||||
|
||||
Those assumptions have proven incorrect. Because it was too easy to just `::CreateProcess` in
|
||||
the default manner and then get access to the session after-the-fact and manipulate it with
|
||||
APIs like `::GetConsoleWindow()`, tooling and tests organically grew to make use of this process.
|
||||
Instead of requesting up front that they didn't need a window or the overhead of a console session,
|
||||
they would create one anyway by default and then manipulate it afterward to hide it, move it off-
|
||||
screen, or otherwise push it around. Overall, this is terrible for their performance and overall
|
||||
reliability because they've obscured their intent by not asking for it upfront and impacted their
|
||||
performance by having the entire subsystem spin up interactive work when they intend to not use it.
|
||||
But Windows is the place for compatibility, so we must react and compensate for the existing
|
||||
non-ideal situation.
|
||||
|
||||
We will implement a mechanism to compensate for these that attempts to capture the intent of the
|
||||
requests from the calling applications against the ConPTY and translates them into the "universal"
|
||||
Virtual Terminal language to the best of its ability to make the same effects as prior to the
|
||||
change to the new PTY + Terminal platform.
|
||||
|
||||
## Solution Design
|
||||
|
||||
Overall, there are three processes involved in this situation:
|
||||
|
||||
1. The client command-line application utility, tool, or test that will manipulate the window.
|
||||
1. The console host (`conhost.exe` or `openconsole.exe`) operating in PTY mode.
|
||||
1. The terminal (`windowsterminal.exe` when it's Windows Terminal, but could be a third party).
|
||||
|
||||
The following diagram shows the components and how they will interact.
|
||||
|
||||
```txt
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────────┐
|
||||
│ │ 1 │ │ │ │
|
||||
│ Command-Line ├─────────────────► │ Console Host │ │ Windows Terminal │
|
||||
│ Tool or │ │ as ConPTY │ │ Backend │
|
||||
│ Utility │ 2 │ │ 6 │ │
|
||||
│ │ ◄─────────────────┤ ├─────────────────► │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ 9 │ │
|
||||
│ │ │ │ ◄─────────────────┤ │
|
||||
│ │ │ │ │ │
|
||||
└─────┬───────────┘ └───────────┬──────┘ └─────────────────┬────┘
|
||||
│ ▲ │ ▲ │
|
||||
│ │ │ │ │
|
||||
│ │ │10 │ │7
|
||||
│3 5│ │ │8 │
|
||||
│ │ ▼ │ ▼
|
||||
│ ┌───┴────┐ ┌──┴────┬───────┬─────────────────────────┐
|
||||
▼ │ Hidden │ │ │ │ v^x│
|
||||
┌─────────────────┐ │ Fake │ ├───────┴───────┴─────────────────────────┤
|
||||
│ │ 4 │ PTY │ │ │
|
||||
│ ├──────────────────────► │ Window │ │ │
|
||||
│ user32.dll │ └────────┘ │ Windows Terminal │
|
||||
│ Window APIs │ │ Displayed Window │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
└─────────────────┘ │ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
1. The command-line tool calls `::GetConsoleWindow()` on the PTY host
|
||||
2. The PTY host returns the raw `HWND` to the *Hidden Fake PTY Window* in its control
|
||||
3. The command-line tool calls `::ShowWindow()` on the `user32.dll` API surface to manipulate that window.
|
||||
4. `user32.dll` sends a message to the window message queue on the *Fake PTY Window*
|
||||
5. The PTY host retrieves the message from the queue and translates it to a virtual terminal message
|
||||
6. The Windows Terminal connection layer receives the virtual terminal message and decodes it into a window operation.
|
||||
7. The true displayed *Windows Terminal Window* is told to change its status to show or hide.
|
||||
8. The changed Show/Hide status is returned to the back-end on completion.
|
||||
9. The Windows Terminal connection layer returns that information to the PTY host so it can remain in-the-know.
|
||||
10. The PTY updates its *Fake PTY Window* status to match the real one so it continues to receive appropriate messages from `user32`.
|
||||
|
||||
This can be conceptually understood in a few phases:
|
||||
|
||||
- The client application grabs a handle and attempts to send a command via a back-channel through user32.
|
||||
- User32 decides what message to send based on the window state of the handle.
|
||||
- The message is translated by the PTY and propagated to the true visible window.
|
||||
- The visible window state is returned back to the hidden/fake window to remain in synchronization so the next call to user32 can make the correct decision.
|
||||
|
||||
The communication between the PTY and the hosting terminal application occurs with a virtual terminal sequence.
|
||||
Fortunately, *xterm* had already invented and implemented one for this behavior called **XTWINOPS** which means
|
||||
we should be able to utilize that one and not worry about inventing our own Microsoft-specific thing. This ensures
|
||||
that there is some precedence for what we're doing, guarantees a major third party terminal can support the same
|
||||
sequence, and induces a high probability of other terminals already using it given *xterm* is the defacto standard
|
||||
for terminal emulation.
|
||||
|
||||
Information about **XTWINOPS** can be found at [Xterm control sequences](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html). Search for *XTWINOPS*.
|
||||
The sequence is **CSI** *Ps*; *Ps*; *Ps* **t**. It starts with the common "control sequence initiator" of `ESC [` (`0x1B 0x5B`).
|
||||
Then between 1 and 3 numerical parameters are given, separated by semicolons (`0x3B`).
|
||||
And finally, the sequence is terminated with `t` (`0x74`).
|
||||
|
||||
Specifically, the two parameter commands of `1` for *De-iconify window* and `2` for *Iconify window* appear relevant to our interests.
|
||||
In `user32` parlance, "iconify" traditionally corresponds to minimize/restore state and is a good proxy for overall visibility of the window.
|
||||
|
||||
The theory then is to detect when the assorted calls to `::ShowWindow()` against the *Fake PTY Window* are asking for a command that
|
||||
maps to either "iconify" or "deiconify" and translate them into the corresponding message over the VT channel to the attached terminal.
|
||||
|
||||
To detect this, we need to use some heuristics inside the [window procedure](https://docs.microsoft.com/windows/win32/winmsg/window-procedures) for the window owned by the PTY.
|
||||
Unfortunately, calls to `::ShowWindow()` on research with the team that owns `user32` do not go straight into the window message queue. Instead, they're dispatched straight into `win32k` to be analyzed and then trigger an array of follow on window messages into the queue depending on the `HWND`'s current state. Most specifically, they vary based on the `WS_VISIBLE` state of the `HWND`. (See [Window Styles](https://docs.microsoft.com/windows/win32/winmsg/window-styles) for details on the `WS_VISIBLE` flag.)
|
||||
|
||||
I evaluated a handful of messages with the help of the IXP Essentials team to see which ones would telegraph the changes from `::ShowWindow()` into our window procedure:
|
||||
|
||||
- [WM_QUERYOPEN](https://docs.microsoft.com/windows/win32/winmsg/wm-queryopen) - This one allows us to accept/reject a minimize/restore call. Not really useful for finding out current state
|
||||
- [WM_SYSCOMMAND](https://docs.microsoft.com/windows/win32/menurc/wm-syscommand) - This one is what is called when the minimize, maximize/restore, and exit buttons are called in the window toolbar. But apparently it is not generated for these requests coming from outside the window itself through the `user32` APIs.
|
||||
- [WM_SHOWWINDOW](https://docs.microsoft.com/windows/win32/winmsg/wm-showwindow) - This one provides some insight in certain transitions, specifically around force hiding and showing. When the `lParam` is `0`, we're supposed to know that someone explicitly called `::ShowWindow()` to show or hide with the `wParam` being a `BOOL` where `TRUE` is "show" and `FALSE` is "hide". We can translate that into *de-iconify* and *iconify* respectively.
|
||||
- [WM_WINDOWPOSCHANGING](https://docs.microsoft.com/windows/win32/winmsg/wm-windowposchanging) - This one I evaluated extensively as it looked to provide us insight into how the window was about to change before it did so and offered us the opportunity to veto some of those changes (for instance, if we wanted to remain invisible while propagating a "show" message). I'll detail more about this one in a sub-heading below.
|
||||
- [WM_SIZE](https://docs.microsoft.com/windows/win32/winmsg/wm-size) - This one has a `wParam` that specifically sends `SIZE_MINIMIZED` (`1`) and `SIZE_RESTORED` (`0`) that should translate into *iconify* and *de-iconify respectively.
|
||||
|
||||
#### WM_WINDOWPOSCHANGING data
|
||||
|
||||
In investigating `WM_WINDOWPOSCHANGING`, I built a table of some of the states I observed while receiving messages from an external caller that was using `::ShowWindow()`:
|
||||
|
||||
|integer|constant|flags|Should Hide?|minimizing|maximizing|showing|hiding|activating|`0x8000`|`SWP_NOCOPYBITS`|`SWP_SHOWWINDOW`|`SWP_FRAMECHANGED`|`SWP_NOACTIVATE`|`SWP_NOZORDER`|`SWP_NOMOVE`|`SWP_NOSIZE`|
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
|0|`SW_HIDE`|?|YES|?|?|?|?|?|?|?|?|?|?|?|?|?|
|
||||
|1|`SW_NORMAL`|`0x43`|NO|F|F|T|F|T|||X||||X|X|
|
||||
|2|`SW_SHOWMINIMIZED`|`0x8160`|YES|T|F|T|F|T|X|X|X|X|||||
|
||||
|3|`SW_SHOWMAXIMIZED`|`0x8160`|NO|F|T|T|F|T|X|X|X|X|||||
|
||||
|4|`SW_SHOWNOACTIVATE`|`0x8070`|NO|F|F|T|F|F|X||X|X|X||||
|
||||
|5|`SW_SHOW`|`0x43`|NO|F|F|T|F|T|||X||||X|X|
|
||||
|6|`SW_MINIMIZE`|`0x8170`|YES|T|F|T|F|F|X|X|X|X|X||||
|
||||
|7|`SW_SHOWMINNOACTIVE`|`0x57`|YES|T|F|T|F|F|||X||X|X|X|X|
|
||||
|8|`SW_SHOWNA`|`0x53`|NO|F|F|T|F|F|||X||X||X|X|
|
||||
|9|`SW_RESTORE`|`0x8160`|NO|F|F|T|F|T|||X|X|||||
|
||||
|10|`SW_SHOWDEFAULT`|`0x43`|NO|F|F|T|F|T|||X||||X|X|
|
||||
|11|`SW_FORCEMINIMIZE`|?|YES|?|?|?|?|?|?|?|?|?|?|?|?|?|
|
||||
|
||||
The headings are as follows:
|
||||
|
||||
- integer - The value of the Show Window constant `SW_*` (see [ShowWindow](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-showwindow))
|
||||
- constant - The name of the Show Window constant
|
||||
- flags - The `lParam` field is a pointer to a [**WINDOWPOS**](https://docs.microsoft.com/windows/win32/api/winuser/ns-winuser-windowpos) structure during this message. This the `UINT flags` field of that structure.
|
||||
- Should Hide? - Whether or not I believe that the window should hide if this constant is seen. (Conversely, should show on the opposite.)
|
||||
- minimizing - This is the `BOOL` response from a call to [**IsIconic()**](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-isiconic) during this message.
|
||||
- maximizing - This is the `BOOL` response from a call to [**IsZoomed()**](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-iszoomed) during this message.
|
||||
- showing - This is whether `SWP_SHOWWINDOW` is set on the `WINDOWPOS.flags` field during this message.
|
||||
- hiding - This is whether `SWP_HIDEWINDOW` is set on the `WINDOWPOS.flags` field during this message.
|
||||
- activating - This is the inverse of whether `SWP_NOACTIVATE` is set on the `WINDOWPOS.flags` field during this message.
|
||||
- Remaining headings are `flags` values expanded to `X` is set and blank is unset. See [**SetWindowPos()**](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-setwindowpos) for the definitions of all the flags.
|
||||
|
||||
From this data collection, I noticed a few things:
|
||||
|
||||
- The data in this table was unstable. The fields varied depending on the order in which I called the various constants against `ShowWindow()`. This is just one particular capture.
|
||||
- Some of the states, I wouldn't see any message data at all (`SW_HIDE` and `SW_FORCEMINIMIZE`).
|
||||
- There didn't seem to be a definitive way to use this data to reliably decide when to show or hide the window. I didn't have a reliable way of pulling this together with my *Should Hide?* column.
|
||||
|
||||
On further investigation, it became apparent that the values received were sometimes not coming through or varying because the `WS_VISIBLE` state of the `HWND` affected how `win32k` decided to dispatch messages and what values they contained. This is where I determined that steps #8-10 in the diagram above were going to be necessary: to report the state of the real window back to the *fake window* so it could report status to `user32` and `win32k` and receive state-appropriate messages.
|
||||
|
||||
For reporting back #8-10, I initially was going to use the `XTWINOPS` call with parameter `11`. The PTY could ask the attached terminal for its state and expect to hear back an answer of either `1` or `2` in the same format message depending on the state. However, on further consideration, I realized that the real window could change at a moments notice without prompting from the PTY, so I instead wrote the PTY to always listen for this and had the Windows Terminal send this back down unprompted.
|
||||
|
||||
#### Refined WM_SHOWWINDOW and WM_SIZE data
|
||||
|
||||
Upon setting up the synchronization for #8-10, I then tried again to build the table using just the two window messages that were giving me reliable data: `WM_SHOWWINDOW` and `WM_SIZE`:
|
||||
|
||||
|integer|constant|Should Hide?|`WM_SHOWWINDOW` OR `WM_SIZE` reported hide?|
|
||||
|---|---|---|---|
|
||||
|0|`SW_HIDE`|YES|YES|
|
||||
|1|`SW_NORMAL`|NO|NO|
|
||||
|2|`SW_SHOWMINIMIZED`|YES|YES|
|
||||
|3|`SW_SHOWMAXIMIZED`|NO|NO|
|
||||
|4|`SW_SHOWNOACTIVATE`|NO|NO|
|
||||
|5|`SW_SHOW`|NO|NO|
|
||||
|6|`SW_MINIMIZE`|YES|YES|
|
||||
|7|`SW_SHOWMINNOACTIVE`|YES|YES|
|
||||
|8|`SW_SHOWNA`|NO|NO|
|
||||
|9|`SW_RESTORE`|NO|NO|
|
||||
|10|`SW_SHOWDEFAULT`|NO|NO|
|
||||
|11|`SW_FORCEMINIMIZE`|YES|YES|
|
||||
|
||||
Since this now matched up perfectly with what I was suspecting should happen *and* it was easier to implement than picking apart the `WM_WINDOWPOSCHANGING` message, it is what I believe the design should be.
|
||||
|
||||
Finally, with the *fake window* changing state to and from `WS_VISIBLE`... it was appearing on the screen and showing up in the taskbar and alt-tab. To resolve this, I utilized [**DWMWA_CLOAK**](https://docs.microsoft.com//windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute) which makes the window completely invisible even when in a normally `WS_VISIBLE` state. I then added the [**WS_EX_TOOLWINDOW**](https://docs.microsoft.com/windows/win32/winmsg/extended-window-styles) extended window style to hide it from alt-tab and taskbar.
|
||||
|
||||
With this setup, the PTY now has a completely invisible window with a synchronized `WS_VISIBLE` state with the real terminal window, a bidirectional signal channel to adjust the state between the terminal and PTY, and the ability to catch `user32` calls being made against the *fake window* that the PTY stands up for the client command-line application.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
The visible change in behavior is that a call to `::ShowWindow()` against the `::GetConsoleWindow()`
|
||||
handle that is returned by the ConPTY will be propagated to the attached Terminal. As such, a
|
||||
user will see the entire window be shown or hidden if one of the underlying attached
|
||||
command-line applications requests a show or hide.
|
||||
|
||||
At the initial moment, the fact that the Terminal contains tabbed and/or paned sessions and
|
||||
therefore multiple command-line clients on "different sessions" are attached to the same window
|
||||
is partially ignored. If one attached client calls "show", the entire window will be shown with
|
||||
all tabs. If another calls "hide", the entire window will be hidden including the other tab
|
||||
that just requested a show. In the opposite direction, when the window is shown, all attached
|
||||
PTYs for all tabs/panes will be alerted that they're now shown at once.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
Users of assistive devices will have the same experience that they did with the legacy Windows
|
||||
Console after this change. If a command-line application decides to show or hide the window
|
||||
through the API without their consent, they will receive notification of the showing/hiding
|
||||
window through our UIA framework.
|
||||
|
||||
Prior to this change, the window would have always remained visible and there would be no
|
||||
action.
|
||||
|
||||
Overall, the experience will be consistent between what is happening on-screen and what is
|
||||
presented through the UIA framework to assistive tools.
|
||||
|
||||
For third party terminals, it will be up to them to decide what their reaction and experience is.
|
||||
|
||||
### Security
|
||||
|
||||
We will maintain the security and integrity of the Terminal application chosen for presentation
|
||||
by not revealing its true window handle information to the client process through the existing
|
||||
`::GetConsoleWindow()` API. Through our design for default terminal applications, the final
|
||||
presentation terminal could be Windows Terminal or it could be any third-party terminal that
|
||||
meets the same specifications for communication. Giving raw access to its `HWND` to a client
|
||||
application could disrupt its security.
|
||||
|
||||
By maintaining a level of separation with this feature by generating a "fake window" in the
|
||||
ConPTY layer and only forwarding events, the attached terminal (whether ours or a 3rd party)
|
||||
maintains the final level of control on whether or not it processes the message. This is
|
||||
improved security over the legacy console host where the tool had full backdoor style access
|
||||
to all `user32` based window APIs.
|
||||
|
||||
### Reliability
|
||||
|
||||
This test doesn't improve overall reliability in the system because utilities that are relying
|
||||
on the behavior that this compatibility shim will restore are already introducing additional
|
||||
layers of complexity and additional processes into their operation than were strictly necessary
|
||||
simply by not stating their desires upfront at creation time.
|
||||
|
||||
In some capacity, you could argue it increases reliability of the existing tests that were
|
||||
using this complex behavior in that they didn't work before and they will work now, but
|
||||
the entire process is fragile. We're just restoring the fragile process instead of having
|
||||
it not work at all.
|
||||
|
||||
### Compatibility
|
||||
|
||||
This change restores compatibility with existing applications that were relying on the behavior
|
||||
we had excluded from our initial designs.
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
The performance of tooling that is leveraging this process to create a console and then hide
|
||||
or manipulate the session after the fact will be significantly worse when we enable the
|
||||
default Windows Terminal than it was with the old Windows Console. This is because the
|
||||
Terminal is significantly heavier weight (with its modern technologies like WinUI) and
|
||||
will take more time to start and more committed memory. Additionally, more processes
|
||||
will be in use because there will be the `conhost.exe` doing the ConPTY translation
|
||||
and then the `windowsterminal.exe` doing the presentation.
|
||||
|
||||
However, this particular feature doesn't do anything to make that better or worse.
|
||||
|
||||
The appropriate solution for any tooling, test, or scenario that has a need for
|
||||
performance and efficiency is to use the flags to `::CreateProcess` in the first place
|
||||
to specify that they did not need a console window session at all, or to direct its
|
||||
placement and visibility as a part of the creation call. We are working with
|
||||
Microsoft's test automation tooling (TAEF) as well as the Windows performance
|
||||
fundamentals (FUN) team to ensure that the test automation supports creating sessions
|
||||
without a console window and that our internal performance test suite uses those
|
||||
specifications on creation so we have accurate performance testing of the operating
|
||||
system.
|
||||
|
||||
## Potential Issues
|
||||
|
||||
### Multiple clients sharing the same window host
|
||||
|
||||
With the initial design, multiple clients sharing the same window host will effectively
|
||||
share the window state. Two different tabs or panes with two different client applications
|
||||
could fight over the show/hide state of the window. In the initial revision, this is
|
||||
ignored because this feature is being driven by a narrow failure scenario in the test gates.
|
||||
In the reported scenario, a singular application is default-launched into a singular tab
|
||||
in a terminal window and then the application expects to be able to hide it after the creation.
|
||||
|
||||
In the future, we may have to implement a conflict resolution or a graphical variance to
|
||||
compensate for multiple tabs.
|
||||
|
||||
### Other verbs against the console window handle
|
||||
|
||||
This scenario initially focuses on just the `::ShowWindow()` call against the window handle
|
||||
from `::GetConsoleWindow()`. Other functions from `user32` against the `HWND` will not
|
||||
necessarily be captured and forwarded to the attached terminal application. And even more
|
||||
specifically, we're focusing only on the Show and Hide state. Other state modifications that
|
||||
are subtle related to z-ordering, activation, maximizing, snapping, and so on are not considered.
|
||||
|
||||
## Future considerations
|
||||
|
||||
### Multiple clients
|
||||
|
||||
If the multiple clients problem becomes more widespread, we may need to change the graphical
|
||||
behavior of the Windows Terminal window to only hide certain tabs or panes when a command
|
||||
comes in instead of hiding the entire window (unless of course there is only one tab/pane).
|
||||
|
||||
We may also need to adjust that once consensus is reached among tabs/panes that it can then
|
||||
and only then propagate up to the entire window.
|
||||
|
||||
We will decide on this after we receive feedback that it is a necessary scenario. Otherwise,
|
||||
we will hold for now.
|
||||
|
||||
### Other verbs
|
||||
|
||||
If it turns out that we discover tests/scenarios that need maximizing, activation, or other
|
||||
properties of the `::ShowWindow()` call to be propagated to maintain compatibility, we will
|
||||
be able to carry those through on the same channel and command. Most of them have an existing
|
||||
equivalent in `XTWINOPS`. Those that do not, we would want to probably avoid as they will not
|
||||
be implemented in any other terminal. We would extend the protocol as an absolute last resort
|
||||
and only after receiving feedback from the greater worldwide terminal community.
|
||||
|
||||
### Z-ordering
|
||||
|
||||
The channel we're establishing here to communicate information about the window and its
|
||||
placement may be useful for the z-ordering issues we have in #2988. In those scenarios,
|
||||
a console client application is attempting to launch and position a window on top of the
|
||||
terminal, wherever it is. Further synchronizing the state of the new fake-window in the
|
||||
ConPTY with the real window on the terminal side may enable those tools to function as
|
||||
they expect.
|
||||
|
||||
This is another circumstance we didn't expect: having command-line applications create windows
|
||||
with a need for complex layout and ordering. These sorts of behaviors cannot be translated
|
||||
to a universal language and will not be available off the singular machine, so encouraged
|
||||
alternative methods like command-line based UI. However, for single-box scenarios, this
|
||||
behavior is engrained in some Windows tooling due to its ease of use.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Default Terminal spec](https://github.com/microsoft/terminal/pull/7414)
|
||||
- [Z-ordering issue](https://github.com/microsoft/terminal/issues/2988)
|
||||
- See all the embedded links in this document to Windows API resources
|
||||
@@ -242,7 +242,7 @@ HRESULT HwndTerminal::Initialize()
|
||||
_terminal->Create(COORD{ 80, 25 }, 1000, *_renderer);
|
||||
_terminal->SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, RGB(12, 12, 12));
|
||||
_terminal->SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, RGB(204, 204, 204));
|
||||
_terminal->SetWriteInputCallback([=](std::wstring& input) noexcept { _WriteTextToConnection(input); });
|
||||
_terminal->SetWriteInputCallback([=](std::wstring_view input) noexcept { _WriteTextToConnection(input); });
|
||||
localPointerToThread->EnablePainting();
|
||||
|
||||
_multiClickTime = std::chrono::milliseconds{ GetDoubleClickTime() };
|
||||
@@ -282,7 +282,7 @@ void HwndTerminal::RegisterScrollCallback(std::function<void(int, int, int)> cal
|
||||
_terminal->SetScrollPositionChangedCallback(callback);
|
||||
}
|
||||
|
||||
void HwndTerminal::_WriteTextToConnection(const std::wstring& input) noexcept
|
||||
void HwndTerminal::_WriteTextToConnection(const std::wstring_view input) noexcept
|
||||
{
|
||||
if (!_pfnWriteCallback)
|
||||
{
|
||||
|
||||
@@ -108,7 +108,7 @@ private:
|
||||
friend void _stdcall TerminalKillFocus(void* terminal);
|
||||
|
||||
void _UpdateFont(int newDpi);
|
||||
void _WriteTextToConnection(const std::wstring& text) noexcept;
|
||||
void _WriteTextToConnection(const std::wstring_view text) noexcept;
|
||||
HRESULT _CopyTextToSystemClipboard(const TextBuffer::TextAndColor& rows, bool const fAlsoCopyFormatting);
|
||||
HRESULT _CopyToSystemClipboard(std::string stringToCopy, LPCWSTR lpszFormat);
|
||||
void _PasteTextFromClipboard() noexcept;
|
||||
|
||||
@@ -1135,6 +1135,22 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Used to tell the PTY connection that the window visibility has changed.
|
||||
// The underlying PTY might need to expose window visibility status to the
|
||||
// client application for the `::GetConsoleWindow()` API.
|
||||
// Arguments:
|
||||
// - showOrHide - True is show; false is hide.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppLogic::WindowVisibilityChanged(const bool showOrHide)
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
_root->WindowVisibilityChanged(showOrHide);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Implements the F7 handler (per GH#638)
|
||||
// - Implements the Alt handler (per GH#6421)
|
||||
|
||||
@@ -65,6 +65,8 @@ namespace winrt::TerminalApp::implementation
|
||||
void LoadSettings();
|
||||
[[nodiscard]] Microsoft::Terminal::Settings::Model::CascadiaSettings GetSettings() const noexcept;
|
||||
|
||||
void SetOwnerHwnd(uint64_t owner) { _root->SetOwnerHwnd(owner); }
|
||||
|
||||
void Quit();
|
||||
|
||||
bool HasCommandlineArguments() const noexcept;
|
||||
@@ -114,6 +116,7 @@ namespace winrt::TerminalApp::implementation
|
||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||
|
||||
void CloseWindow(Microsoft::Terminal::Settings::Model::LaunchPosition position);
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||
|
||||
@@ -208,6 +211,7 @@ namespace winrt::TerminalApp::implementation
|
||||
FORWARDED_TYPED_EVENT(CloseRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, CloseRequested);
|
||||
FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu);
|
||||
FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested);
|
||||
FORWARDED_TYPED_EVENT(ShowWindowChanged, Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs, _root, ShowWindowChanged);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class TerminalAppLocalTests::CommandlineTest;
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace TerminalApp
|
||||
// registered?" when it definitely is.
|
||||
void Create();
|
||||
|
||||
void SetOwnerHwnd(UInt64 owner);
|
||||
|
||||
Boolean IsUwp();
|
||||
void RunAsUwp();
|
||||
Boolean IsElevated();
|
||||
@@ -91,6 +93,7 @@ namespace TerminalApp
|
||||
Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension);
|
||||
void TitlebarClicked();
|
||||
void CloseWindow(Microsoft.Terminal.Settings.Model.LaunchPosition position);
|
||||
void WindowVisibilityChanged(Boolean showOrHide);
|
||||
|
||||
TaskbarState TaskbarState{ get; };
|
||||
|
||||
@@ -127,5 +130,6 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.ShowWindowArgs> ShowWindowChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1426,6 +1426,8 @@ namespace winrt::TerminalApp::implementation
|
||||
term.SetTaskbarProgress({ get_weak(), &TerminalPage::_SetTaskbarProgressHandler });
|
||||
|
||||
term.ConnectionStateChanged({ get_weak(), &TerminalPage::_ConnectionStateChangedHandler });
|
||||
|
||||
term.ShowWindowChanged({ get_weak(), &TerminalPage::_ShowWindowChangedHandler });
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -2338,6 +2340,17 @@ namespace winrt::TerminalApp::implementation
|
||||
_SetTaskbarProgressHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Send an event (which will be caught by AppHost) to change the show window state of the entire hosting window
|
||||
// Arguments:
|
||||
// - sender (not used)
|
||||
// - args: the arguments specifying how to set the display status to ShowWindow for our window handle
|
||||
winrt::fire_and_forget TerminalPage::_ShowWindowChangedHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::ShowWindowArgs args)
|
||||
{
|
||||
co_await resume_foreground(Dispatcher());
|
||||
_ShowWindowChangedHandlers(*this, args);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Paste text from the Windows Clipboard to the focused terminal
|
||||
void TerminalPage::_PasteText()
|
||||
@@ -2413,6 +2426,9 @@ namespace winrt::TerminalApp::implementation
|
||||
// create here.
|
||||
// TermControl will copy the settings out of the settings passed to it.
|
||||
TermControl term{ settings.DefaultSettings(), settings.UnfocusedSettings(), connection };
|
||||
if (_hostingHwnd.has_value())
|
||||
term.OwningHwnd(_ownerHwnd);
|
||||
// term.OwningHwnd(reinterpret_cast<uint64_t>(_ownerHwnd));
|
||||
return term;
|
||||
}
|
||||
|
||||
@@ -2778,6 +2794,35 @@ namespace winrt::TerminalApp::implementation
|
||||
_DismissTabContextMenus();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Notifies all attached console controls that the visibility of the
|
||||
// hosting window has changed. The underlying PTYs may need to know this
|
||||
// for the proper response to `::GetConsoleWindow()` from a Win32 console app.
|
||||
// Arguments:
|
||||
// - showOrHide: Show is true; hide is false.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::WindowVisibilityChanged(const bool showOrHide)
|
||||
{
|
||||
for (const auto& tab : _tabs)
|
||||
{
|
||||
if (auto terminalTab{ _GetTerminalTabImpl(tab) })
|
||||
{
|
||||
// Manually enumerate the panes in each tab; this will let us recycle TerminalSettings
|
||||
// objects but only have to iterate one time.
|
||||
terminalTab->GetRootPane()->WalkTree([&](auto&& pane) {
|
||||
if (const auto profile{ pane->GetProfile() })
|
||||
{
|
||||
if (auto control = pane->GetTerminalControl())
|
||||
{
|
||||
control.WindowVisibilityChanged(showOrHide);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when the user tries to do a search using keybindings.
|
||||
// This will tell the current focused terminal control to create
|
||||
|
||||
@@ -63,6 +63,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void Create();
|
||||
|
||||
uint64_t _ownerHwnd{ 0 };
|
||||
void SetOwnerHwnd(uint64_t owner) { _ownerHwnd = owner; };
|
||||
|
||||
bool ShouldUsePersistedLayout(Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||
bool ShouldImmediatelyHandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const;
|
||||
void HandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
|
||||
@@ -75,6 +78,7 @@ namespace winrt::TerminalApp::implementation
|
||||
hstring Title();
|
||||
|
||||
void TitlebarClicked();
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
|
||||
@@ -154,6 +158,7 @@ namespace winrt::TerminalApp::implementation
|
||||
TYPED_EVENT(CloseRequested, IInspectable, IInspectable);
|
||||
TYPED_EVENT(OpenSystemMenu, IInspectable, IInspectable);
|
||||
TYPED_EVENT(QuitRequested, IInspectable, IInspectable);
|
||||
TYPED_EVENT(ShowWindowChanged, IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs)
|
||||
|
||||
private:
|
||||
friend struct TerminalPageT<TerminalPage>; // for Xaml to bind events
|
||||
@@ -433,6 +438,8 @@ namespace winrt::TerminalApp::implementation
|
||||
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
|
||||
winrt::fire_and_forget _ShowWindowChangedHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
|
||||
|
||||
#pragma region ActionHandlers
|
||||
// These are all defined in AppActionHandlers.cpp
|
||||
#define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action);
|
||||
|
||||
@@ -61,5 +61,6 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Control.ShowWindowArgs> ShowWindowChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +296,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
if (!_inPipe)
|
||||
{
|
||||
THROW_IF_FAILED(_CreatePseudoConsoleAndPipes(dimensions, PSEUDOCONSOLE_RESIZE_QUIRK | PSEUDOCONSOLE_WIN32_INPUT_MODE, &_inPipe, &_outPipe, &_hPC));
|
||||
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(_initialParentHwnd)));
|
||||
THROW_IF_FAILED(_LaunchAttachedClient());
|
||||
}
|
||||
// But if it was an inbound handoff... attempt to synchronize the size of it with what our connection
|
||||
@@ -313,6 +314,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
THROW_IF_FAILED(ConptyResizePseudoConsole(_hPC.get(), dimensions));
|
||||
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(_initialParentHwnd)));
|
||||
}
|
||||
|
||||
_startTime = std::chrono::high_resolution_clock::now();
|
||||
@@ -468,6 +470,20 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void ConptyConnection::ReparentWindow(const uint64_t newParent)
|
||||
{
|
||||
// If we haven't started connecting at all, TODO!
|
||||
if (!_isStateAtOrBeyond(ConnectionState::Connecting))
|
||||
{
|
||||
_initialParentHwnd = newParent;
|
||||
}
|
||||
// Otherwise, TODO!
|
||||
else if (_isConnected())
|
||||
{
|
||||
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(newParent)));
|
||||
}
|
||||
}
|
||||
|
||||
void ConptyConnection::Close() noexcept
|
||||
try
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
void Resize(uint32_t rows, uint32_t columns);
|
||||
void Close() noexcept;
|
||||
void ClearBuffer();
|
||||
void ReparentWindow(const uint64_t newParent);
|
||||
|
||||
winrt::guid Guid() const noexcept;
|
||||
winrt::hstring Commandline() const;
|
||||
@@ -65,6 +66,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
|
||||
uint32_t _initialRows{};
|
||||
uint32_t _initialCols{};
|
||||
uint64_t _initialParentHwnd{ 0 };
|
||||
hstring _commandline{};
|
||||
hstring _startingDirectory{};
|
||||
hstring _startingTitle{};
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Microsoft.Terminal.TerminalConnection
|
||||
Guid Guid { get; };
|
||||
String Commandline { get; };
|
||||
void ClearBuffer();
|
||||
void ReparentWindow(UInt64 newParent);
|
||||
|
||||
static event NewConnectionHandler NewConnection;
|
||||
static void StartInboundListener();
|
||||
|
||||
@@ -77,9 +77,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// This event is explicitly revoked in the destructor: does not need weak_ref
|
||||
_connectionOutputEventToken = _connection.TerminalOutput({ this, &ControlCore::_connectionOutputHandler });
|
||||
|
||||
_terminal->SetWriteInputCallback([this](std::wstring& wstr) {
|
||||
_sendInputToConnection(wstr);
|
||||
});
|
||||
auto pfnWriteInput = std::bind(&ControlCore::_sendInputToConnection, this, std::placeholders::_1);
|
||||
_terminal->SetWriteInputCallback(pfnWriteInput);
|
||||
|
||||
// GH#8969: pre-seed working directory to prevent potential races
|
||||
_terminal->SetWorkingDirectory(_settings->StartingDirectory());
|
||||
@@ -108,6 +107,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_terminalTaskbarProgressChanged, this);
|
||||
_terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged);
|
||||
|
||||
auto pfnShowWindowChanged = std::bind(&ControlCore::_terminalShowWindowChanged, this, std::placeholders::_1);
|
||||
_terminal->SetShowWindowCallback(pfnShowWindowChanged);
|
||||
|
||||
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
|
||||
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
|
||||
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
|
||||
@@ -262,6 +264,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
const auto height = vp.Height();
|
||||
_connection.Resize(height, width);
|
||||
|
||||
if (auto conpty{ _connection.try_as<TerminalConnection::ConptyConnection>() })
|
||||
{
|
||||
conpty.ReparentWindow(_OwningHwnd);
|
||||
}
|
||||
|
||||
// Override the default width and height to match the size of the swapChainPanel
|
||||
_settings->InitialCols(width);
|
||||
_settings->InitialRows(height);
|
||||
@@ -1206,6 +1213,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_TaskbarProgressChangedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
void ControlCore::_terminalShowWindowChanged(bool showOrHide)
|
||||
{
|
||||
auto showWindow = winrt::make_self<implementation::ShowWindowArgs>(showOrHide);
|
||||
_ShowWindowChangedHandlers(*this, *showWindow);
|
||||
}
|
||||
|
||||
bool ControlCore::HasSelection() const
|
||||
{
|
||||
return _terminal->IsSelectionActive();
|
||||
@@ -1683,6 +1696,32 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Notifies the attached PTY that the window has changed visibility state
|
||||
// - NOTE: Most VT commands are generated in `TerminalDispatch` and sent to this
|
||||
// class as the target for transmission. But since this message isn't
|
||||
// coming in via VT parsing (and rather from a window state transition)
|
||||
// we generate and send it here.
|
||||
// Arguments:
|
||||
// - visible: True for visible; false for not visible.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ControlCore::WindowVisibilityChanged(const bool showOrHide)
|
||||
{
|
||||
// show is true, hide is false
|
||||
_connection.WriteInput(showOrHide ? L"\x1b[1t" : L"\x1b[2t");
|
||||
}
|
||||
|
||||
void ControlCore::GotFocus()
|
||||
{
|
||||
_connection.WriteInput(L"\x1b[I");
|
||||
}
|
||||
|
||||
void ControlCore::LostFocus()
|
||||
{
|
||||
_connection.WriteInput(L"\x1b[O");
|
||||
}
|
||||
|
||||
bool ControlCore::_isBackgroundTransparent()
|
||||
{
|
||||
// If we're:
|
||||
|
||||
@@ -81,6 +81,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void PasteText(const winrt::hstring& hstr);
|
||||
bool CopySelectionToClipboard(bool singleLine, const Windows::Foundation::IReference<CopyFormat>& formats);
|
||||
|
||||
void GotFocus();
|
||||
void LostFocus();
|
||||
|
||||
void ToggleShaderEffects();
|
||||
void AdjustOpacity(const double adjustment);
|
||||
void ResumeRendering();
|
||||
@@ -168,6 +171,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void AdjustOpacity(const double opacity, const bool relative);
|
||||
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
WINRT_PROPERTY(uint64_t, OwningHwnd, 0);
|
||||
|
||||
RUNTIME_SETTING(double, Opacity, _settings->Opacity());
|
||||
RUNTIME_SETTING(bool, UseAcrylic, _settings->UseAcrylic());
|
||||
|
||||
@@ -192,6 +199,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
TYPED_EVENT(TransparencyChanged, IInspectable, Control::TransparencyChangedEventArgs);
|
||||
TYPED_EVENT(ReceivedOutput, IInspectable, IInspectable);
|
||||
TYPED_EVENT(FoundMatch, IInspectable, Control::FoundResultsArgs);
|
||||
TYPED_EVENT(ShowWindowChanged, IInspectable, Control::ShowWindowArgs);
|
||||
// clang-format on
|
||||
|
||||
private:
|
||||
@@ -259,6 +267,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
const int bufferSize);
|
||||
void _terminalCursorPositionChanged();
|
||||
void _terminalTaskbarProgressChanged();
|
||||
void _terminalShowWindowChanged(bool showOrHide);
|
||||
#pragma endregion
|
||||
|
||||
#pragma region RendererCallbacks
|
||||
|
||||
@@ -100,6 +100,7 @@ namespace Microsoft.Terminal.Control
|
||||
String ReadEntireBuffer();
|
||||
|
||||
void AdjustOpacity(Double Opacity, Boolean relative);
|
||||
void WindowVisibilityChanged(Boolean showOrHide);
|
||||
|
||||
event FontSizeChangedEventArgs FontSizeChanged;
|
||||
|
||||
@@ -120,6 +121,7 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, TransparencyChangedEventArgs> TransparencyChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ReceivedOutput;
|
||||
event Windows.Foundation.TypedEventHandler<Object, FoundResultsArgs> FoundMatch;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ShowWindowArgs> ShowWindowChanged;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -111,6 +111,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
THROW_IF_FAILED(_uiaEngine->Enable());
|
||||
}
|
||||
|
||||
_core->GotFocus();
|
||||
|
||||
_updateSystemParameterSettings();
|
||||
}
|
||||
|
||||
@@ -120,6 +122,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
THROW_IF_FAILED(_uiaEngine->Disable());
|
||||
}
|
||||
|
||||
_core->LostFocus();
|
||||
}
|
||||
|
||||
// Method Description
|
||||
|
||||
@@ -12,3 +12,4 @@
|
||||
#include "RendererWarningArgs.g.cpp"
|
||||
#include "TransparencyChangedEventArgs.g.cpp"
|
||||
#include "FoundResultsArgs.g.cpp"
|
||||
#include "ShowWindowArgs.g.cpp"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "RendererWarningArgs.g.h"
|
||||
#include "TransparencyChangedEventArgs.g.h"
|
||||
#include "FoundResultsArgs.g.h"
|
||||
#include "ShowWindowArgs.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
@@ -145,4 +146,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
WINRT_PROPERTY(bool, FoundMatch);
|
||||
};
|
||||
|
||||
struct ShowWindowArgs : public ShowWindowArgsT<ShowWindowArgs>
|
||||
{
|
||||
public:
|
||||
ShowWindowArgs(const bool showOrHide) :
|
||||
_ShowOrHide(showOrHide)
|
||||
{
|
||||
}
|
||||
|
||||
WINRT_PROPERTY(bool, ShowOrHide);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -74,4 +74,9 @@ namespace Microsoft.Terminal.Control
|
||||
{
|
||||
Boolean FoundMatch { get; };
|
||||
}
|
||||
|
||||
runtimeclass ShowWindowArgs
|
||||
{
|
||||
Boolean ShowOrHide { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,5 +24,8 @@ namespace Microsoft.Terminal.Control
|
||||
Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; };
|
||||
|
||||
Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };
|
||||
|
||||
UInt64 OwningHwnd;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2060,6 +2060,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return cells * fontDimension + nonTerminalArea;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Forwards window visibility changing event down into the control core
|
||||
// to eventually let the hosting PTY know whether the window is visible or
|
||||
// not (which can be relevant to `::GetConsoleWindow()` calls.)
|
||||
// Arguments:
|
||||
// - showOrHide: Show is true; hide is false.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TermControl::WindowVisibilityChanged(const bool showOrHide)
|
||||
{
|
||||
_core.WindowVisibilityChanged(showOrHide);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Create XAML Thickness object based on padding props provided.
|
||||
// Used for controlling the TermControl XAML Grid container's Padding prop.
|
||||
@@ -2777,4 +2790,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TermControl::OwningHwnd(uint64_t owner)
|
||||
{
|
||||
_core.OwningHwnd(owner);
|
||||
}
|
||||
|
||||
uint64_t TermControl::OwningHwnd()
|
||||
{
|
||||
return _core.OwningHwnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
Windows::Foundation::Size MinimumSize();
|
||||
float SnapDimensionToGrid(const bool widthOrHeight, const float dimension);
|
||||
|
||||
void WindowVisibilityChanged(const bool showOrHide);
|
||||
|
||||
#pragma region ICoreState
|
||||
const uint64_t TaskbarState() const noexcept;
|
||||
const uint64_t TaskbarProgress() const noexcept;
|
||||
@@ -59,6 +61,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
bool BracketedPasteEnabled() const noexcept;
|
||||
|
||||
double BackgroundOpacity() const;
|
||||
|
||||
uint64_t OwningHwnd();
|
||||
void OwningHwnd(uint64_t owner);
|
||||
#pragma endregion
|
||||
|
||||
void ScrollViewport(int viewTop);
|
||||
@@ -121,6 +126,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(TabColorChanged, IInspectable, IInspectable, _core, TabColorChanged);
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable, _core, TaskbarProgressChanged);
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable, _core, ConnectionStateChanged);
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(ShowWindowChanged, IInspectable, Control::ShowWindowArgs, _core, ShowWindowChanged);
|
||||
|
||||
PROJECTED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs, _interactivity, PasteFromClipboard);
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace Microsoft.Terminal.Control
|
||||
// We expose this and ConnectionState here so that it might eventually be data bound.
|
||||
event Windows.Foundation.TypedEventHandler<Object, IInspectable> ConnectionStateChanged;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, ShowWindowArgs> ShowWindowChanged;
|
||||
|
||||
Boolean CopySelectionToClipboard(Boolean singleLine, Windows.Foundation.IReference<CopyFormat> formats);
|
||||
void PasteTextFromClipboard();
|
||||
void ClearBuffer(ClearBufferType clearType);
|
||||
@@ -54,6 +56,8 @@ namespace Microsoft.Terminal.Control
|
||||
Windows.Foundation.Size MinimumSize { get; };
|
||||
Single SnapDimensionToGrid(Boolean widthOrHeight, Single dimension);
|
||||
|
||||
void WindowVisibilityChanged(Boolean showOrHide);
|
||||
|
||||
void ScrollViewport(Int32 viewTop);
|
||||
|
||||
void CreateSearchBoxControl();
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace Microsoft::Terminal::Core
|
||||
|
||||
virtual void PrintString(std::wstring_view string) = 0;
|
||||
|
||||
virtual bool ReturnResponse(std::wstring_view responseString) = 0;
|
||||
|
||||
virtual TextAttribute GetTextAttributes() const = 0;
|
||||
virtual void SetTextAttributes(const TextAttribute& attrs) = 0;
|
||||
|
||||
@@ -67,6 +69,8 @@ namespace Microsoft::Terminal::Core
|
||||
virtual void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) = 0;
|
||||
virtual void PopGraphicsRendition() = 0;
|
||||
|
||||
virtual void ShowWindow(bool showOrHide) = 0;
|
||||
|
||||
protected:
|
||||
ITerminalApi() = default;
|
||||
};
|
||||
|
||||
@@ -221,6 +221,21 @@ void Terminal::UpdateAppearance(const ICoreAppearance& appearance)
|
||||
_defaultCursorShape = cursorShape;
|
||||
}
|
||||
|
||||
// // Method Description:
|
||||
// // - Notifies the attached PTY that the window has changed visibility state
|
||||
// // - NOTE: Most VT commands are generated in `TerminalDispatch` and sent to this
|
||||
// // class as the target for transmission. But since this message isn't
|
||||
// // coming in via VT parsing (and rather from a window state transition)
|
||||
// // we generate and send it here.
|
||||
// // Arguments:
|
||||
// // - visible: True for visible; false for not visible.
|
||||
// // Return Value:
|
||||
// // - <none>
|
||||
// void Terminal::UpdateVisibility(const bool visible)
|
||||
// {
|
||||
// ReturnResponse(visible ? L"\x1b[1t" : L"\x1b[2t");
|
||||
// }
|
||||
|
||||
// Method Description:
|
||||
// - Resize the terminal as the result of some user interaction.
|
||||
// Arguments:
|
||||
@@ -1164,7 +1179,7 @@ void Terminal::_NotifyTerminalCursorPositionChanged() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
void Terminal::SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noexcept
|
||||
void Terminal::SetWriteInputCallback(std::function<void(std::wstring_view)> pfn) noexcept
|
||||
{
|
||||
_pfnWriteInput.swap(pfn);
|
||||
}
|
||||
@@ -1218,6 +1233,15 @@ void Microsoft::Terminal::Core::Terminal::TaskbarProgressChangedCallback(std::fu
|
||||
_pfnTaskbarProgressChanged.swap(pfn);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Propagates an incoming set window visibility call from the PTY up into our window control layers
|
||||
// Arguments:
|
||||
// - pfn: a function callback that accepts true as "make window visible" and false as "hide window"
|
||||
void Terminal::SetShowWindowCallback(std::function<void(bool)> pfn) noexcept
|
||||
{
|
||||
_pfnShowWindowChanged.swap(pfn);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the cursor to be currently on. On/Off is tracked independently of
|
||||
// cursor visibility (hidden/visible). On/off is controlled by the cursor
|
||||
|
||||
@@ -75,12 +75,13 @@ public:
|
||||
|
||||
void UpdateSettings(winrt::Microsoft::Terminal::Core::ICoreSettings settings);
|
||||
void UpdateAppearance(const winrt::Microsoft::Terminal::Core::ICoreAppearance& appearance);
|
||||
// void UpdateVisibility(const bool visible);
|
||||
void SetFontInfo(const FontInfo& fontInfo);
|
||||
|
||||
// Write goes through the parser
|
||||
// Write comes from the PTY and goes to our parser to be stored in the output buffer
|
||||
void Write(std::wstring_view stringView);
|
||||
|
||||
// WritePastedText goes directly to the connection
|
||||
// Write comes from the PTY and goes to our parser to be stored in the output buffer
|
||||
void WritePastedText(std::wstring_view stringView);
|
||||
|
||||
[[nodiscard]] std::unique_lock<til::ticket_lock> LockForReading();
|
||||
@@ -97,6 +98,7 @@ public:
|
||||
#pragma region ITerminalApi
|
||||
// These methods are defined in TerminalApi.cpp
|
||||
void PrintString(std::wstring_view stringView) override;
|
||||
bool ReturnResponse(std::wstring_view responseString) override;
|
||||
TextAttribute GetTextAttributes() const override;
|
||||
void SetTextAttributes(const TextAttribute& attrs) override;
|
||||
Microsoft::Console::Types::Viewport GetBufferSize() override;
|
||||
@@ -137,6 +139,8 @@ public:
|
||||
void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override;
|
||||
void PopGraphicsRendition() override;
|
||||
|
||||
void ShowWindow(bool showOrHide) override;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ITerminalInput
|
||||
@@ -197,7 +201,7 @@ public:
|
||||
const bool IsUiaDataInitialized() const noexcept override;
|
||||
#pragma endregion
|
||||
|
||||
void SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noexcept;
|
||||
void SetWriteInputCallback(std::function<void(std::wstring_view)> pfn) noexcept;
|
||||
void SetWarningBellCallback(std::function<void()> pfn) noexcept;
|
||||
void SetTitleChangedCallback(std::function<void(std::wstring_view)> pfn) noexcept;
|
||||
void SetTabColorChangedCallback(std::function<void(const std::optional<til::color>)> pfn) noexcept;
|
||||
@@ -206,6 +210,7 @@ public:
|
||||
void SetCursorPositionChangedCallback(std::function<void()> pfn) noexcept;
|
||||
void SetBackgroundCallback(std::function<void(const til::color)> pfn) noexcept;
|
||||
void TaskbarProgressChangedCallback(std::function<void()> pfn) noexcept;
|
||||
void SetShowWindowCallback(std::function<void(bool)> pfn) noexcept;
|
||||
|
||||
void SetCursorOn(const bool isOn);
|
||||
bool IsCursorBlinkingAllowed() const noexcept;
|
||||
@@ -252,7 +257,7 @@ public:
|
||||
#pragma endregion
|
||||
|
||||
private:
|
||||
std::function<void(std::wstring&)> _pfnWriteInput;
|
||||
std::function<void(std::wstring_view)> _pfnWriteInput;
|
||||
std::function<void()> _pfnWarningBell;
|
||||
std::function<void(std::wstring_view)> _pfnTitleChanged;
|
||||
std::function<void(std::wstring_view)> _pfnCopyToClipboard;
|
||||
@@ -273,6 +278,7 @@ private:
|
||||
std::function<void()> _pfnCursorPositionChanged;
|
||||
std::function<void(const std::optional<til::color>)> _pfnTabColorChanged;
|
||||
std::function<void()> _pfnTaskbarProgressChanged;
|
||||
std::function<void(bool)> _pfnShowWindowChanged;
|
||||
|
||||
RenderSettings _renderSettings;
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
|
||||
|
||||
@@ -21,6 +21,16 @@ TextAttribute Terminal::GetTextAttributes() const
|
||||
return _buffer->GetCurrentAttributes();
|
||||
}
|
||||
|
||||
bool Terminal::ReturnResponse(std::wstring_view responseString)
|
||||
{
|
||||
if (!_pfnWriteInput)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_pfnWriteInput(responseString);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Terminal::SetTextAttributes(const TextAttribute& attrs)
|
||||
{
|
||||
_buffer->SetCurrentAttributes(attrs);
|
||||
@@ -570,3 +580,17 @@ void Terminal::PopGraphicsRendition()
|
||||
const TextAttribute current = _buffer->GetCurrentAttributes();
|
||||
_buffer->SetCurrentAttributes(_sgrStack.Pop(current));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Reacts to a client asking us to show or hide the window.
|
||||
// Arguments:
|
||||
// - showOrHide - True for show. False for hide.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Terminal::ShowWindow(bool showOrHide)
|
||||
{
|
||||
if (_pfnShowWindowChanged)
|
||||
{
|
||||
_pfnShowWindowChanged(showOrHide);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,6 +442,58 @@ bool TerminalDispatch::ResetMode(const DispatchTypes::ModeParams param)
|
||||
return _ModeParamsHelper(param, false);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DSR - Reports status of a console property back to the STDIN based on the type of status requested.
|
||||
// - This particular routine responds to ANSI status patterns only (CSI # n), not the DEC format (CSI ? # n)
|
||||
// Arguments:
|
||||
// - statusType - ANSI status type indicating what property we should report back
|
||||
// Return Value:
|
||||
// - True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::DeviceStatusReport(const DispatchTypes::AnsiStatusType statusType)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
switch (statusType)
|
||||
{
|
||||
case DispatchTypes::AnsiStatusType::OS_OperatingStatus:
|
||||
success = _OperatingStatus();
|
||||
break;
|
||||
case DispatchTypes::AnsiStatusType::CPR_CursorPositionReport:
|
||||
success = _CursorPositionReport();
|
||||
break;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DSR-OS - Reports the operating status back to the input channel
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::_OperatingStatus() const
|
||||
{
|
||||
// We always report a good operating condition.
|
||||
return _WriteResponse(L"\x1b[0n");
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - DSR-CPR - Reports the current cursor position within the viewport back to the input channel
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - True if handled successfully. False otherwise.
|
||||
bool TerminalDispatch::_CursorPositionReport() const
|
||||
{
|
||||
// Now send it back into the input channel of the console.
|
||||
// First format the response string.
|
||||
const auto pos = _terminalApi.GetCursorPosition();
|
||||
// VT has origin at 1,1 where as we use 0,0 internally
|
||||
const auto response = wil::str_printf<std::wstring>(L"\x1b[%d;%dR", pos.Y + 1, pos.X + 1);
|
||||
return _WriteResponse(response);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Start a hyperlink
|
||||
// Arguments:
|
||||
@@ -545,6 +597,18 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Helper to send a string reply to the input stream of the console.
|
||||
// - Used by various commands where the program attached would like a reply to one of the commands issued.
|
||||
// Arguments:
|
||||
// - reply - The reply string to transmit back to the input stream
|
||||
// Return Value:
|
||||
// - True if the string was sent to the connected application. False otherwise.
|
||||
bool TerminalDispatch::_WriteResponse(const std::wstring_view reply) const
|
||||
{
|
||||
return _terminalApi.ReturnResponse(reply);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Support routine for routing private mode parameters to be set/reset as flags
|
||||
// Arguments:
|
||||
@@ -722,3 +786,20 @@ bool TerminalDispatch::HardReset()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TerminalDispatch::WindowManipulation(const DispatchTypes::WindowManipulationType function,
|
||||
const VTParameter /*parameter1*/,
|
||||
const VTParameter /*parameter2*/)
|
||||
{
|
||||
switch (function)
|
||||
{
|
||||
case DispatchTypes::WindowManipulationType::DeIconifyWindow:
|
||||
_terminalApi.ShowWindow(true);
|
||||
return true;
|
||||
case DispatchTypes::WindowManipulationType::IconifyWindow:
|
||||
_terminalApi.ShowWindow(false);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,11 @@ public:
|
||||
bool SoftReset() override; // DECSTR
|
||||
bool HardReset() override; // RIS
|
||||
|
||||
// DTTERM_WindowManipulation
|
||||
bool WindowManipulation(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::WindowManipulationType /*function*/,
|
||||
const ::Microsoft::Console::VirtualTerminal::VTParameter /*parameter1*/,
|
||||
const ::Microsoft::Console::VirtualTerminal::VTParameter /*parameter2*/) override;
|
||||
|
||||
bool EnableVT200MouseMode(const bool enabled) override; // ?1000
|
||||
bool EnableUTF8ExtendedMouseMode(const bool enabled) override; // ?1005
|
||||
bool EnableSGRExtendedMouseMode(const bool enabled) override; // ?1006
|
||||
@@ -75,6 +80,8 @@ public:
|
||||
bool SetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) override; // DECSET
|
||||
bool ResetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) override; // DECRST
|
||||
|
||||
bool DeviceStatusReport(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::AnsiStatusType /*statusType*/) override; // DSR, DSR-OS, DSR-CPR
|
||||
|
||||
bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) override;
|
||||
bool EndHyperlink() override;
|
||||
|
||||
@@ -90,8 +97,12 @@ private:
|
||||
TextAttribute& attr,
|
||||
const bool isForeground);
|
||||
|
||||
bool _WriteResponse(const std::wstring_view reply) const;
|
||||
bool _ModeParamsHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams param, const bool enable);
|
||||
|
||||
bool _OperatingStatus() const;
|
||||
bool _CursorPositionReport() const;
|
||||
|
||||
void _ClearSingleTabStop();
|
||||
void _ClearAllTabStops();
|
||||
void _ResetTabStops();
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace TerminalCoreUnitTests
|
||||
TEST_METHOD(AltShiftKey);
|
||||
TEST_METHOD(InvalidKeyEvent);
|
||||
|
||||
void _VerifyExpectedInput(std::wstring& actualInput)
|
||||
void _VerifyExpectedInput(std::wstring_view actualInput)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(expectedinput.size(), actualInput.size());
|
||||
VERIFY_ARE_EQUAL(expectedinput, actualInput);
|
||||
|
||||
@@ -335,6 +335,8 @@ void AppHost::Initialize()
|
||||
if (auto withWindow{ _logic.try_as<IInitializeWithWindow>() })
|
||||
{
|
||||
withWindow->Initialize(_window->GetHandle());
|
||||
// _logic.SetOwnerHwnd(reinterpret_cast<uint64_t>(_window->GetInteropHandle()));
|
||||
_logic.SetOwnerHwnd(reinterpret_cast<uint64_t>(_window->GetHandle()));
|
||||
}
|
||||
|
||||
if (_useNonClientArea)
|
||||
@@ -371,6 +373,8 @@ void AppHost::Initialize()
|
||||
// application layer.
|
||||
_window->DragRegionClicked([this]() { _logic.TitlebarClicked(); });
|
||||
|
||||
_window->WindowVisibilityChanged([this](bool showOrHide) { _logic.WindowVisibilityChanged(showOrHide); });
|
||||
|
||||
_revokers.RequestedThemeChanged = _logic.RequestedThemeChanged(winrt::auto_revoke, { this, &AppHost::_UpdateTheme });
|
||||
_revokers.FullscreenChanged = _logic.FullscreenChanged(winrt::auto_revoke, { this, &AppHost::_FullscreenChanged });
|
||||
_revokers.FocusModeChanged = _logic.FocusModeChanged(winrt::auto_revoke, { this, &AppHost::_FocusModeChanged });
|
||||
@@ -398,6 +402,7 @@ void AppHost::Initialize()
|
||||
_revokers.SummonWindowRequested = _logic.SummonWindowRequested(winrt::auto_revoke, { this, &AppHost::_SummonWindowRequested });
|
||||
_revokers.OpenSystemMenu = _logic.OpenSystemMenu(winrt::auto_revoke, { this, &AppHost::_OpenSystemMenu });
|
||||
_revokers.QuitRequested = _logic.QuitRequested(winrt::auto_revoke, { this, &AppHost::_RequestQuitAll });
|
||||
_revokers.ShowWindowChanged = _logic.ShowWindowChanged(winrt::auto_revoke, { this, &AppHost::_ShowWindowChanged });
|
||||
|
||||
_window->UpdateTitle(_logic.Title());
|
||||
|
||||
@@ -1380,6 +1385,12 @@ void AppHost::_QuitAllRequested(const winrt::Windows::Foundation::IInspectable&,
|
||||
args.BeforeQuitAllAction(_SaveWindowLayouts());
|
||||
}
|
||||
|
||||
void AppHost::_ShowWindowChanged(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Microsoft::Terminal::Control::ShowWindowArgs& args)
|
||||
{
|
||||
_window->ShowWindowChanged(args.ShowOrHide());
|
||||
}
|
||||
|
||||
void AppHost::_SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
|
||||
@@ -112,6 +112,9 @@ private:
|
||||
void _QuitAllRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Microsoft::Terminal::Remoting::QuitAllRequestedArgs& args);
|
||||
|
||||
void _ShowWindowChanged(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Microsoft::Terminal::Control::ShowWindowArgs& args);
|
||||
|
||||
void _CreateNotificationIcon();
|
||||
void _DestroyNotificationIcon();
|
||||
void _ShowNotificationIconRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
@@ -157,6 +160,7 @@ private:
|
||||
winrt::TerminalApp::AppLogic::SummonWindowRequested_revoker SummonWindowRequested;
|
||||
winrt::TerminalApp::AppLogic::OpenSystemMenu_revoker OpenSystemMenu;
|
||||
winrt::TerminalApp::AppLogic::QuitRequested_revoker QuitRequested;
|
||||
winrt::TerminalApp::AppLogic::ShowWindowChanged_revoker ShowWindowChanged;
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager::ShowNotificationIconRequested_revoker ShowNotificationIconRequested;
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager::HideNotificationIconRequested_revoker HideNotificationIconRequested;
|
||||
winrt::Microsoft::Terminal::Remoting::WindowManager::QuitAllRequested_revoker QuitAllRequested;
|
||||
|
||||
@@ -41,6 +41,11 @@ IslandWindow::~IslandWindow()
|
||||
_source.Close();
|
||||
}
|
||||
|
||||
HWND IslandWindow::GetInteropHandle() const
|
||||
{
|
||||
return _interopWindowHandle;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Create the actual window that we'll use for the application.
|
||||
// Arguments:
|
||||
@@ -471,13 +476,18 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
||||
{
|
||||
if (wparam == SIZE_RESTORED || wparam == SIZE_MAXIMIZED)
|
||||
{
|
||||
_WindowVisibilityChangedHandlers(true);
|
||||
_MaximizeChangedHandlers(wparam == SIZE_MAXIMIZED);
|
||||
}
|
||||
|
||||
if (wparam == SIZE_MINIMIZED && _isQuakeWindow)
|
||||
if (wparam == SIZE_MINIMIZED)
|
||||
{
|
||||
ShowWindow(GetHandle(), SW_HIDE);
|
||||
return 0;
|
||||
_WindowVisibilityChangedHandlers(false);
|
||||
if (_isQuakeWindow)
|
||||
{
|
||||
ShowWindow(GetHandle(), SW_HIDE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -538,13 +548,14 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
||||
return 0;
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
{
|
||||
// Pull out the parameters from the call.
|
||||
auto lpwpos = (LPWINDOWPOS)lparam;
|
||||
|
||||
// GH#10274 - if the quake window gets moved to another monitor via aero
|
||||
// snap (win+shift+arrows), then re-adjust the size for the new monitor.
|
||||
if (IsQuakeWindow())
|
||||
{
|
||||
// Retrieve the suggested dimensions and make a rect and size.
|
||||
LPWINDOWPOS lpwpos = (LPWINDOWPOS)lparam;
|
||||
|
||||
// We only need to apply restrictions if the position is changing.
|
||||
// The SWP_ flags are confusing to read. This is
|
||||
// "if we're not moving the window, do nothing."
|
||||
@@ -813,6 +824,15 @@ void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop)
|
||||
}
|
||||
}
|
||||
|
||||
void IslandWindow::ShowWindowChanged(const bool showOrHide)
|
||||
{
|
||||
const auto hwnd = GetHandle();
|
||||
if (hwnd)
|
||||
{
|
||||
PostMessage(hwnd, WM_SYSCOMMAND, showOrHide ? SC_RESTORE : SC_MINIMIZE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description
|
||||
// - Flash the taskbar icon, indicating to the user that something needs their attention
|
||||
void IslandWindow::FlashTaskbar()
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
virtual void MakeWindow() noexcept;
|
||||
void Close();
|
||||
virtual void OnSize(const UINT width, const UINT height);
|
||||
HWND GetInteropHandle() const;
|
||||
|
||||
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
|
||||
void OnResize(const UINT width, const UINT height) override;
|
||||
@@ -42,6 +43,7 @@ public:
|
||||
void FocusModeChanged(const bool focusMode);
|
||||
void FullscreenChanged(const bool fullscreen);
|
||||
void SetAlwaysOnTop(const bool alwaysOnTop);
|
||||
void ShowWindowChanged(const bool showOrHide);
|
||||
|
||||
void FlashTaskbar();
|
||||
void SetTaskbarProgress(const size_t state, const size_t progress);
|
||||
@@ -76,6 +78,7 @@ public:
|
||||
WINRT_CALLBACK(MaximizeChanged, winrt::delegate<void(bool)>);
|
||||
|
||||
WINRT_CALLBACK(WindowMoved, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(WindowVisibilityChanged, winrt::delegate<void(bool)>);
|
||||
|
||||
protected:
|
||||
void ForceResize()
|
||||
|
||||
@@ -67,6 +67,10 @@ void PtySignalInputThread::ConnectConsole() noexcept
|
||||
{
|
||||
_DoResizeWindow(*_earlyResize);
|
||||
}
|
||||
if (_earlyReparent)
|
||||
{
|
||||
_DoSetWindowParent(*_earlyReparent);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -119,6 +123,26 @@ void PtySignalInputThread::ConnectConsole() noexcept
|
||||
|
||||
break;
|
||||
}
|
||||
case PtySignal::SetParent:
|
||||
{
|
||||
SetParentData reparentMessage = { 0 };
|
||||
_GetData(&reparentMessage, sizeof(reparentMessage));
|
||||
|
||||
LockConsole();
|
||||
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });
|
||||
|
||||
// todo
|
||||
if (!_consoleConnected)
|
||||
{
|
||||
_earlyReparent = reparentMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
_DoSetWindowParent(reparentMessage);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
THROW_HR(E_UNEXPECTED);
|
||||
@@ -147,6 +171,11 @@ void PtySignalInputThread::_DoClearBuffer()
|
||||
_pConApi->ClearBuffer();
|
||||
}
|
||||
|
||||
void PtySignalInputThread::_DoSetWindowParent(const SetParentData& data)
|
||||
{
|
||||
_pConApi->ReparentWindow(data.handle);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves bytes from the file stream and exits or throws errors should the pipe state
|
||||
// be compromised.
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Microsoft::Console
|
||||
enum class PtySignal : unsigned short
|
||||
{
|
||||
ClearBuffer = 2,
|
||||
SetParent = 3,
|
||||
ResizeWindow = 8
|
||||
};
|
||||
|
||||
@@ -49,10 +50,15 @@ namespace Microsoft::Console
|
||||
unsigned short sx;
|
||||
unsigned short sy;
|
||||
};
|
||||
struct SetParentData
|
||||
{
|
||||
uint64_t handle;
|
||||
};
|
||||
|
||||
[[nodiscard]] HRESULT _InputThread();
|
||||
bool _GetData(_Out_writes_bytes_(cbBuffer) void* const pBuffer, const DWORD cbBuffer);
|
||||
void _DoResizeWindow(const ResizeWindowData& data);
|
||||
void _DoSetWindowParent(const SetParentData& data);
|
||||
void _DoClearBuffer();
|
||||
void _Shutdown();
|
||||
|
||||
@@ -62,5 +68,8 @@ namespace Microsoft::Console
|
||||
bool _consoleConnected;
|
||||
std::optional<ResizeWindowData> _earlyResize;
|
||||
std::unique_ptr<Microsoft::Console::VirtualTerminal::ConGetSet> _pConApi;
|
||||
|
||||
public:
|
||||
std::optional<SetParentData> _earlyReparent;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -215,6 +215,10 @@ bool VtIo::IsUsingVt() const
|
||||
g.pRender->AddRenderEngine(_pVtRenderEngine.get());
|
||||
g.getConsoleInformation().GetActiveOutputBuffer().SetTerminalConnection(_pVtRenderEngine.get());
|
||||
g.getConsoleInformation().GetActiveInputBuffer()->SetTerminalConnection(_pVtRenderEngine.get());
|
||||
ServiceLocator::SetPseudoWindowCallback([&](bool showOrHide) -> void {
|
||||
// Set the remote window visibility to the request
|
||||
LOG_IF_FAILED(_pVtRenderEngine->SetWindowVisibility(showOrHide));
|
||||
});
|
||||
}
|
||||
CATCH_RETURN();
|
||||
}
|
||||
@@ -254,6 +258,16 @@ bool VtIo::IsUsingVt() const
|
||||
|
||||
if (_pPtySignalInputThread)
|
||||
{
|
||||
// IMPORTANT! Start the pseudo window on this thread. This thread has a
|
||||
// message pump. If you DON'T, then a DPI change in the parent hwnd will
|
||||
// cause us to get a dpi change as well, which we'll never deque and
|
||||
// handle, effectively HANGING THE PARENT HWND. super bad.
|
||||
//
|
||||
// TODO! clean this up
|
||||
if (_pPtySignalInputThread->_earlyReparent.has_value())
|
||||
{
|
||||
ServiceLocator::LocatePseudoWindow(reinterpret_cast<HWND>(_pPtySignalInputThread->_earlyReparent.value().handle));
|
||||
}
|
||||
// Let the signal thread know that the console is connected
|
||||
_pPtySignalInputThread->ConnectConsole();
|
||||
}
|
||||
|
||||
@@ -503,6 +503,19 @@ void ConhostInternalGetSet::SetCursorStyle(const CursorType style)
|
||||
_io.GetActiveOutputBuffer().GetTextBuffer().GetCursor().SetType(style);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Shows or hides the active window when asked.
|
||||
// Arguments:
|
||||
// - showOrHide - True for show, False for hide. Matching WM_SHOWWINDOW lParam.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ConhostInternalGetSet::ShowWindow(bool showOrHide)
|
||||
{
|
||||
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
const auto hwnd = gci.IsInVtIoMode() ? ServiceLocator::LocatePseudoWindow() : ServiceLocator::LocateConsoleWindow()->GetWindowHandle();
|
||||
::ShowWindow(hwnd, showOrHide ? SW_NORMAL : SW_MINIMIZE);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Forces the renderer to repaint the screen. If the input screen buffer is
|
||||
// not the active one, then just do nothing. We only want to redraw the
|
||||
@@ -892,3 +905,20 @@ void ConhostInternalGetSet::UpdateSoftFont(const gsl::span<const uint16_t> bitPa
|
||||
pRender->UpdateSoftFont(bitPattern, cellSize, centeringHint);
|
||||
}
|
||||
}
|
||||
|
||||
void ConhostInternalGetSet::ReparentWindow(const uint64_t handle)
|
||||
{
|
||||
// This will initialize s_interactivityFactory for us. It will also
|
||||
// conveniently return 0 when we're on OneCore.
|
||||
if (const auto psuedoHwnd{ ServiceLocator::LocatePseudoWindow(reinterpret_cast<HWND>(handle)) })
|
||||
{
|
||||
LOG_LAST_ERROR_IF_NULL(::SetParent(psuedoHwnd, reinterpret_cast<HWND>(handle)));
|
||||
}
|
||||
}
|
||||
|
||||
void ConhostInternalGetSet::FocusChanged(const bool focused)
|
||||
{
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& gci = g.getConsoleInformation();
|
||||
gci.ProcessHandleList.ModifyConsoleProcessFocus(focused);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ public:
|
||||
CursorType GetUserDefaultCursorStyle() const override;
|
||||
void SetCursorStyle(CursorType const style) override;
|
||||
|
||||
void ShowWindow(bool showOrHide) override;
|
||||
void RefreshWindow() override;
|
||||
bool ResizeWindow(const size_t width, const size_t height) override;
|
||||
void SuppressResizeRepaint() override;
|
||||
@@ -116,6 +117,9 @@ public:
|
||||
const SIZE cellSize,
|
||||
const size_t centeringHint) override;
|
||||
|
||||
void ReparentWindow(const uint64_t handle) override;
|
||||
void FocusChanged(const bool focused) override;
|
||||
|
||||
private:
|
||||
void _modifyLines(const size_t count, const bool insert);
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ HRESULT WINAPI ConptyResizePseudoConsole(HPCON hPC, COORD size);
|
||||
|
||||
HRESULT WINAPI ConptyClearPseudoConsole(HPCON hPC);
|
||||
|
||||
HRESULT WINAPI ConptyReparentPseudoConsole(HPCON hPC, HWND newParent);
|
||||
|
||||
VOID WINAPI ConptyClosePseudoConsole(HPCON hPC);
|
||||
|
||||
HRESULT WINAPI ConptyPackPseudoConsole(HANDLE hServerProcess, HANDLE hRef, HANDLE hSignal, HPCON* phPC);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "InteractivityFactory.hpp"
|
||||
|
||||
#include <dwmapi.h>
|
||||
|
||||
#ifdef BUILD_ONECORE_INTERACTIVITY
|
||||
#include "..\onecore\AccessibilityNotifier.hpp"
|
||||
#include "..\onecore\ConsoleControl.hpp"
|
||||
@@ -291,12 +293,12 @@ using namespace Microsoft::Console::Interactivity;
|
||||
// - hwnd: Receives the value of the newly created window's HWND.
|
||||
// Return Value:
|
||||
// - STATUS_SUCCESS on success, otherwise an appropriate error.
|
||||
[[nodiscard]] NTSTATUS InteractivityFactory::CreatePseudoWindow(HWND& hwnd)
|
||||
[[nodiscard]] NTSTATUS InteractivityFactory::CreatePseudoWindow(HWND& hwnd, const HWND owner)
|
||||
{
|
||||
hwnd = nullptr;
|
||||
ApiLevel level;
|
||||
NTSTATUS status = ApiDetector::DetectNtUserWindow(&level);
|
||||
;
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
try
|
||||
@@ -306,18 +308,41 @@ using namespace Microsoft::Console::Interactivity;
|
||||
switch (level)
|
||||
{
|
||||
case ApiLevel::Win32:
|
||||
{
|
||||
pseudoClass.lpszClassName = PSEUDO_WINDOW_CLASS;
|
||||
pseudoClass.lpfnWndProc = DefWindowProc;
|
||||
pseudoClass.lpfnWndProc = s_PseudoWindowProc;
|
||||
RegisterClass(&pseudoClass);
|
||||
|
||||
// const auto windowStyle = (owner == HWND_DESKTOP) ? WS_OVERLAPPEDWINDOW : WS_CHILD;
|
||||
const auto windowStyle = WS_OVERLAPPEDWINDOW;
|
||||
const auto exStyles = WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_LAYERED;
|
||||
// Attempt to create window
|
||||
hwnd = CreateWindowExW(
|
||||
0, PSEUDO_WINDOW_CLASS, nullptr, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, HWND_DESKTOP, nullptr, nullptr, nullptr);
|
||||
exStyles,
|
||||
PSEUDO_WINDOW_CLASS,
|
||||
nullptr,
|
||||
windowStyle, //WS_CHILD, //WS_OVERLAPPEDWINDOW,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
// Niksa just had the parent as HWND_DESKTOP always,
|
||||
// This branch tests a merged version of the prototypes
|
||||
owner /*(HWND)0x00070C6A*/ /*HWND_DESKTOP*/, // parent
|
||||
nullptr,
|
||||
nullptr,
|
||||
this);
|
||||
if (hwnd == nullptr)
|
||||
{
|
||||
DWORD const gle = GetLastError();
|
||||
status = NTSTATUS_FROM_WIN32(gle);
|
||||
}
|
||||
|
||||
/*BOOL const cloak = TRUE;
|
||||
DwmSetWindowAttribute(hwnd, DWMWA_CLOAK, &cloak, sizeof(cloak));*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef BUILD_ONECORE_INTERACTIVITY
|
||||
case ApiLevel::OneCore:
|
||||
@@ -338,4 +363,118 @@ using namespace Microsoft::Console::Interactivity;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gives the pseudo console window a target to relay show/hide window messages
|
||||
// Arguments:
|
||||
// - func - A function that will take a true for "show" and false for "hide" and
|
||||
// relay that information to the attached terminal to adjust its window state.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void InteractivityFactory::SetPseudoWindowCallback(std::function<void(bool)> func)
|
||||
{
|
||||
_pseudoWindowMessageCallback = func;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Static window procedure for pseudo console windows
|
||||
// - Processes set-up on create to stow the "this" pointer to specific instantiations and routes
|
||||
// to the specific object on future calls.
|
||||
// Arguments:
|
||||
// - hWnd - Associated window handle from message
|
||||
// - Message - ID of message in queue
|
||||
// - wParam - Variable wParam depending on message type
|
||||
// - lParam - Variable lParam depending on message type
|
||||
// Return Value:
|
||||
// - 0 if we processed this message. See details on how a WindowProc is implemented.
|
||||
[[nodiscard]] LRESULT CALLBACK InteractivityFactory::s_PseudoWindowProc(_In_ HWND hWnd, _In_ UINT Message, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
||||
{
|
||||
// Save the pointer here to the specific window instance when one is created
|
||||
if (Message == WM_CREATE)
|
||||
{
|
||||
const CREATESTRUCT* const pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
|
||||
|
||||
InteractivityFactory* const pFactory = reinterpret_cast<InteractivityFactory*>(pCreateStruct->lpCreateParams);
|
||||
SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pFactory));
|
||||
}
|
||||
|
||||
// Dispatch the message to the specific class instance
|
||||
InteractivityFactory* const pFactory = reinterpret_cast<InteractivityFactory*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
|
||||
if (pFactory != nullptr)
|
||||
{
|
||||
return pFactory->PseudoWindowProc(hWnd, Message, wParam, lParam);
|
||||
}
|
||||
|
||||
// If we get this far, call the default window proc
|
||||
return DefWindowProcW(hWnd, Message, wParam, lParam);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Per-object window procedure for pseudo console windows
|
||||
// Arguments:
|
||||
// - hWnd - Associated window handle from message
|
||||
// - Message - ID of message in queue
|
||||
// - wParam - Variable wParam depending on message type
|
||||
// - lParam - Variable lParam depending on message type
|
||||
// Return Value:
|
||||
// - 0 if we processed this message. See details on how a WindowProc is implemented.
|
||||
[[nodiscard]] LRESULT CALLBACK InteractivityFactory::PseudoWindowProc(_In_ HWND hWnd, _In_ UINT Message, _In_ WPARAM wParam, _In_ LPARAM lParam)
|
||||
{
|
||||
switch (Message)
|
||||
{
|
||||
// NOTE: To the future reader, all window messages that are talked about but unused were tested
|
||||
// during prototyping and didn't give quite the results needed to determine show/hide window
|
||||
// state. The notes are left here for future expeditions into message queues.
|
||||
// case WM_QUERYOPEN:
|
||||
// It can be fun to toggle WM_QUERYOPEN but DefWindowProc returns TRUE.
|
||||
case WM_SIZE:
|
||||
{
|
||||
if (wParam == SIZE_RESTORED)
|
||||
{
|
||||
_WritePseudoWindowCallback(true);
|
||||
}
|
||||
|
||||
if (wParam == SIZE_MINIMIZED)
|
||||
{
|
||||
_WritePseudoWindowCallback(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// case WM_WINDOWPOSCHANGING:
|
||||
// As long as user32 didn't eat the `ShowWindow` call because the window state requested
|
||||
// matches the existing WS_VISIBLE state of the HWND... we should hear from it in WM_WINDOWPOSCHANGING.
|
||||
// WM_WINDOWPOSCHANGING can tell us a bunch through the flags fields.
|
||||
// We can also check IsIconic/IsZoomed on the HWND during the message
|
||||
// and we could suppress the change to prevent things from happening.
|
||||
// case WM_SYSCOMMAND:
|
||||
// WM_SYSCOMMAND will not come through. Don't try.
|
||||
case WM_SHOWWINDOW:
|
||||
// WM_SHOWWINDOW comes through on some of the messages.
|
||||
{
|
||||
if (0 == lParam) // Someone explicitly called ShowWindow on us.
|
||||
{
|
||||
_WritePseudoWindowCallback((bool)wParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we get this far, call the default window proc
|
||||
return DefWindowProcW(hWnd, Message, wParam, lParam);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper for the pseudo console message loop to send a notification
|
||||
// when it realizes we should be showing or hiding the window.
|
||||
// - Simply skips if no callback is installed.
|
||||
// Arguments:
|
||||
// - showOrHide: Show is true; hide is false.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void InteractivityFactory::_WritePseudoWindowCallback(bool showOrHide)
|
||||
{
|
||||
if (_pseudoWindowMessageCallback)
|
||||
{
|
||||
_pseudoWindowMessageCallback(showOrHide);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
@@ -26,6 +26,21 @@ namespace Microsoft::Console::Interactivity
|
||||
[[nodiscard]] NTSTATUS CreateAccessibilityNotifier(_Inout_ std::unique_ptr<IAccessibilityNotifier>& notifier);
|
||||
[[nodiscard]] NTSTATUS CreateSystemConfigurationProvider(_Inout_ std::unique_ptr<ISystemConfigurationProvider>& provider);
|
||||
|
||||
[[nodiscard]] NTSTATUS CreatePseudoWindow(HWND& hwnd);
|
||||
[[nodiscard]] NTSTATUS CreatePseudoWindow(HWND& hwnd, const HWND owner);
|
||||
void SetPseudoWindowCallback(std::function<void(bool)> func);
|
||||
|
||||
// Wndproc
|
||||
[[nodiscard]] static LRESULT CALLBACK s_PseudoWindowProc(_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam);
|
||||
[[nodiscard]] LRESULT CALLBACK PseudoWindowProc(_In_ HWND,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam);
|
||||
|
||||
private:
|
||||
void _WritePseudoWindowCallback(bool showOrHide);
|
||||
std::function<void(bool)> _pseudoWindowMessageCallback;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -285,13 +285,34 @@ Globals& ServiceLocator::LocateGlobals()
|
||||
return s_globals;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Installs a callback method to receive notifications when the pseudo console
|
||||
// window is shown or hidden by an attached client application (so we can
|
||||
// translate it and forward it to the attached terminal, in case it would like
|
||||
// to react accordingly.)
|
||||
// Arguments:
|
||||
// - func - Callback function that takes True as Show and False as Hide.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ServiceLocator::SetPseudoWindowCallback(std::function<void(bool)> func)
|
||||
{
|
||||
// Force the whole window to be put together first.
|
||||
// We don't really need the handle, we just want to leverage the setup steps.
|
||||
(void)LocatePseudoWindow();
|
||||
|
||||
if (s_interactivityFactory)
|
||||
{
|
||||
s_interactivityFactory->SetPseudoWindowCallback(func);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the pseudo console window, or attempts to instantiate one.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a reference to the pseudoconsole window.
|
||||
HWND ServiceLocator::LocatePseudoWindow()
|
||||
HWND ServiceLocator::LocatePseudoWindow(const HWND owner)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
if (!s_pseudoWindowInitialized)
|
||||
@@ -304,16 +325,24 @@ HWND ServiceLocator::LocatePseudoWindow()
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
HWND hwnd;
|
||||
status = s_interactivityFactory->CreatePseudoWindow(hwnd);
|
||||
status = s_interactivityFactory->CreatePseudoWindow(hwnd, owner);
|
||||
s_pseudoWindow.reset(hwnd);
|
||||
}
|
||||
|
||||
s_pseudoWindowInitialized = true;
|
||||
}
|
||||
LOG_IF_NTSTATUS_FAILED(status);
|
||||
return s_pseudoWindow.get();
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
// void ServiceLocator::ReparentPseudoHwnd(HWND newParent)
|
||||
// {
|
||||
// // This will initialize s_interactivityFactory for us. It will also conveniently return 0 when we're on OneCore.
|
||||
// if (const auto psuedoHwnd{ LocatePseudoWindow() })
|
||||
// {
|
||||
// ::SetParent(psuedoHwnd, newParent);
|
||||
// }
|
||||
// }
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ namespace Microsoft::Console::Interactivity
|
||||
[[nodiscard]] virtual NTSTATUS CreateAccessibilityNotifier(_Inout_ std::unique_ptr<IAccessibilityNotifier>& notifier) = 0;
|
||||
[[nodiscard]] virtual NTSTATUS CreateSystemConfigurationProvider(_Inout_ std::unique_ptr<ISystemConfigurationProvider>& provider) = 0;
|
||||
|
||||
[[nodiscard]] virtual NTSTATUS CreatePseudoWindow(HWND& hwnd) = 0;
|
||||
virtual void SetPseudoWindowCallback(std::function<void(bool)> func) = 0;
|
||||
[[nodiscard]] virtual NTSTATUS CreatePseudoWindow(HWND& hwnd, const HWND owner) = 0;
|
||||
};
|
||||
|
||||
inline IInteractivityFactory::~IInteractivityFactory() {}
|
||||
|
||||
@@ -84,7 +84,8 @@ namespace Microsoft::Console::Interactivity
|
||||
|
||||
static Globals& LocateGlobals();
|
||||
|
||||
static HWND LocatePseudoWindow();
|
||||
static void SetPseudoWindowCallback(std::function<void(bool)> func);
|
||||
static HWND LocatePseudoWindow(const HWND owner = 0 /*HWND_DESKTOP*/);
|
||||
|
||||
protected:
|
||||
ServiceLocator(ServiceLocator const&) = delete;
|
||||
|
||||
@@ -530,6 +530,25 @@ CATCH_RETURN();
|
||||
return _Flush();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sends a command to set the terminal's window to visible or hidden
|
||||
// Arguments:
|
||||
// - showOrHide - True if show; false if hide.
|
||||
// Return Value:
|
||||
// - S_OK or suitable HRESULT error from either conversion or writing pipe.
|
||||
[[nodiscard]] HRESULT XtermEngine::SetWindowVisibility(const bool showOrHide) noexcept
|
||||
{
|
||||
if (showOrHide)
|
||||
{
|
||||
RETURN_IF_FAILED(_Write("\x1b[1t"));
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_IF_FAILED(_Write("\x1b[2t"));
|
||||
}
|
||||
return _Flush();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the window's title string. Emits the VT sequence to SetWindowTitle.
|
||||
// Arguments:
|
||||
|
||||
@@ -53,6 +53,8 @@ namespace Microsoft::Console::Render
|
||||
|
||||
[[nodiscard]] HRESULT WriteTerminalW(const std::wstring_view str) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT SetWindowVisibility(const bool showOrHide) noexcept override;
|
||||
|
||||
protected:
|
||||
// I'm using a non-class enum here, so that the values
|
||||
// are trivially convertible and comparable to bool.
|
||||
|
||||
@@ -82,6 +82,7 @@ namespace Microsoft::Console::Render
|
||||
void SetResizeQuirk(const bool resizeQuirk);
|
||||
[[nodiscard]] virtual HRESULT ManuallyClearScrollback() noexcept;
|
||||
[[nodiscard]] HRESULT RequestWin32Input() noexcept;
|
||||
[[nodiscard]] virtual HRESULT SetWindowVisibility(const bool showOrHide) noexcept = 0;
|
||||
|
||||
protected:
|
||||
wil::unique_hfile _hFile;
|
||||
|
||||
@@ -456,7 +456,11 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
|
||||
return pReceiveMsg;
|
||||
}
|
||||
|
||||
gci.ProcessHandleList.ModifyConsoleProcessFocus(WI_IsFlagSet(gci.Flags, CONSOLE_HAS_FOCUS));
|
||||
// const bool inConpty{ gci.IsInVtIoMode() };
|
||||
const bool hasFocus{ WI_IsFlagSet(gci.Flags, CONSOLE_HAS_FOCUS) };
|
||||
// const auto grantFG{ inConpty || hasFocus };
|
||||
const auto grantFG{ hasFocus };
|
||||
gci.ProcessHandleList.ModifyConsoleProcessFocus(grantFG);
|
||||
|
||||
// Create the handles.
|
||||
|
||||
|
||||
@@ -406,6 +406,8 @@ namespace Microsoft::Console::VirtualTerminal::DispatchTypes
|
||||
enum WindowManipulationType : size_t
|
||||
{
|
||||
Invalid = 0,
|
||||
DeIconifyWindow = 1,
|
||||
IconifyWindow = 2,
|
||||
RefreshWindow = 7,
|
||||
ResizeWindowInCharacters = 8,
|
||||
};
|
||||
|
||||
@@ -42,5 +42,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
const size_t col) = 0;
|
||||
|
||||
virtual bool IsVtInputEnabled() const = 0;
|
||||
|
||||
virtual bool FocusChanged(const bool focused) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -100,6 +100,12 @@ bool InteractDispatch::WindowManipulation(const DispatchTypes::WindowManipulatio
|
||||
// MSFT:13271146 - QueryScreenSize
|
||||
switch (function)
|
||||
{
|
||||
case DispatchTypes::WindowManipulationType::DeIconifyWindow:
|
||||
_pConApi->ShowWindow(true);
|
||||
return true;
|
||||
case DispatchTypes::WindowManipulationType::IconifyWindow:
|
||||
_pConApi->ShowWindow(false);
|
||||
return true;
|
||||
case DispatchTypes::WindowManipulationType::RefreshWindow:
|
||||
_pConApi->RefreshWindow();
|
||||
return true;
|
||||
@@ -168,3 +174,13 @@ bool InteractDispatch::IsVtInputEnabled() const
|
||||
{
|
||||
return _pConApi->IsVtInputEnabled();
|
||||
}
|
||||
|
||||
bool InteractDispatch::FocusChanged(const bool focused) const
|
||||
{
|
||||
// * We should assume this is false by default?
|
||||
// * TODO!: ConPTY should ask for this mode? Yea? Lets make sure that VTE will send that sequence even without other mouse sequences enabled.
|
||||
// - in the past, this is something we've made opt-in (request cursor, for example. Maybe also the other mouse modes, can't recall)
|
||||
// * gotta make sure that we can always handle the focus events, even if the client hasn't requested them.
|
||||
_pConApi->FocusChanged(focused);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
|
||||
bool IsVtInputEnabled() const override;
|
||||
|
||||
bool FocusChanged(const bool focused) const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<ConGetSet> _pConApi;
|
||||
};
|
||||
|
||||
@@ -2179,6 +2179,12 @@ bool AdaptDispatch::WindowManipulation(const DispatchTypes::WindowManipulationTy
|
||||
// MSFT:13271146 - QueryScreenSize
|
||||
switch (function)
|
||||
{
|
||||
case DispatchTypes::WindowManipulationType::DeIconifyWindow:
|
||||
_pConApi->ShowWindow(true);
|
||||
return true;
|
||||
case DispatchTypes::WindowManipulationType::IconifyWindow:
|
||||
_pConApi->ShowWindow(false);
|
||||
return true;
|
||||
case DispatchTypes::WindowManipulationType::RefreshWindow:
|
||||
_pConApi->RefreshWindow();
|
||||
return true;
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
virtual void SetCursorStyle(const CursorType style) = 0;
|
||||
virtual void WriteControlInput(const KeyEvent key) = 0;
|
||||
virtual void RefreshWindow() = 0;
|
||||
virtual void ShowWindow(bool showOrHide) = 0;
|
||||
|
||||
virtual void SetConsoleOutputCP(const unsigned int codepage) = 0;
|
||||
virtual unsigned int GetConsoleOutputCP() const = 0;
|
||||
@@ -111,5 +112,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
virtual void UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
||||
const SIZE cellSize,
|
||||
const size_t centeringHint) = 0;
|
||||
|
||||
virtual void ReparentWindow(const uint64_t handle) = 0;
|
||||
virtual void FocusChanged(const bool focused) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -312,6 +312,12 @@ public:
|
||||
VERIFY_ARE_EQUAL(_expectedCursorStyle, cursorType);
|
||||
}
|
||||
|
||||
void ShowWindow(bool showOrHide) override
|
||||
{
|
||||
Log::Comment(L"ShowWindow MOCK called...");
|
||||
VERIFY_ARE_EQUAL(_expectedShowWindow, showOrHide);
|
||||
}
|
||||
|
||||
void RefreshWindow() override
|
||||
{
|
||||
Log::Comment(L"RefreshWindow MOCK called...");
|
||||
@@ -422,6 +428,11 @@ public:
|
||||
VERIFY_ARE_EQUAL(_expectedCellSize.cy, cellSize.cy);
|
||||
}
|
||||
|
||||
void ReparentWindow(const uint64_t /*handle*/)
|
||||
{
|
||||
Log::Comment(L"UpdateSoftFont MOCK called...");
|
||||
}
|
||||
|
||||
void PrepData()
|
||||
{
|
||||
PrepData(CursorDirection::UP); // if called like this, the cursor direction doesn't matter.
|
||||
@@ -641,6 +652,7 @@ public:
|
||||
bool _setConsoleOutputCPResult = false;
|
||||
bool _getConsoleOutputCPResult = false;
|
||||
bool _moveToBottomResult = false;
|
||||
bool _expectedShowWindow = false;
|
||||
|
||||
bool _getColorTableEntryResult = false;
|
||||
bool _setColorTableEntryResult = false;
|
||||
|
||||
@@ -421,6 +421,12 @@ bool InputStateMachineEngine::ActionCsiDispatch(const VTID id, const VTParameter
|
||||
case CsiActionCodes::DTTERM_WindowManipulation:
|
||||
success = _pDispatch->WindowManipulation(parameters.at(0), parameters.at(1), parameters.at(2));
|
||||
break;
|
||||
case CsiActionCodes::FocusIn:
|
||||
success = _pDispatch->FocusChanged(true);
|
||||
break;
|
||||
case CsiActionCodes::FocusOut:
|
||||
success = _pDispatch->FocusChanged(false);
|
||||
break;
|
||||
case CsiActionCodes::Win32KeyboardInput:
|
||||
{
|
||||
// Use WriteCtrlKey here, even for keys that _aren't_ control keys,
|
||||
|
||||
@@ -58,6 +58,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
ArrowLeft = VTID("D"),
|
||||
Home = VTID("H"),
|
||||
End = VTID("F"),
|
||||
FocusIn = VTID("I"),
|
||||
FocusOut = VTID("O"),
|
||||
MouseDown = VTID("<M"),
|
||||
MouseUp = VTID("<m"),
|
||||
Generic = VTID("~"), // Used for a whole bunch of possible keys
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<RootNamespace>Scratch</RootNamespace>
|
||||
<ProjectName>Scratch</ProjectName>
|
||||
<TargetName>Scratch</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
@@ -21,6 +21,14 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- subsume fmt, one of our dependencies, into contypes. -->
|
||||
<ProjectReference Include="..\..\dep\fmt\fmt.vcxproj">
|
||||
<Project>{6bae5851-50d5-4934-8d5e-30361a8a40f3}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
||||
<Import Project="..\..\common.build.post.props" />
|
||||
<Import Project="..\..\common.build.tests.props" />
|
||||
|
||||
@@ -1,10 +1,216 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
#include "../../inc/LibraryIncludes.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// This wmain exists for help in writing scratch programs while debugging.
|
||||
int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/)
|
||||
// Register the window class.
|
||||
const wchar_t CLASS_NAME[] = L"Sample Window Class";
|
||||
|
||||
struct handle_data
|
||||
{
|
||||
unsigned long process_id;
|
||||
HWND window_handle;
|
||||
};
|
||||
|
||||
BOOL is_main_window(HWND handle)
|
||||
{
|
||||
auto owner{ GetWindow(handle, GW_OWNER) };
|
||||
// wprintf(fmt::format(L"\t\towner: {}\n", reinterpret_cast<unsigned long long>(owner)).c_str());
|
||||
return owner == (HWND)0 && IsWindowVisible(handle);
|
||||
}
|
||||
|
||||
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
|
||||
{
|
||||
// wprintf(fmt::format(L"enum_windows_callback\n").c_str());
|
||||
handle_data& data = *(handle_data*)lParam;
|
||||
unsigned long process_id = 0;
|
||||
GetWindowThreadProcessId(handle, &process_id);
|
||||
const bool pidDidntMatch{ data.process_id != process_id };
|
||||
// wprintf(fmt::format(L"\tpidDidntMatch: {}\n", pidDidntMatch).c_str());
|
||||
const bool wasntMainWindow{ !is_main_window(handle) };
|
||||
// wprintf(fmt::format(L"\twasntMainWindow: {}\n", wasntMainWindow).c_str());
|
||||
if (pidDidntMatch || wasntMainWindow)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wprintf(fmt::format(L"\tpidDidntMatch: {}\n", pidDidntMatch).c_str());
|
||||
wprintf(fmt::format(L"\twasntMainWindow: {}\n", wasntMainWindow).c_str());
|
||||
|
||||
auto owner{ GetWindow(handle, GW_OWNER) };
|
||||
wprintf(fmt::format(L"\t\thandle: {}\n", reinterpret_cast<unsigned long long>(handle)).c_str());
|
||||
wprintf(fmt::format(L"\t\towner: {}\n", reinterpret_cast<unsigned long long>(owner)).c_str());
|
||||
|
||||
data.window_handle = handle;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HWND find_main_window(unsigned long process_id)
|
||||
{
|
||||
handle_data data;
|
||||
data.process_id = process_id;
|
||||
data.window_handle = 0;
|
||||
EnumWindows(enum_windows_callback, (LPARAM)&data);
|
||||
return data.window_handle;
|
||||
}
|
||||
|
||||
static LRESULT __stdcall WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
|
||||
{
|
||||
static bool gotKeyDown{ false };
|
||||
switch (message)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
gotKeyDown = true;
|
||||
return 0;
|
||||
case WM_KEYUP:
|
||||
if (gotKeyDown)
|
||||
DestroyWindow(window);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(window, message, wparam, lparam);
|
||||
}
|
||||
|
||||
int doTheWindowThing(HWND hwndToUseAsParent)
|
||||
{
|
||||
const auto hInst{ GetModuleHandle(NULL) };
|
||||
wprintf(fmt::format(L"=====Creating a Window, then a MessageBox, using {} as the parent HWND=====\n", reinterpret_cast<unsigned long long>(hwndToUseAsParent)).c_str());
|
||||
|
||||
auto doWindowCreateLoop = [&](bool child) {
|
||||
// Create the window.
|
||||
HWND hwnd = CreateWindowEx(
|
||||
0, // Optional window styles.
|
||||
CLASS_NAME, // Window class
|
||||
L"Learn to Program Windows", // Window text
|
||||
WS_OVERLAPPEDWINDOW | (child ? WS_CHILD : 0), // Window style
|
||||
|
||||
// Size and position
|
||||
200,
|
||||
200,
|
||||
200,
|
||||
200,
|
||||
|
||||
hwndToUseAsParent, // Parent window
|
||||
NULL, // Menu
|
||||
hInst, // Instance handle
|
||||
NULL // Additional application data
|
||||
);
|
||||
|
||||
// wprintf(fmt::format(L"hwnd: {}\n", reinterpret_cast<unsigned long long>(hwnd)).c_str());
|
||||
|
||||
// const auto newHwnd{ find_main_window(pid) };
|
||||
// wprintf(fmt::format(L"newHwnd: {}\n", reinterpret_cast<unsigned long long>(newHwnd)).c_str());
|
||||
|
||||
if (hwnd == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
wprintf(fmt::format(L" created window\n").c_str());
|
||||
|
||||
ShowWindow(hwnd, SW_SHOW);
|
||||
MSG msg = {};
|
||||
while (GetMessage(&msg, NULL, 0, 0) > 0)
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
wprintf(fmt::format(L" window was closed\n").c_str());
|
||||
return 0;
|
||||
};
|
||||
|
||||
wprintf(fmt::format(L" create an unowned window...\n").c_str());
|
||||
doWindowCreateLoop(false);
|
||||
|
||||
wprintf(fmt::format(L" create a child window...\n").c_str());
|
||||
doWindowCreateLoop(true);
|
||||
|
||||
wprintf(fmt::format(L" Opening a MessageBoxW...\n").c_str());
|
||||
MessageBoxW(hwndToUseAsParent, L"foo", L"bar", MB_OK);
|
||||
wprintf(fmt::format(L" closed a MessageBoxW\n").c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int createSomeWindows(const HWND& consoleHwnd)
|
||||
{
|
||||
WNDCLASS wc = {};
|
||||
const auto hInst{ GetModuleHandle(NULL) };
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = hInst;
|
||||
wc.lpszClassName = CLASS_NAME;
|
||||
|
||||
RegisterClass(&wc);
|
||||
|
||||
wprintf(fmt::format(L"Make some windows, using NULL as the parent.\n").c_str());
|
||||
|
||||
doTheWindowThing(nullptr);
|
||||
wprintf(fmt::format(L"Now, with the console window handle.\n").c_str());
|
||||
doTheWindowThing(consoleHwnd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int doDefaultOutput()
|
||||
{
|
||||
const auto pid{ GetCurrentProcessId() };
|
||||
const auto consoleWindow{ GetConsoleWindow() };
|
||||
|
||||
wprintf(fmt::format(L"pid: {}\n", pid).c_str());
|
||||
wprintf(fmt::format(L"consoleWindow: {0:#010x}\n", reinterpret_cast<unsigned long long>(consoleWindow)).c_str());
|
||||
|
||||
const auto mainHwnd{ find_main_window(pid) };
|
||||
wprintf(fmt::format(L"mainHwnd: {0:#010x}\n", reinterpret_cast<unsigned long long>(mainHwnd)).c_str());
|
||||
|
||||
const auto consoleParent{ GetParent(consoleWindow) };
|
||||
wprintf(fmt::format(L"parent: {0:#010x}\n", reinterpret_cast<unsigned long long>(consoleParent)).c_str());
|
||||
const auto consoleOwner{ GetWindow(consoleWindow, GW_OWNER) };
|
||||
wprintf(fmt::format(L"owner: {0:#010x}\n", reinterpret_cast<unsigned long long>(consoleOwner)).c_str());
|
||||
const auto consoleAncestor_PARENT{ GetAncestor(consoleWindow, GA_PARENT) };
|
||||
const auto consoleAncestor_ROOT{ GetAncestor(consoleWindow, GA_ROOT) };
|
||||
const auto consoleAncestor_ROOTOWNER{ GetAncestor(consoleWindow, GA_ROOTOWNER) };
|
||||
wprintf(fmt::format(L"Ancestor_PARENT: {0:#010x}\n", reinterpret_cast<unsigned long long>(consoleAncestor_PARENT)).c_str());
|
||||
wprintf(fmt::format(L"Ancestor_ROOT: {0:#010x}\n", reinterpret_cast<unsigned long long>(consoleAncestor_ROOT)).c_str());
|
||||
wprintf(fmt::format(L"Ancestor_ROOTOWNER: {0:#010x}\n", reinterpret_cast<unsigned long long>(consoleAncestor_ROOTOWNER)).c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This wmain exists for help in writing scratch programs while debugging.
|
||||
int __cdecl wmain(int argc, WCHAR* argv[])
|
||||
{
|
||||
doDefaultOutput();
|
||||
|
||||
const auto consoleWindow{ GetConsoleWindow() };
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
HWND target = consoleWindow;
|
||||
std::wstring arg{ argv[1] };
|
||||
if (arg == L"--parent" && argc > 2)
|
||||
{
|
||||
target = GetAncestor(consoleWindow, GA_ROOT);
|
||||
arg = argv[2];
|
||||
}
|
||||
|
||||
if (arg == L"messagebox")
|
||||
{
|
||||
MessageBoxW(target, L"foo", L"bar", MB_OK);
|
||||
}
|
||||
else if (arg == L"windows")
|
||||
{
|
||||
createSomeWindows(target);
|
||||
}
|
||||
else if (arg == L"hide")
|
||||
{
|
||||
ShowWindow(target, SW_HIDE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -252,6 +252,37 @@ HRESULT _ClearPseudoConsole(_In_ const PseudoConsole* const pPty)
|
||||
return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - TODO!
|
||||
HRESULT _ReparentPseudoConsole(_In_ const PseudoConsole* const pPty, _In_ const HWND newParent)
|
||||
{
|
||||
if (pPty == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct _signal
|
||||
{
|
||||
const unsigned short id; // = PTY_SIGNAL_RESIZE_WINDOW;
|
||||
const uint64_t hwnd; // = reinterpret_cast<uint64_t>(newParent);
|
||||
} data{ PTY_SIGNAL_REPARENT_WINDOW, reinterpret_cast<uint64_t>(newParent) };
|
||||
#pragma pack(pop)
|
||||
|
||||
// unsigned short signalPacket[5];
|
||||
// signalPacket[0] = PTY_SIGNAL_RESIZE_WINDOW;
|
||||
// // hwnd is a uint64_t.
|
||||
// signalPacket[1] = size.X;
|
||||
// signalPacket[2] = size.Y;
|
||||
// signalPacket[3] = size.Y;
|
||||
// signalPacket[4] = size.Y;
|
||||
// static_assert(sizeof(data) == (10));
|
||||
// static_assert(sizeof(data) == (sizeof(unsigned short) + sizeof(HWND)));
|
||||
|
||||
const BOOL fSuccess = WriteFile(pPty->hSignal, &data, sizeof(data), nullptr, nullptr);
|
||||
return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - This closes each of the members of a PseudoConsole. It does not free the
|
||||
// data associated with the PseudoConsole. This is helpful for testing,
|
||||
@@ -423,6 +454,19 @@ extern "C" HRESULT WINAPI ConptyClearPseudoConsole(_In_ HPCON hPC)
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - TODO!
|
||||
extern "C" HRESULT WINAPI ConptyReparentPseudoConsole(_In_ HPCON hPC, HWND newParent)
|
||||
{
|
||||
const PseudoConsole* const pPty = (PseudoConsole*)hPC;
|
||||
HRESULT hr = pPty == nullptr ? E_INVALIDARG : S_OK;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _ReparentPseudoConsole(pPty, newParent);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// Closes the conpty and all associated state.
|
||||
// Client applications attached to the conpty will also behave as though the
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef struct _PseudoConsole
|
||||
// These are not defined publicly, but are used for controlling the conpty via
|
||||
// the signal pipe.
|
||||
#define PTY_SIGNAL_CLEAR_WINDOW (2u)
|
||||
#define PTY_SIGNAL_REPARENT_WINDOW (3u)
|
||||
#define PTY_SIGNAL_RESIZE_WINDOW (8u)
|
||||
|
||||
// CreatePseudoConsole Flags
|
||||
@@ -36,6 +37,7 @@ HRESULT _CreatePseudoConsole(const HANDLE hToken,
|
||||
|
||||
HRESULT _ResizePseudoConsole(_In_ const PseudoConsole* const pPty, _In_ const COORD size);
|
||||
HRESULT _ClearPseudoConsole(_In_ const PseudoConsole* const pPty);
|
||||
HRESULT _ReparentPseudoConsole(_In_ const PseudoConsole* const pPty, _In_ const HWND newParent);
|
||||
void _ClosePseudoConsoleMembers(_In_ PseudoConsole* pPty);
|
||||
VOID _ClosePseudoConsole(_In_ PseudoConsole* pPty);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user