Compare commits

...

34 commits

Author SHA1 Message Date
Dustin L. Howett 37decda639 Migrate spelling-0.0.19 changes from main 2020-07-30 12:13:45 -05:00
Mike Griese 8f3ad5dcd9 Merge remote-tracking branch 'origin/master' into dev/migrie/oop-scratch-4 2020-07-30 12:13:45 -05:00
Mike Griese 982d30467b some dead code cleanup 2020-07-30 11:06:59 -05:00
Mike Griese bb2920ec01 THIS WORKS 2020-07-22 16:43:50 -05:00
Mike Griese ecf99fac23 This doesn't crash immediately on resize, so it might be okay, right? 2020-07-22 16:30:29 -05:00
Mike Griese c86038926d we're failing to find the registration for ISwapChainPanelNative2, which is probably B A D. I'm gonna fork here and try and do the 'create the swapchain on the window process then hand it to the child' thing 2020-07-22 11:19:12 -05:00
Mike Griese 52b05e065e None of these suggestions worked for me, I'm sure I'm off my rocker 2020-07-21 08:24:04 -05:00
Mike Griese 81a80257c9 It's monday, and I tried TODO this, but the call to
```c++
    auto nativePanel2 = panel.try_as<ISwapChainPanelNative2>();
```

keeps failing in the server, but succeeding in the window process. This doesn't make any sense to me.
2020-07-21 07:52:49 -05:00
Mike Griese 1ea9fc26c8 Get the island spawning a server 2020-07-17 14:16:06 -05:00
Mike Griese e1d15105d7 add some swapchainpanels 2020-07-17 13:28:47 -05:00
Mike Griese d321ec084c Hey, lets make sure to get some XAML in there 2020-07-17 13:17:41 -05:00
Mike Griese f33c69d8b4 Add a scratch island project for testing 2020-07-17 13:01:07 -05:00
Michael Niksa 30b8335479 Use DComp surface handle for Swap Chain management. 2020-07-17 08:42:47 -05:00
Mike Griese 93b79fb23c Merge remote-tracking branch 'origin/master' into dev/migrie/oop-scratch-2 2020-07-17 08:42:19 -05:00
Mike Griese 7b8806b1fe These notes about ISwapChainPanelNative2 are VERY IMPORTANT 2020-07-16 09:53:20 -05:00
Mike Griese 8c5041b2ae dead ends, all dead ends 2020-07-16 07:42:43 -05:00
Mike Griese a511ab0bc7 Revert "I was thinking of making the HostClass a COM class by default, but this is horrible. Then, the client wouldn't be able to use it to get the winrt type. We want to use the winrt type in Lists in the client. So this won't work"
This reverts commit 501c47adb2.
2020-07-15 16:28:35 -05:00
Mike Griese 501c47adb2 I was thinking of making the HostClass a COM class by default, but this is horrible. Then, the client wouldn't be able to use it to get the winrt type. We want to use the winrt type in Lists in the client. So this won't work 2020-07-15 16:28:27 -05:00
Mike Griese 72121721f3 So this doesn't work because HostClass is fundamentally a WinRT type, not a CoClass. What if it _wasn't_ a runtimeclass? 2020-07-15 16:08:44 -05:00
Mike Griese 3e80b6a466 The server's lifetime is based on the lifetime of the first client it creates now. 2020-07-15 12:52:29 -05:00
Mike Griese a80e1d3f73 this works neatly for having a HostManager for all the hosts, but the server eats the newline as well as the client, so I'm removing that bit of it 2020-07-15 12:04:20 -05:00
Mike Griese f45df9a717 This ALSO works 2020-07-15 09:43:29 -05:00
Mike Griese b37f69826e This experiment has been a wild success 2020-07-15 09:34:55 -05:00
Mike Griese b2e76c1812 register a single instance of a class over the lifetime of the process?? 2020-07-14 17:01:48 -05:00
Mike Griese 2179e16e3d Mostly refactor these scratch projects to use our shared helpers 2020-07-14 16:53:17 -05:00
Mike Griese fafc0e1316 Merge remote-tracking branch 'origin/master' into dev/migrie/oop-scratch-2 2020-07-14 14:53:47 -05:00
Mike Griese ca6dff9f20 revert the XAML bits from the server 2020-07-14 14:18:48 -05:00
Mike Griese 186ff8f638 If you do this, the server will crash when it tries to instantiate the XAML button 2020-07-14 14:16:47 -05:00
Mike Griese 37810aac71 merge branch 'origin/master' 2020-07-14 10:29:54 -05:00
Mike Griese 33bc88b225 oh cool, I can make a ScratchClass 2020-07-10 15:38:04 -05:00
Mike Griese d56137876e curious, I can get the IClosable, but not the ScratchInterface? 2020-07-10 15:23:58 -05:00
Mike Griese f928d41917 this is all dead end 2020-07-10 12:02:29 -05:00
Mike Griese e4cc3104ab Merge remote-tracking branch 'origin/master' into dev/migrie/oop-scratch-2 2020-07-10 10:12:36 -05:00
Mike Griese 0c10b4b265 Well, this actually kinda works. Probably horribly insecure 2020-06-16 17:02:42 -05:00
76 changed files with 3952 additions and 480220 deletions

View file

@ -1,25 +0,0 @@
<details>
<summary>
:pencil2: Contributor please read this
</summary>
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...
If the listed items are:
* ... **misspelled**, then please *correct* them instead of using the command.
* ... *names*, please add them to `.github/actions/spell-check/dictionary/names.txt`.
* ... APIs, you can add them to a file in `.github/actions/spell-check/dictionary/`.
* ... just things you're using, please add them to an appropriate file in `.github/actions/spell-check/expect/`.
* ... tokens you only need in one place and shouldn't *generally be used*, you can add an item in an appropriate file in `.github/actions/spell-check/patterns/`.
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>
#### :warning: Reviewers
At present, the action that triggered this message will not show its :x: in this PR unless the branch is within this repository.
Thus, you **should** make sure that this comment has been addressed before encouraging the merge bot to merge this PR.

View file

@ -1,45 +0,0 @@
ACCEPTFILES
ACCESSDENIED
alignof
bitfield
bitfields
CLASSNOTAVAILABLE
EXPCMDFLAGS
EXPCMDSTATE
fullkbd
futex
href
IAsync
IBind
IBox
IClass
IComparable
ICustom
IDialog
IDirect
IExplorer
IMap
IObject
IStorage
llabs
LCID
LSHIFT
NCHITTEST
NCLBUTTONDBLCLK
NCRBUTTONDBLCLK
NOAGGREGATION
NOREDIRECTIONBITMAP
oaidl
ocidl
PAGESCROLL
RETURNCMD
rfind
roundf
RSHIFT
rx
SIZENS
spsc
STDCPP
syscall
tmp
tx

File diff suppressed because it is too large Load diff

View file

@ -1,3 +0,0 @@
powf
sqrtf
isnan

View file

@ -1,18 +0,0 @@
ACLs
altform
backplating
DACL
DACLs
LKG
mfcribbon
microsoft
microsoftonline
osgvsowi
powerrename
powershell
pscustomobject
SACLs
tdbuildteamid
vcruntime
visualstudio
wslpath

50
.github/actions/spelling/advice.md vendored Normal file
View file

@ -0,0 +1,50 @@
<!-- markdownlint-disable MD033 MD041 -->
<details>
<summary>
:pencil2: Contributor please read this
</summary>
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...
If the listed items are:
* ... **misspelled**, then please *correct* them instead of using the command.
* ... *names*, please add them to `.github/actions/spelling/allow/names.txt`.
* ... APIs, you can add them to a file in `.github/actions/spelling/allow/`.
* ... just things you're using, please add them to an appropriate file in `.github/actions/spelling/expect/`.
* ... tokens you only need in one place and shouldn't *generally be used*, you can add an item in an appropriate file in `.github/actions/spelling/patterns/`.
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>
See if there's a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it.
If not, try writing one and adding it to a `patterns/{file}.txt`.
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](
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](
../tree/HEAD/README.md) (on whichever branch you're using).
</details>
</details>
</details>

View file

@ -1,6 +1,6 @@
# Dictionaries are lists of words to accept unconditionally
# Allow files are lists of words to accept unconditionally
While check spelling will complain about a whitelisted word
While check spelling will complain about an expected word
which is no longer present, you can include things here even if
they are not otherwise present in the repository.
@ -8,13 +8,14 @@ E.g., you could include a list of system APIs here, or potential
contributors (so that if a future commit includes their name,
it'll be accepted).
### Files
## Files
| File | Description |
| ---- | ----------- |
| [Dictionary](dictionary.txt) | Primary US English dictionary |
| [Allow](allow.txt) | Supplements to the dictionary |
| [Chinese](chinese.txt) | Chinese words |
| [Japanese](japanese.txt) | Japanese words |
| [Microsoft](microsoft.txt) | Microsoft brand items |
| [Fonts](fonts.txt) | Font names |
| [Names](names.txt) | Names of people |
| [Colors](colors.txt) | Names of color |

View file

@ -0,0 +1,77 @@
apc
calt
ccmp
changelog
cybersecurity
Apc
clickable
clig
copyable
dalet
dcs
Dcs
dialytika
dje
downside
downsides
dze
dzhe
Enum'd
Fitt
formattings
ftp
fvar
geeksforgeeks
ghe
gje
hostname
hostnames
hyperlink
hyperlinking
hyperlinks
img
It'd
kje
liga
lje
locl
lorem
Llast
Lmid
Lorigin
maxed
mkmk
mru
noreply
nje
ogonek
ok'd
overlined
postmodern
ptys
qof
qps
rclt
reimplementation
reserialization
reserialize
reserializes
rlig
runtimes
shcha
slnt
Sos
timestamped
TLDR
tokenizes
tonos
tshe
uiatextrange
UIs
und
unregister
versioned
We'd
wildcards
yeru
zhe

194
.github/actions/spelling/allow/apis.txt vendored Normal file
View file

@ -0,0 +1,194 @@
ACCEPTFILES
ACCESSDENIED
alignas
alignof
APPLYTOSUBMENUS
bitfield
bitfields
BUILDBRANCH
BUILDMSG
BUILDNUMBER
BYPOSITION
charconv
CLASSNOTAVAILABLE
cmdletbinding
COLORPROPERTY
colspan
COMDLG
comparand
cstdint
CXICON
CYICON
dataobject
dcomp
DERR
dlldata
DONTADDTORECENT
DWORDLONG
enumset
environstrings
EXPCMDFLAGS
EXPCMDSTATE
filetime
FILTERSPEC
FORCEFILESYSTEM
FORCEMINIMIZE
frac
fullkbd
futex
GETDESKWALLPAPER
GETHIGHCONTRAST
Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
hotkeys
href
hrgn
IActivation
IApp
IAppearance
IAsync
IBind
IBox
IClass
IComparable
IComparer
IConnection
ICustom
IDialog
IDirect
IExplorer
IFACEMETHOD
IFile
IInheritable
IMap
IObject
iosfwd
IPackage
IPeasant
isspace
ISetup
IStorage
istream
IStringable
ITab
ITaskbar
IUri
IVirtual
KEYSELECT
LCID
llabs
llu
localtime
lround
LSHIFT
MENUCOMMAND
MENUDATA
MENUINFO
memicmp
mptt
mov
msappx
MULTIPLEUSE
NCHITTEST
NCLBUTTONDBLCLK
NCRBUTTONDBLCLK
NIF
NIN
NOAGGREGATION
NOASYNC
NOCHANGEDIR
NOPROGRESS
NOREDIRECTIONBITMAP
NOREPEAT
NOTIFYBYPOS
NOTIFYICON
NOTIFYICONDATA
ntprivapi
oaidl
ocidl
ODR
offsetof
osver
OSVERSIONINFOEXW
otms
OUTLINETEXTMETRICW
overridable
PAGESCROLL
PICKFOLDERS
pmr
rcx
REGCLS
RETURNCMD
rfind
roundf
RSHIFT
schandle
semver
serializer
SETVERSION
SHELLEXECUTEINFOW
shobjidl
SHOWMINIMIZED
SHOWTIP
SINGLEUSE
SIZENS
smoothstep
snprintf
spsc
sregex
SRWLOC
SRWLOCK
STDCPP
STDMETHOD
strchr
strcpy
streambuf
strtoul
Stubless
Subheader
Subpage
syscall
TASKBARCREATED
TBPF
THEMECHANGED
tlg
tmp
tolower
toupper
TTask
TVal
UChar
UPDATEINIFILE
userenv
wcsstr
wcstoui
winmain
wmemcmp
wpc
wsregex
wwinmain
xchg
XDocument
XElement
xfacet
xhash
XIcon
xiosbase
xlocale
xlocbuf
xlocinfo
xlocmes
xlocmon
xlocnum
xloctime
XMax
xmemory
XParse
xpath
xstddef
xstring
xtree
xutility
YIcon
YMax

View file

@ -0,0 +1,117 @@
alice
aliceblue
antiquewhite
blanchedalmond
blueviolet
burlywood
cadetblue
cornflowerblue
cornsilk
cyan
darkblue
darkcyan
darkgoldenrod
darkgray
darkgreen
darkgrey
darkkhaki
darkmagenta
darkolivegreen
darkorange
darkorchid
darkred
darksalmon
darkseagreen
darkslateblue
darkslategray
darkslategrey
darkturquoise
darkviolet
deeppink
deepskyblue
dimgray
dimgrey
dodgerblue
firebrick
floralwhite
forestgreen
gainsboro
ghostwhite
greenyellow
hotpink
indian
indianred
lavenderblush
lawngreen
lemonchiffon
lightblue
lightcoral
lightcyan
lightgoldenrod
lightgoldenrodyellow
lightgray
lightgreen
lightgrey
lightpink
lightsalmon
lightseagreen
lightskyblue
lightslateblue
lightslategray
lightslategrey
lightsteelblue
lightyellow
limegreen
mediumaquamarine
mediumblue
mediumorchid
mediumpurple
mediumseagreen
mediumslateblue
mediumspringgreen
mediumturquoise
mediumvioletred
midnightblue
mintcream
mistyrose
navajo
navajowhite
navyblue
oldlace
olivedrab
orangered
palegoldenrod
palegreen
paleturquoise
palevioletred
papayawhip
peachpuff
peru
powderblue
rebecca
rebeccapurple
rosybrown
royalblue
saddlebrown
sandybrown
seagreen
sienna
skyblue
slateblue
slategray
slategrey
springgreen
steelblue
violetred
webgray
webgreen
webgrey
webmaroon
webpurple
whitesmoke
xaroon
xray
xreen
xrey
xurple
yellowgreen

View file

@ -1,8 +1,10 @@
Consolas
emoji
emojis
Extralight
Gabriola
Iosevka
MDL
Monofur
Segoe
wght

11
.github/actions/spelling/allow/math.txt vendored Normal file
View file

@ -0,0 +1,11 @@
atan
CPrime
HBar
HPrime
isnan
LPrime
LStep
powf
RSub
sqrtf
ULP

View file

@ -0,0 +1,78 @@
ACLs
ADMINS
advapi
altform
altforms
appendwttlogging
appx
appxbundle
appxerror
appxmanifest
ATL
backplating
bitmaps
BOMs
CPLs
cpptools
cppvsdbg
CPRs
cryptbase
DACL
DACLs
diffs
disposables
dotnetfeed
DTDs
DWINRT
enablewttlogging
Intelli
IVisual
LKG
LOCKFILE
Lxss
mfcribbon
microsoft
microsoftonline
MSAA
msixbundle
MSVC
muxc
netcore
osgvsowi
PFILETIME
pgc
pgo
pgosweep
powerrename
powershell
propkey
pscustomobject
QWORD
regedit
robocopy
SACLs
sdkddkver
Shobjidl
Skype
SRW
sxs
Sysinternals
sysnative
systemroot
taskkill
tasklist
tdbuildteamid
unvirtualized
VCRT
vcruntime
Virtualization
visualstudio
vscode
VSTHRD
winsdkver
wlk
wslpath
wtl
wtt
wttlog
Xamarin

View file

@ -8,36 +8,52 @@ dhowett
Diviness
dsafa
duhowett
ekg
ethanschoonover
Firefox
Gatta
glsl
Gravell
Grie
Griese
Hernan
Howett
Illhardt
iquilezles
jantari
jerrysh
Kaiyu
kimwalisch
KMehrain
KODELIFE
Kodelife
Kourosh
kowalczyk
leonmsft
Lepilleur
lhecker
lukesampson
Manandhar
mbadolato
Mehrain
menger
mgravell
michaelniksa
michkap
migrie
mikegr
mikemaccana
miloush
miniksa
niksa
nvaccess
nvda
oising
oldnewthing
opengl
osgwiki
pabhojwa
panos
paulcam
pauldotknopf
PGP
@ -45,11 +61,14 @@ Pham
Rincewind
rprichard
Schoonover
shadertoy
Somuah
sonph
sonpham
stakx
thereses
Walisch
Wellons
Wirt
Wojciech
zadjii

View file

@ -1,3 +1,4 @@
(?:(?i)\.png$)
(?:^|/)dirs$
(?:^|/)go\.mod$
(?:^|/)go\.sum$
@ -35,7 +36,6 @@ SUMS$
\.pbxproj$
\.pdf$
\.pem$
\.png$
\.psd$
\.runsettings$
\.sig$
@ -45,6 +45,7 @@ SUMS$
\.tar$
\.tgz$
\.ttf$
\.vsdx$
\.woff
\.xcf$
\.xls
@ -53,11 +54,26 @@ SUMS$
\.zip$
^consolegit2gitfilters\.json$
^dep/
^oss/
^doc/reference/master-sequence-list.csv$
^doc/reference/UTF8-torture-test\.txt$
^oss/
^src/host/ft_uia/run\.bat$
^src/host/runft\.bat$
^src/host/runut\.bat$
^src/interactivity/onecore/BgfxEngine\.
^src/renderer/wddmcon/WddmConRenderer\.
^src/terminal/adapter/ut_adapter/run\.bat$
^src/terminal/parser/delfuzzpayload\.bat$
^src/terminal/parser/ft_fuzzer/run\.bat$
^src/terminal/parser/ft_fuzzer/VTCommandFuzzer\.cpp$
^src/terminal/parser/ft_fuzzwrapper/run\.bat$
^src/terminal/parser/ut_parser/run\.bat$
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
^src/tools/lnkd/lnkd\.bat$
^src/tools/pixels/pixels\.bat$
^src/tools/texttests/fira\.txt$
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
^\.github/actions/spell-check/
^src/types/ut_types/UtilsTests.cpp$
^\.github/actions/spelling/
^\.gitignore$
^\XamlStyler.json$

View file

@ -1,15 +1,32 @@
AAAa
AAAAA
AAAAAAAAAAAAA
AAAAAABBBBBBCCC
AAAAABBBBBBCCC
abcd
abcd
abcde
abcdef
ABCDEFG
ABCDEFGH
ABCDEFGHIJ
abcdefghijk
ABCDEFGHIJKLMNO
abcdefghijklmnop
ABCDEFGHIJKLMNOPQRST
abcdefghijklmnopqrstuvwxyz
ABCG
ABE
BBGGRR
abf
BBBBB
BBBBBBBB
BBBBBBBBBBBBBBDDDD
BBBBBCCC
BBBBCCCCC
BBGGRR
CCE
EFG
EFGh
QQQQQQQQQQABCDEFGHIJ
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQ
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
@ -28,3 +45,4 @@ ZYXWVUT
ZZBBZ
ZZZBB
ZZZBZ
ZZZZZ

View file

@ -1,6 +1,7 @@
http
td
www
easyrgb
php
ecma
rapidtables
WCAG
@ -10,6 +11,9 @@ robertelder
kovidgoyal
leonerd
fixterms
uk
winui
appshellintegration
mdtauk
cppreference
gfycat
Guake

View file

@ -4,7 +4,8 @@ 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-]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.]*
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
[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
@ -15,8 +16,12 @@ Scro\&ll
:\\windows\\syste\b
TestUtils::VerifyExpectedString\(tb, L"[^"]+"
(?:hostSm|mach)\.ProcessString\(L"[^"]+"
\b([A-Za-z])\1{3,}\b
\b([A-Za-z])\g{-1}{3,}\b
0x[0-9A-Za-z]+
Base64::s_(?:En|De)code\(L"[^"]+"
VERIFY_ARE_EQUAL\(L"[^"]+"
L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
std::memory_order_[\w]+
D2DERR_SHADER_COMPILE_FAILED
TIL_FEATURE_[0-9A-Z_]+
vcvars\w*

22
.github/actions/spelling/reject.txt vendored Normal file
View file

@ -0,0 +1,22 @@
^attache$
^attacher$
^attachers$
^spae$
^spaebook$
^spaecraft$
^spaed$
^spaedom$
^spaeing$
^spaeings$
^spae-man$
^spaeman$
^spaer$
^Spaerobee$
^spaes$
^spaewife$
^spaewoman$
^spaework$
^spaewright$
^wether$
^wethers$
^wetherteg$

View file

@ -1,20 +0,0 @@
name: Spell checking
on:
push:
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '15 * * * *'
jobs:
build:
name: Spell checking
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.0.0
with:
fetch-depth: 5
- uses: check-spelling/check-spelling@0.0.16-alpha
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
bucket: .github/actions
project: spell-check

20
.github/workflows/spelling2.yml vendored Normal file
View file

@ -0,0 +1,20 @@
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
name: Spell checking
on:
pull_request_target:
push:
jobs:
spelling:
name: Spell checking
runs-on: ubuntu-latest
steps:
- name: checkout-merge
if: "contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2
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

View file

@ -87,8 +87,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Feature", "src\h
ProjectSection(ProjectDependencies) = postProject
{18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
{FC802440-AD6A-4919-8F2C-7701F2B38D79} = {FC802440-AD6A-4919-8F2C-7701F2B38D79}
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
{58A03BB2-DF5A-4B66-91A0-7EF3BA01269A} = {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser.UnitTests", "src\terminal\parser\ut_parser\Parser.UnitTests.vcxproj", "{12144E07-FE63-4D33-9231-748B8D8C3792}"
@ -314,6 +314,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "s
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {84848BFA-931D-42CE-9ADF-01EE54DE7890}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScratchWinRTServer", "src\tools\ScratchWinRTServer\ScratchWinRTServer.vcxproj", "{D46D9547-F085-4645-B8F7-E8CD21559AB4}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
{CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
{48D21369-3D7B-4431-9967-24E81292CF62} = {48D21369-3D7B-4431-9967-24E81292CF62}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScratchIsland", "src\tools\ScratchIsland\ScratchIsland.vcxproj", "{23A1F736-CD19-4196-980F-84BCD50CF783}"
ProjectSection(ProjectDependencies) = postProject
{D46D9547-F085-4645-B8F7-E8CD21559AB4} = {D46D9547-F085-4645-B8F7-E8CD21559AB4}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wt", "src\cascadia\wt\wt.vcxproj", "{506FD703-BAA7-4F6E-9361-64F550EC8FCA}"
EndProject
Global
@ -1997,6 +2010,90 @@ Global
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|DotNet_x86Test.Build.0 = Release|x86
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|x64.ActiveCfg = Release|Any CPU
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|x86.ActiveCfg = Release|Any CPU
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|Any CPU.ActiveCfg = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|Any CPU.Build.0 = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|ARM64.ActiveCfg = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|ARM64.Build.0 = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x64Test.Build.0 = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x86Test.Build.0 = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x64.ActiveCfg = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x64.Build.0 = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x86.ActiveCfg = Release|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x86.Build.0 = Release|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|Any CPU.ActiveCfg = Debug|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|ARM64.ActiveCfg = Debug|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x64.ActiveCfg = Debug|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x64.Build.0 = Debug|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x86.ActiveCfg = Debug|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x86.Build.0 = Debug|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|Any CPU.ActiveCfg = Release|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|ARM64.ActiveCfg = Release|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x64.ActiveCfg = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x64.Build.0 = Release|x64
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x86.ActiveCfg = Release|Win32
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x86.Build.0 = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|Any CPU.ActiveCfg = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|Any CPU.Build.0 = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|ARM64.ActiveCfg = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|ARM64.Build.0 = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x64Test.Build.0 = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x86Test.Build.0 = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x64.ActiveCfg = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x64.Build.0 = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x86.ActiveCfg = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x86.Build.0 = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|Any CPU.ActiveCfg = Debug|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|ARM64.ActiveCfg = Debug|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x64.ActiveCfg = Debug|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x64.Build.0 = Debug|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x86.ActiveCfg = Debug|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x86.Build.0 = Debug|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|Any CPU.ActiveCfg = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|ARM64.ActiveCfg = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x64.ActiveCfg = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x64.Build.0 = Release|x64
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x86.ActiveCfg = Release|Win32
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x86.Build.0 = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|Any CPU.ActiveCfg = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|Any CPU.Build.0 = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|ARM64.ActiveCfg = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|ARM64.Build.0 = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x64Test.Build.0 = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x86Test.Build.0 = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x64.ActiveCfg = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x64.Build.0 = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x86.ActiveCfg = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x86.Build.0 = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|Any CPU.ActiveCfg = Debug|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|ARM64.ActiveCfg = Debug|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x64.ActiveCfg = Debug|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x64.Build.0 = Debug|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x86.ActiveCfg = Debug|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x86.Build.0 = Debug|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|Any CPU.ActiveCfg = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|ARM64.ActiveCfg = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x64.ActiveCfg = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x64.Build.0 = Release|x64
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x86.ActiveCfg = Release|Win32
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x86.Build.0 = Release|Win32
{506FD703-BAA7-4F6E-9361-64F550EC8FCA}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{506FD703-BAA7-4F6E-9361-64F550EC8FCA}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{506FD703-BAA7-4F6E-9361-64F550EC8FCA}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
@ -2104,6 +2201,9 @@ Global
{067F0A06-FCB7-472C-96E9-B03B54E8E18D} = {59840756-302F-44DF-AA47-441A9D673202}
{6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {81C352DB-1818-45B7-A284-18E259F1CC87}
{1588FD7C-241E-4E7D-9113-43735F3E6BAD} = {59840756-302F-44DF-AA47-441A9D673202}
{D46D9547-F085-4645-B8F7-E8CD21559AB4} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{06382349-D62A-4C7D-A7D3-9CA817EAE092} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{23A1F736-CD19-4196-980F-84BCD50CF783} = {A10C4720-DCA4-4640-9749-67F4314F527C}
{506FD703-BAA7-4F6E-9361-64F550EC8FCA} = {59840756-302F-44DF-AA47-441A9D673202}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution

View file

@ -555,21 +555,21 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// This event is only registered during terminal initialization,
// so we don't need to check _initializedTerminal.
// We also don't lock for things that come back from the renderer.
auto chain = _renderEngine->GetSwapChain();
auto chainHandle = _renderEngine->GetSwapChainHandle();
auto weakThis{ get_weak() };
co_await winrt::resume_foreground(Dispatcher());
if (auto control{ weakThis.get() })
{
_AttachDxgiSwapChainToXaml(chain.Get());
_AttachDxgiSwapChainToXaml(chainHandle);
}
}
void TermControl::_AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain)
void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle)
{
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative>();
nativePanel->SetSwapChain(swapChain);
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative2>();
nativePanel->SetSwapChainHandle(swapChainHandle);
}
bool TermControl::_InitializeTerminal()
@ -673,7 +673,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
THROW_IF_FAILED(dxEngine->Enable());
_renderEngine = std::move(dxEngine);
_AttachDxgiSwapChainToXaml(_renderEngine->GetSwapChain().Get());
_AttachDxgiSwapChainToXaml(_renderEngine->GetSwapChainHandle());
// Tell the DX Engine to notify us when the swap chain changes.
// We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems)

View file

@ -81,7 +81,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
void ToggleRetroEffect();
winrt::fire_and_forget RenderEngineSwapChainChanged();
void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain);
void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle);
winrt::fire_and_forget _RendererEnteredErrorState();
void _RenderRetryButton_Click(IInspectable const& button, IInspectable const& args);

View file

@ -107,62 +107,68 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
// Make sure to call this so we get WM_POINTER messages.
EnableMouseInPointer(true);
// !!! LOAD BEARING !!!
// We must initialize the main thread as a single-threaded apartment before
// constructing any Xaml objects. Failing to do so will cause some issues
// in accessibility somewhere down the line when a UIAutomation object will
// be queried on the wrong thread at the wrong time.
// We used to initialize as STA only _after_ initializing the application
// host, which loaded the settings. The settings needed to be loaded in MTA
// because we were using the Windows.Storage APIs. Since we're no longer
// doing that, we can safely init as STA before any WinRT dispatches.
winrt::init_apartment(winrt::apartment_type::single_threaded);
auto mainLoop = []() {
// !!! LOAD BEARING !!!
// We must initialize the main thread as a single-threaded apartment before
// constructing any Xaml objects. Failing to do so will cause some issues
// in accessibility somewhere down the line when a UIAutomation object will
// be queried on the wrong thread at the wrong time.
// We used to initialize as STA only _after_ initializing the application
// host, which loaded the settings. The settings needed to be loaded in MTA
// because we were using the Windows.Storage APIs. Since we're no longer
// doing that, we can safely init as STA before any WinRT dispatches.
winrt::init_apartment(winrt::apartment_type::single_threaded);
// Create the AppHost object, which will create both the window and the
// Terminal App. This MUST BE constructed before the Xaml manager as TermApp
// provides an implementation of Windows.UI.Xaml.Application.
AppHost host;
// Create the AppHost object, which will create both the window and the
// Terminal App. This MUST BE constructed before the Xaml manager as TermApp
// provides an implementation of Windows.UI.Xaml.Application.
AppHost host;
// Initialize the xaml content. This must be called AFTER the
// WindowsXamlManager is initialized.
host.Initialize();
// Initialize the xaml content. This must be called AFTER the
// WindowsXamlManager is initialized.
host.Initialize();
MSG message;
MSG message;
while (GetMessage(&message, nullptr, 0, 0))
{
// GH#638 (Pressing F7 brings up both the history AND a caret browsing message)
// The Xaml input stack doesn't allow an application to suppress the "caret browsing"
// dialog experience triggered when you press F7. Official recommendation from the Xaml
// team is to catch F7 before we hand it off.
// AppLogic contains an ad-hoc implementation of event bubbling for a runtime classes
// implementing a custom IF7Listener interface.
// If the recipient of IF7Listener::OnF7Pressed suggests that the F7 press has, in fact,
// been handled we can discard the message before we even translate it.
if (_messageIsF7Keypress(message))
while (GetMessage(&message, nullptr, 0, 0))
{
if (host.OnDirectKeyEvent(VK_F7, true))
// GH#638 (Pressing F7 brings up both the history AND a caret browsing message)
// The Xaml input stack doesn't allow an application to suppress the "caret browsing"
// dialog experience triggered when you press F7. Official recommendation from the Xaml
// team is to catch F7 before we hand it off.
// AppLogic contains an ad-hoc implementation of event bubbling for a runtime classes
// implementing a custom IF7Listener interface.
// If the recipient of IF7Listener::OnF7Pressed suggests that the F7 press has, in fact,
// been handled we can discard the message before we even translate it.
if (_messageIsF7Keypress(message))
{
// The application consumed the F7. Don't let Xaml get it.
continue;
if (host.OnDirectKeyEvent(VK_F7, true))
{
// The application consumed the F7. Don't let Xaml get it.
continue;
}
}
}
// GH#6421 - System XAML will never send an Alt KeyUp event. So, similar
// to how we'll steal the F7 KeyDown above, we'll steal the Alt KeyUp
// here, and plumb it through.
if (_messageIsAltKeyup(message))
{
// Let's pass <Alt> to the application
if (host.OnDirectKeyEvent(VK_MENU, false))
// GH#6421 - System XAML will never send an Alt KeyUp event. So, similar
// to how we'll steal the F7 KeyDown above, we'll steal the Alt KeyUp
// here, and plumb it through.
if (_messageIsAltKeyup(message))
{
// The application consumed the Alt. Don't let Xaml get it.
continue;
// Let's pass <Alt> to the application
if (host.OnDirectKeyEvent(VK_MENU, false))
{
// The application consumed the Alt. Don't let Xaml get it.
continue;
}
}
}
TranslateMessage(&message);
DispatchMessage(&message);
}
TranslateMessage(&message);
DispatchMessage(&message);
}
};
std::thread t{ mainLoop };
mainLoop();
return 0;
}

View file

@ -13,7 +13,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>onecoreuap_apiset.lib;d3dcompiler.lib;dwmapi.lib;uxtheme.lib;shlwapi.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>onecoreuap_apiset.lib;d3dcompiler.lib;dwmapi.lib;uxtheme.lib;shlwapi.lib;ntdll.lib;dcomp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>

View file

@ -84,6 +84,7 @@ DxEngine::DxEngine() :
_glyphCell{},
_boxDrawingEffect{},
_haveDeviceResources{ false },
_swapChainHandle{ INVALID_HANDLE_VALUE },
_swapChainDesc{ 0 },
_swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE },
_recreateDeviceRequested{ false },
@ -488,6 +489,13 @@ try
}
case SwapChainMode::ForComposition:
{
if (!_swapChainHandle)
{
RETURN_IF_FAILED(DCompositionCreateSurfaceHandle(GENERIC_ALL, nullptr, &_swapChainHandle));
}
RETURN_IF_FAILED(_dxgiFactory2.As(&_dxgiFactoryMedia));
// Use the given target size for compositions.
_swapChainDesc.Width = _displaySizePixels.width<UINT>();
_swapChainDesc.Height = _displaySizePixels.height<UINT>();
@ -497,10 +505,11 @@ try
// It's 100% required to use scaling mode stretch for composition. There is no other choice.
_swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(),
&_swapChainDesc,
nullptr,
&_dxgiSwapChain));
RETURN_IF_FAILED(_dxgiFactoryMedia->CreateSwapChainForCompositionSurfaceHandle(_d3dDevice.Get(),
_swapChainHandle.get(),
&_swapChainDesc,
nullptr,
&_dxgiSwapChain));
break;
}
default:
@ -826,14 +835,14 @@ try
}
CATCH_LOG()
Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain()
HANDLE DxEngine::GetSwapChainHandle()
{
if (_dxgiSwapChain.Get() == nullptr)
if (!_swapChainHandle)
{
THROW_IF_FAILED(_CreateDeviceResources(true));
}
return _dxgiSwapChain;
return _swapChainHandle.get();
}
void DxEngine::_InvalidateRectangle(const til::rectangle& rc)

View file

@ -63,7 +63,7 @@ namespace Microsoft::Console::Render
void SetSoftwareRendering(bool enable) noexcept;
::Microsoft::WRL::ComPtr<IDXGISwapChain1> GetSwapChain();
HANDLE GetSwapChainHandle();
// IRenderEngine Members
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
@ -118,6 +118,8 @@ namespace Microsoft::Console::Render
void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept;
void SetDefaultTextBackgroundOpacity(const float opacity) noexcept;
wil::unique_handle _swapChainHandle;
protected:
[[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring& newTitle) noexcept override;
[[nodiscard]] HRESULT _PaintTerminalEffects() noexcept;
@ -191,6 +193,7 @@ namespace Microsoft::Console::Render
::Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> _d2dBrushBackground;
::Microsoft::WRL::ComPtr<IDXGIFactory2> _dxgiFactory2;
::Microsoft::WRL::ComPtr<IDXGIFactoryMedia> _dxgiFactoryMedia;
::Microsoft::WRL::ComPtr<IDXGIDevice> _dxgiDevice;
::Microsoft::WRL::ComPtr<IDXGISurface> _dxgiSurface;

View file

@ -21,6 +21,8 @@
#include <typeinfo>
#include <stdexcept>
#include <dcomp.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <dxgi1_3.h>

View file

@ -0,0 +1,281 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "AppHost.h"
#include "../types/inc/Viewport.hpp"
#include "../types/inc/utils.hpp"
#include "../types/inc/User32Utils.hpp"
#include "resource.h"
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Hosting;
using namespace winrt::Windows::Foundation::Numerics;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Console::Types;
AppHost::AppHost() noexcept :
_window{ nullptr }
{
_window = std::make_unique<IslandWindow>();
// Tell the window to callback to us when it's about to handle a WM_CREATE
auto pfn = std::bind(&AppHost::_HandleCreateWindow,
this,
std::placeholders::_1,
std::placeholders::_2);
_window->SetCreateCallback(pfn);
_window->MakeWindow();
}
AppHost::~AppHost()
{
// destruction order is important for proper teardown here
_window = nullptr;
}
// Method Description:
// - Initializes the XAML island, creates the terminal app, and sets the
// island's content to that of the terminal app's content. Also registers some
// callbacks with TermApp.
// !!! IMPORTANT!!!
// This must be called *AFTER* WindowsXamlManager::InitializeForCurrentThread.
// If it isn't, then we won't be able to create the XAML island.
// Arguments:
// - <none>
// Return Value:
// - <none>
void AppHost::Initialize()
{
_window->Initialize();
////////////////////////////////////////////////////////////////////////////
// Initialize the UI
////////////////////////////////////////////////////////////////////////////
_rootGrid = Grid();
_swapchainsGrid = Grid();
_swp0 = SwapChainPanel();
_swp1 = SwapChainPanel();
_swp2 = SwapChainPanel();
_swp3 = SwapChainPanel();
// Set up the content of the application. If the app has a custom titlebar,
// set that content as well.
{
auto firstRowDef = Controls::RowDefinition();
firstRowDef.Height(GridLengthHelper::FromValueAndType(1, GridUnitType::Star));
auto secondRowDef = Controls::RowDefinition();
secondRowDef.Height(GridLengthHelper::FromValueAndType(9, GridUnitType::Star));
_rootGrid.RowDefinitions().Append(firstRowDef);
_rootGrid.RowDefinitions().Append(secondRowDef);
}
{
auto firstRowDef = Controls::RowDefinition();
firstRowDef.Height(GridLengthHelper::FromValueAndType(1, GridUnitType::Star));
auto secondRowDef = Controls::RowDefinition();
secondRowDef.Height(GridLengthHelper::FromValueAndType(1, GridUnitType::Star));
_swapchainsGrid.RowDefinitions().Append(firstRowDef);
_swapchainsGrid.RowDefinitions().Append(secondRowDef);
auto firstColDef = Controls::ColumnDefinition();
firstColDef.Width(GridLengthHelper::FromValueAndType(1, GridUnitType::Star));
auto secondColDef = Controls::ColumnDefinition();
secondColDef.Width(GridLengthHelper::FromValueAndType(1, GridUnitType::Star));
_swapchainsGrid.ColumnDefinitions().Append(firstColDef);
_swapchainsGrid.ColumnDefinitions().Append(secondColDef);
}
_rootGrid.Children().Append(_swapchainsGrid);
Controls::Grid::SetRow(_swapchainsGrid, 1);
{
Media::SolidColorBrush solidColor{};
til::color newBgColor{ 0xFFFF0000 };
solidColor.Color(newBgColor);
_rootGrid.Background(solidColor);
}
{
Media::SolidColorBrush solidColor{};
til::color newBgColor{ 0xFF00FF00 };
solidColor.Color(newBgColor);
_swapchainsGrid.Background(solidColor);
}
winrt::Windows::UI::Xaml::Thickness newMargin = ThicknessHelper::FromUniformLength(4);
_swp0.Margin(newMargin);
_swp1.Margin(newMargin);
_swp2.Margin(newMargin);
_swp3.Margin(newMargin);
_rootGrid.Children().Append(_swp0);
_rootGrid.Children().Append(_swp1);
_rootGrid.Children().Append(_swp2);
_rootGrid.Children().Append(_swp3);
Controls::Grid::SetRow(_swp0, 0);
Controls::Grid::SetColumn(_swp0, 0);
Controls::Grid::SetRow(_swp1, 0);
Controls::Grid::SetColumn(_swp1, 1);
Controls::Grid::SetRow(_swp2, 1);
Controls::Grid::SetColumn(_swp2, 0);
Controls::Grid::SetRow(_swp3, 1);
Controls::Grid::SetColumn(_swp3, 1);
_window->SetContent(_rootGrid);
////////////////////////////////////////////////////////////////////////////
_createHost();
_window->OnAppInitialized();
}
winrt::fire_and_forget AppHost::_createHost()
{
co_await winrt::resume_background();
auto host0 = _manager.CreateHost();
co_await winrt::resume_foreground(_swp0.Dispatcher());
host0.CreateSwapChain(_swp0);
_swp0_layoutUpdatedRevoker = _swp0.LayoutUpdated(winrt::auto_revoke, [this, host0](auto /*s*/, auto /*e*/) {
// This event fires every time the layout changes, but it is always the last one to fire
// in any layout change chain. That gives us great flexibility in finding the right point
// at which to initialize our renderer (and our terminal).
// Any earlier than the last layout update and we may not know the terminal's starting size.
host0.Host().BeginRendering();
// if (_InitializeTerminal())
// {
// Only let this succeed once.
_swp0_layoutUpdatedRevoker.revoke();
// }
});
}
// Method Description:
// - Resize the window we're about to create to the appropriate dimensions, as
// specified in the settings. This will be called during the handling of
// WM_CREATE. We'll load the settings for the app, then get the proposed size
// of the terminal from the app. Using that proposed size, we'll resize the
// window we're creating, so that it'll match the values in the settings.
// Arguments:
// - hwnd: The HWND of the window we're about to create.
// - proposedRect: The location and size of the window that we're about to
// create. We'll use this rect to determine which monitor the window is about
// to appear on.
// - launchMode: A LaunchMode enum reference that indicates the launch mode
// Return Value:
// - None
void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect)
{
// Acquire the actual initial position
winrt::Windows::Foundation::Point initialPosition{ (float)proposedRect.left, (float)proposedRect.top };
proposedRect.left = gsl::narrow_cast<long>(initialPosition.X);
proposedRect.top = gsl::narrow_cast<long>(initialPosition.Y);
long adjustedHeight = 0;
long adjustedWidth = 0;
// Find nearest monitor.
HMONITOR hmon = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST);
// Get nearest monitor information
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(hmon, &monitorInfo);
// This API guarantees that dpix and dpiy will be equal, but neither is an
// optional parameter so give two UINTs.
UINT dpix = USER_DEFAULT_SCREEN_DPI;
UINT dpiy = USER_DEFAULT_SCREEN_DPI;
// If this fails, we'll use the default of 96.
GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy);
// We need to check if the top left point of the titlebar of the window is within any screen
RECT offScreenTestRect;
offScreenTestRect.left = proposedRect.left;
offScreenTestRect.top = proposedRect.top;
offScreenTestRect.right = offScreenTestRect.left + 1;
offScreenTestRect.bottom = offScreenTestRect.top + 1;
bool isTitlebarIntersectWithMonitors = false;
EnumDisplayMonitors(
nullptr, &offScreenTestRect, [](HMONITOR, HDC, LPRECT, LPARAM lParam) -> BOOL {
auto intersectWithMonitor = reinterpret_cast<bool*>(lParam);
*intersectWithMonitor = true;
// Continue the enumeration
return FALSE;
},
reinterpret_cast<LPARAM>(&isTitlebarIntersectWithMonitors));
if (!isTitlebarIntersectWithMonitors)
{
// If the title bar is out-of-screen, we set the initial position to
// the top left corner of the nearest monitor
proposedRect.left = monitorInfo.rcWork.left;
proposedRect.top = monitorInfo.rcWork.top;
}
winrt::Windows::Foundation::Size initialSize{ 800, 600 };
const short islandWidth = Utils::ClampToShortMax(
static_cast<long>(ceil(initialSize.Width)), 1);
const short islandHeight = Utils::ClampToShortMax(
static_cast<long>(ceil(initialSize.Height)), 1);
// Get the size of a window we'd need to host that client rect. This will
// add the titlebar space.
const auto nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix);
adjustedWidth = islandWidth + nonClientSize.cx;
adjustedHeight = islandHeight + nonClientSize.cy;
const COORD origin{ gsl::narrow<short>(proposedRect.left),
gsl::narrow<short>(proposedRect.top) };
const COORD dimensions{ Utils::ClampToShortMax(adjustedWidth, 1),
Utils::ClampToShortMax(adjustedHeight, 1) };
const auto newPos = Viewport::FromDimensions(origin, dimensions);
bool succeeded = SetWindowPos(hwnd,
nullptr,
newPos.Left(),
newPos.Top(),
newPos.Width(),
newPos.Height(),
SWP_NOACTIVATE | SWP_NOZORDER);
// Refresh the dpi of HWND because the dpi where the window will launch may be different
// at this time
_window->RefreshCurrentDPI();
// If we can't resize the window, that's really okay. We can just go on with
// the originally proposed window size.
LOG_LAST_ERROR_IF(!succeeded);
}
// Method Description:
// - Called when the app wants to change its theme. We'll forward this to the
// IslandWindow, so it can update the root UI element of the entire XAML tree.
// Arguments:
// - sender: unused
// - arg: the ElementTheme to use as the new theme for the UI
// Return Value:
// - <none>
void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::ElementTheme& arg)
{
_window->OnApplicationThemeChanged(arg);
}

View file

@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "IslandWindow.h"
#include "HostManager.h"
class AppHost
{
public:
AppHost() noexcept;
virtual ~AppHost();
void Initialize();
private:
bool _useNonClientArea{ false };
std::unique_ptr<IslandWindow> _window;
winrt::ScratchIsland::HostManager _manager;
void _HandleCreateWindow(const HWND hwnd, RECT proposedRect);
void _UpdateTheme(const winrt::Windows::Foundation::IInspectable&,
const winrt::Windows::UI::Xaml::ElementTheme& arg);
winrt::fire_and_forget _createHost();
winrt::Windows::UI::Xaml::Controls::Grid _rootGrid{ nullptr };
winrt::Windows::UI::Xaml::Controls::Grid _swapchainsGrid{ nullptr };
winrt::Windows::UI::Xaml::Controls::SwapChainPanel _swp0{ nullptr };
winrt::Windows::UI::Xaml::Controls::SwapChainPanel _swp1{ nullptr };
winrt::Windows::UI::Xaml::Controls::SwapChainPanel _swp2{ nullptr };
winrt::Windows::UI::Xaml::Controls::SwapChainPanel _swp3{ nullptr };
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _swp0_layoutUpdatedRevoker;
};

View file

@ -0,0 +1,228 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
// Custom window messages
#define CM_UPDATE_TITLE (WM_USER)
#include <wil/resource.h>
template<typename T>
class BaseWindow
{
public:
virtual ~BaseWindow() = 0;
static T* GetThisFromHandle(HWND const window) noexcept
{
return reinterpret_cast<T*>(GetWindowLongPtr(window, GWLP_USERDATA));
}
[[nodiscard]] static LRESULT __stdcall WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
{
WINRT_ASSERT(window);
if (WM_NCCREATE == message)
{
auto cs = reinterpret_cast<CREATESTRUCT*>(lparam);
T* that = static_cast<T*>(cs->lpCreateParams);
WINRT_ASSERT(that);
WINRT_ASSERT(!that->_window);
that->_window = wil::unique_hwnd(window);
return that->_OnNcCreate(wparam, lparam);
}
else if (T* that = GetThisFromHandle(window))
{
return that->MessageHandler(message, wparam, lparam);
}
return DefWindowProc(window, message, wparam, lparam);
}
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
{
switch (message)
{
case WM_DPICHANGED:
{
return HandleDpiChange(_window.get(), wparam, lparam);
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_SIZE:
{
UINT width = LOWORD(lparam);
UINT height = HIWORD(lparam);
switch (wparam)
{
case SIZE_MAXIMIZED:
[[fallthrough]];
case SIZE_RESTORED:
if (_minimized)
{
_minimized = false;
OnRestore();
}
// We always need to fire the resize event, even when we're transitioning from minimized.
// We might be transitioning directly from minimized to maximized, and we'll need
// to trigger any size-related content changes.
OnResize(width, height);
break;
case SIZE_MINIMIZED:
if (!_minimized)
{
_minimized = true;
OnMinimize();
}
break;
default:
// do nothing.
break;
}
break;
}
case CM_UPDATE_TITLE:
{
SetWindowTextW(_window.get(), _title.c_str());
break;
}
}
return DefWindowProc(_window.get(), message, wparam, lparam);
}
// DPI Change handler. on WM_DPICHANGE resize the window
[[nodiscard]] LRESULT HandleDpiChange(const HWND hWnd, const WPARAM wParam, const LPARAM lParam)
{
_inDpiChange = true;
const HWND hWndStatic = GetWindow(hWnd, GW_CHILD);
if (hWndStatic != nullptr)
{
const UINT uDpi = HIWORD(wParam);
// Resize the window
auto lprcNewScale = reinterpret_cast<RECT*>(lParam);
SetWindowPos(hWnd, nullptr, lprcNewScale->left, lprcNewScale->top, lprcNewScale->right - lprcNewScale->left, lprcNewScale->bottom - lprcNewScale->top, SWP_NOZORDER | SWP_NOACTIVATE);
_currentDpi = uDpi;
}
_inDpiChange = false;
return 0;
}
virtual void OnResize(const UINT width, const UINT height) = 0;
virtual void OnMinimize() = 0;
virtual void OnRestore() = 0;
RECT GetWindowRect() const noexcept
{
RECT rc = { 0 };
::GetWindowRect(_window.get(), &rc);
return rc;
}
HWND GetHandle() const noexcept
{
return _window.get();
}
float GetCurrentDpiScale() const noexcept
{
const auto dpi = ::GetDpiForWindow(_window.get());
const auto scale = static_cast<float>(dpi) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
return scale;
}
//// Gets the physical size of the client area of the HWND in _window
SIZE GetPhysicalSize() const noexcept
{
RECT rect = {};
GetClientRect(_window.get(), &rect);
const auto windowsWidth = rect.right - rect.left;
const auto windowsHeight = rect.bottom - rect.top;
return SIZE{ windowsWidth, windowsHeight };
}
//// Gets the logical (in DIPs) size of a physical size specified by the parameter physicalSize
//// Remarks:
//// XAML coordinate system is always in Display Independent Pixels (a.k.a DIPs or Logical). However Win32 GDI (because of legacy reasons)
//// in DPI mode "Per-Monitor and Per-Monitor (V2) DPI Awareness" is always in physical pixels.
//// The formula to transform is:
//// logical = (physical / dpi) + 0.5 // 0.5 is to ensure that we pixel snap correctly at the edges, this is necessary with odd DPIs like 1.25, 1.5, 1, .75
//// See also:
//// https://docs.microsoft.com/en-us/windows/desktop/LearnWin32/dpi-and-device-independent-pixels
//// https://docs.microsoft.com/en-us/windows/desktop/hidpi/high-dpi-desktop-application-development-on-windows#per-monitor-and-per-monitor-v2-dpi-awareness
winrt::Windows::Foundation::Size GetLogicalSize(const SIZE physicalSize) const noexcept
{
const auto scale = GetCurrentDpiScale();
// 0.5 is to ensure that we pixel snap correctly at the edges, this is necessary with odd DPIs like 1.25, 1.5, 1, .75
const auto logicalWidth = (physicalSize.cx / scale) + 0.5f;
const auto logicalHeight = (physicalSize.cy / scale) + 0.5f;
return winrt::Windows::Foundation::Size(logicalWidth, logicalHeight);
}
winrt::Windows::Foundation::Size GetLogicalSize() const noexcept
{
return GetLogicalSize(GetPhysicalSize());
}
// Method Description:
// - Sends a message to our message loop to update the title of the window.
// Arguments:
// - newTitle: a string to use as the new title of the window.
// Return Value:
// - <none>
void UpdateTitle(std::wstring_view newTitle)
{
_title = newTitle;
PostMessageW(_window.get(), CM_UPDATE_TITLE, 0, reinterpret_cast<LPARAM>(nullptr));
}
// Method Description:
// Reset the current dpi of the window. This method is only called after we change the
// initial launch position. This makes sure the dpi is consistent with the monitor on which
// the window will launch
void RefreshCurrentDPI()
{
_currentDpi = GetDpiForWindow(_window.get());
}
protected:
using base_type = BaseWindow<T>;
wil::unique_hwnd _window;
unsigned int _currentDpi = 0;
bool _inDpiChange = false;
std::wstring _title = L"";
bool _minimized = false;
// Method Description:
// - This method is called when the window receives the WM_NCCREATE message.
// Return Value:
// - The value returned from the window proc.
virtual [[nodiscard]] LRESULT _OnNcCreate(WPARAM wParam, LPARAM lParam) noexcept
{
SetWindowLongPtr(_window.get(), GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
EnableNonClientDpiScaling(_window.get());
_currentDpi = GetDpiForWindow(_window.get());
return DefWindowProc(_window.get(), WM_NCCREATE, wParam, lParam);
};
};
template<typename T>
inline BaseWindow<T>::~BaseWindow()
{
}

View file

@ -0,0 +1,50 @@
#include "pch.h"
#include "HostAndProcess.h"
#include "HostAndProcess.g.cpp"
#include "../../types/inc/utils.hpp"
using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace ::Microsoft::Console;
namespace winrt::ScratchIsland::implementation
{
HostAndProcess::HostAndProcess(ScratchWinRTServer::HostClass host,
wil::unique_process_information pi /*, wil::unique_handle hSwapchain*/) :
_host{ host },
_pi{ std::move(pi) } /*,
_hOurSwapchain {std::move(hSwapchain)}*/
{
}
ScratchWinRTServer::HostClass HostAndProcess::Host() const
{
return _host;
}
void HostAndProcess::CreateSwapChain(winrt::Windows::UI::Xaml::Controls::SwapChainPanel panel)
{
// wil::unique_handle _swapChainHandle;
DCompositionCreateSurfaceHandle(GENERIC_ALL, nullptr, &_hOurSwapchain);
// wil::unique_handle otherProcess = OpenProcess(contentProcessPid);
// HANDLE otherGuysHandleId = INVALID_HANDLE_VALUE;
BOOL ret = DuplicateHandle(GetCurrentProcess(),
_hOurSwapchain.get(),
_pi.hProcess,
&_hTheirSwapchain,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
// {
auto panelNative = panel.as<ISwapChainPanelNative2>();
winrt::check_hresult(panelNative->SetSwapChainHandle(_hOurSwapchain.get()));
// }
_host.ThisIsInsane((uint64_t)_hTheirSwapchain.get());
ret;
}
}

View file

@ -0,0 +1,29 @@
#pragma once
#include <winrt/ScratchWinRTServer.h>
#include "HostAndProcess.g.h"
namespace winrt::ScratchIsland::implementation
{
struct HostAndProcess : public HostAndProcessT<HostAndProcess>
{
HostAndProcess(ScratchWinRTServer::HostClass host, wil::unique_process_information pi);
ScratchWinRTServer::HostClass Host() const;
void CreateSwapChain(Windows::UI::Xaml::Controls::SwapChainPanel panel);
private:
ScratchWinRTServer::HostClass _host{ nullptr };
wil::unique_process_information _pi;
wil::unique_handle _hOurSwapchain{ INVALID_HANDLE_VALUE };
wil::unique_handle _hTheirSwapchain{ INVALID_HANDLE_VALUE };
};
}
namespace winrt::ScratchIsland::factory_implementation
{
// struct HostAndProcess : HostAndProcessT<HostAndProcess, implementation::HostAndProcess>
// {
// };
}

View file

@ -0,0 +1,9 @@
namespace ScratchIsland
{
[default_interface] runtimeclass HostAndProcess {
ScratchWinRTServer.HostClass Host { get; };
void CreateSwapChain(Windows.UI.Xaml.Controls.SwapChainPanel panel);
};
}

View file

@ -0,0 +1,81 @@
#include "pch.h"
#include "HostManager.h"
#include "HostManager.g.cpp"
#include "../../types/inc/utils.hpp"
using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace ::Microsoft::Console;
namespace winrt::ScratchIsland::implementation
{
HostManager::HostManager()
{
_hosts = winrt::single_threaded_observable_vector<winrt::ScratchIsland::HostAndProcess>();
}
Collections::IObservableVector<winrt::ScratchIsland::HostAndProcess> HostManager::Hosts()
{
return _hosts;
}
static wil::unique_process_information _createHostClassProcess(const winrt::guid& g)
{
auto guidStr{ Utils::GuidToString(g) };
std::wstring commandline{ fmt::format(L"ScratchWinRTServer.exe {}", guidStr) };
STARTUPINFO siOne{ 0 };
siOne.cb = sizeof(STARTUPINFOW);
wil::unique_process_information piOne;
auto succeeded = CreateProcessW(
nullptr,
commandline.data(),
nullptr, // lpProcessAttributes
nullptr, // lpThreadAttributes
false, // bInheritHandles
CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
nullptr, // lpEnvironment
nullptr, // startingDirectory
&siOne, // lpStartupInfo
&piOne // lpProcessInformation
);
THROW_IF_WIN32_BOOL_FALSE(succeeded);
// if (!succeeded)
// {
// printf("Failed to create host process\n");
// return;
// }
// Ooof this is dumb, but we need a sleep here to make the server starts.
// That's _sub par_. Maybe we could use the host's stdout to have them emit
// a byte when they're set up?
Sleep(2500);
// TODO MONDAY - It seems like it takes conhost too long to start up to
// host the ScratchWinRTServer that even a sleep 100 is too short. However,
// any longer, and XAML will just crash, because some frame took too long.
// So we _need_ to do the "have the server explicitly tell us it's ready"
// thing, and maybe also do it on a bg thread (and signal to the UI thread
// that it can attach now)
return std::move(piOne);
}
winrt::ScratchIsland::HostAndProcess HostManager::CreateHost()
{
// 1. Generate a GUID.
winrt::guid g{ Utils::CreateGuid() };
// 2. Spawn a Server.exe, with the guid on the commandline
auto piContent{ std::move(_createHostClassProcess(g)) };
auto host = create_instance<winrt::ScratchWinRTServer::HostClass>(g, CLSCTX_LOCAL_SERVER);
THROW_IF_NULL_ALLOC(host);
auto hostAndProcess = winrt::make_self<HostAndProcess>(host, std::move(piContent));
_hosts.Append(*hostAndProcess);
return *hostAndProcess;
}
}

View file

@ -0,0 +1,66 @@
#pragma once
#include "HostManager.g.h"
#include "HostAndProcess.h"
// 50dba6cd-4ddb-4b12-8363-5e06f5d0082c
static constexpr GUID HostManager_clsid{
0x50dba6cd,
0x4ddb,
0x4b12,
{ 0x83, 0x63, 0x5e, 0x06, 0xf5, 0xd0, 0x08, 0x2c }
};
namespace winrt::ScratchIsland::implementation
{
struct HostManager : public HostManagerT<HostManager>
{
HostManager();
Windows::Foundation::Collections::IObservableVector<winrt::ScratchIsland::HostAndProcess> Hosts();
winrt::ScratchIsland::HostAndProcess CreateHost();
private:
Windows::Foundation::Collections::IObservableVector<winrt::ScratchIsland::HostAndProcess> _hosts{ nullptr };
};
}
namespace winrt::ScratchIsland::factory_implementation
{
struct HostManager : HostManagerT<HostManager, implementation::HostManager>
{
};
}
// I bet all this could be a macro.
// I MORE be that this is all done by the factory_implementation stuff, isn't it...
struct HostManagerFactory : winrt::implements<HostManagerFactory, IClassFactory>
{
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
{
*result = nullptr;
if (outer)
{
return CLASS_E_NOAGGREGATION;
}
return winrt::make<winrt::ScratchIsland::implementation::HostManager>().as(iid, result);
}
HRESULT __stdcall LockServer(BOOL) noexcept final
{
return S_OK;
}
static void RegisterHostManager()
{
DWORD registrationHostManager{};
winrt::check_hresult(CoRegisterClassObject(HostManager_clsid,
winrt::make<HostManagerFactory>().get(),
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&registrationHostManager));
printf("registrationHostManager:%d\n", registrationHostManager);
}
};

View file

@ -0,0 +1,12 @@
import "HostAndProcess.idl";
namespace ScratchIsland
{
[default_interface] runtimeclass HostManager // : IScratchInterface
{
HostManager();
Windows.Foundation.Collections.IObservableVector<HostAndProcess> Hosts { get; };
HostAndProcess CreateHost();
};
}

View file

@ -0,0 +1,605 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "IslandWindow.h"
#include "../types/inc/Viewport.hpp"
#include "resource.h"
extern "C" IMAGE_DOS_HEADER __ImageBase;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Hosting;
using namespace winrt::Windows::Foundation::Numerics;
using namespace ::Microsoft::Console::Types;
#define XAML_HOSTING_WINDOW_CLASS_NAME L"SCRATCH_ISLAND_CLASS"
IslandWindow::IslandWindow() noexcept :
_interopWindowHandle{ nullptr },
_rootGrid{ nullptr },
_source{ nullptr },
_pfnCreateCallback{ nullptr }
{
}
IslandWindow::~IslandWindow()
{
_source.Close();
}
// Method Description:
// - Create the actual window that we'll use for the application.
// Arguments:
// - <none>
// Return Value:
// - <none>
void IslandWindow::MakeWindow() noexcept
{
WNDCLASS wc{};
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hInstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
wc.lpszClassName = XAML_HOSTING_WINDOW_CLASS_NAME;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hIcon = LoadIconW(wc.hInstance, MAKEINTRESOURCEW(IDI_APPICON));
RegisterClass(&wc);
WINRT_ASSERT(!_window);
// Create the window with the default size here - During the creation of the
// window, the system will give us a chance to set its size in WM_CREATE.
// WM_CREATE will be handled synchronously, before CreateWindow returns.
WINRT_VERIFY(CreateWindowEx(_alwaysOnTop ? WS_EX_TOPMOST : 0,
wc.lpszClassName,
L"Scratch Island",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
nullptr,
nullptr,
wc.hInstance,
this));
WINRT_ASSERT(_window);
}
// Method Description:
// - Called when no tab is remaining to close the window.
// Arguments:
// - <none>
// Return Value:
// - <none>
void IslandWindow::Close()
{
PostQuitMessage(0);
}
// Method Description:
// - Set a callback to be called when we process a WM_CREATE message. This gives
// the AppHost a chance to resize the window to the proper size.
// Arguments:
// - pfn: a function to be called during the handling of WM_CREATE. It takes two
// parameters:
// * HWND: the HWND of the window that's being created.
// * RECT: The position on the screen that the system has proposed for our
// window.
// Return Value:
// - <none>
void IslandWindow::SetCreateCallback(std::function<void(const HWND, const RECT)> pfn) noexcept
{
_pfnCreateCallback = pfn;
}
// Method Description:
// - Handles a WM_CREATE message. Calls our create callback, if one's been set.
// Arguments:
// - wParam: unused
// - lParam: the lParam of a WM_CREATE, which is a pointer to a CREATESTRUCTW
// Return Value:
// - <none>
void IslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam) noexcept
{
// Get proposed window rect from create structure
CREATESTRUCTW* pcs = reinterpret_cast<CREATESTRUCTW*>(lParam);
RECT rc;
rc.left = pcs->x;
rc.top = pcs->y;
rc.right = rc.left + pcs->cx;
rc.bottom = rc.top + pcs->cy;
if (_pfnCreateCallback)
{
_pfnCreateCallback(_window.get(), rc);
}
int nCmdShow = SW_SHOW;
ShowWindow(_window.get(), nCmdShow);
UpdateWindow(_window.get());
}
// Method Description:
// - Handles a WM_SIZING message, which occurs when user drags a window border
// or corner. It intercepts this resize action and applies 'snapping' i.e.
// aligns the terminal's size to its cell grid. We're given the window size,
// which we then adjust based on the terminal's properties (like font size).
// Arguments:
// - wParam: Specifies which edge of the window is being dragged.
// - lParam: Pointer to the requested window rectangle (this is, the one that
// originates from current drag action). It also acts as the return value
// (it's a ref parameter).
// Return Value:
// - <none>
LRESULT IslandWindow::_OnSizing(const WPARAM /*wParam*/, const LPARAM /*lParam*/)
{
// If we haven't been given the callback that would adjust the dimension,
// then we can't do anything, so just bail out.
return FALSE;
}
void IslandWindow::Initialize()
{
const bool initialized = (_interopWindowHandle != nullptr);
_source = DesktopWindowXamlSource{};
auto interop = _source.as<IDesktopWindowXamlSourceNative>();
winrt::check_hresult(interop->AttachToWindow(_window.get()));
// stash the child interop handle so we can resize it when the main hwnd is resized
interop->get_WindowHandle(&_interopWindowHandle);
_rootGrid = winrt::Windows::UI::Xaml::Controls::Grid();
_source.Content(_rootGrid);
}
void IslandWindow::OnSize(const UINT width, const UINT height)
{
// update the interop window size
SetWindowPos(_interopWindowHandle, nullptr, 0, 0, width, height, SWP_SHOWWINDOW);
if (_rootGrid)
{
const auto size = GetLogicalSize();
_rootGrid.Width(size.Width);
_rootGrid.Height(size.Height);
}
}
[[nodiscard]] LRESULT IslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
{
switch (message)
{
case WM_CREATE:
{
_HandleCreateWindow(wparam, lparam);
return 0;
}
case WM_SETFOCUS:
{
if (_interopWindowHandle != nullptr)
{
// send focus to the child window
SetFocus(_interopWindowHandle);
return 0; // eat the message
}
}
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_NCXBUTTONDOWN:
case WM_NCXBUTTONUP:
{
// If we clicked in the titlebar, raise an event so the app host can
// dispatch an appropriate event.
_DragRegionClickedHandlers();
break;
}
case WM_MENUCHAR:
{
// GH#891: return this LRESULT here to prevent the app from making a
// bell when alt+key is pressed. A menu is active and the user presses a
// key that does not correspond to any mnemonic or accelerator key,
return MAKELRESULT(0, MNC_CLOSE);
}
case WM_SIZING:
{
return _OnSizing(wparam, lparam);
}
case WM_CLOSE:
{
// // If the user wants to close the app by clicking 'X' button,
// // we hand off the close experience to the app layer. If all the tabs
// // are closed, the window will be closed as well.
// _windowCloseButtonClickedHandler();
// return 0;
Close();
}
case WM_MOUSEWHEEL:
try
{
// This whole handler is a hack for GH#979.
//
// On some laptops, their trackpads won't scroll inactive windows
// _ever_. With our entire window just being one giant XAML Island, the
// touchpad driver thinks our entire window is inactive, and won't
// scroll the XAML island. On those types of laptops, we'll get a
// WM_MOUSEWHEEL here, in our root window, when the trackpad scrolls.
// We're going to take that message and manually plumb it through to our
// TermControl's, or anything else that implements IMouseWheelListener.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx
// Important! Do not use the LOWORD or HIWORD macros to extract the x-
// and y- coordinates of the cursor position because these macros return
// incorrect results on systems with multiple monitors. Systems with
// multiple monitors can have negative x- and y- coordinates, and LOWORD
// and HIWORD treat the coordinates as unsigned quantities.
const til::point eventPoint{ GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) };
// This mouse event is relative to the display origin, not the window. Convert here.
const til::rectangle windowRect{ GetWindowRect() };
const auto origin = windowRect.origin();
const auto relative = eventPoint - origin;
// Convert to logical scaling before raising the event.
const auto real = relative / GetCurrentDpiScale();
const short wheelDelta = static_cast<short>(HIWORD(wparam));
// Raise an event, so any listeners can handle the mouse wheel event manually.
_MouseScrolledHandlers(real, wheelDelta);
return 0;
}
CATCH_LOG();
}
// TODO: handle messages here...
return base_type::MessageHandler(message, wparam, lparam);
}
// Method Description:
// - Called when the window has been resized (or maximized)
// Arguments:
// - width: the new width of the window _in pixels_
// - height: the new height of the window _in pixels_
void IslandWindow::OnResize(const UINT width, const UINT height)
{
if (_interopWindowHandle)
{
OnSize(width, height);
}
}
// Method Description:
// - Called when the window is minimized to the taskbar.
void IslandWindow::OnMinimize()
{
// TODO GH#1989 Stop rendering island content when the app is minimized.
}
// Method Description:
// - Called when the window is restored from having been minimized.
void IslandWindow::OnRestore()
{
// TODO GH#1989 Stop rendering island content when the app is minimized.
}
void IslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content)
{
_rootGrid.Children().Clear();
_rootGrid.Children().Append(content);
}
// Method Description:
// - Gets the difference between window and client area size.
// Arguments:
// - dpi: dpi of a monitor on which the window is placed
// Return Value
// - The size difference
SIZE IslandWindow::GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept
{
const auto windowStyle = static_cast<DWORD>(GetWindowLong(_window.get(), GWL_STYLE));
RECT islandFrame{};
// If we failed to get the correct window size for whatever reason, log
// the error and go on. We'll use whatever the control proposed as the
// size of our window, which will be at least close.
LOG_IF_WIN32_BOOL_FALSE(AdjustWindowRectExForDpi(&islandFrame, windowStyle, false, 0, dpi));
return {
islandFrame.right - islandFrame.left,
islandFrame.bottom - islandFrame.top
};
}
void IslandWindow::OnAppInitialized()
{
// Do a quick resize to force the island to paint
const auto size = GetPhysicalSize();
OnSize(size.cx, size.cy);
}
// Method Description:
// - Called when the app wants to change its theme. We'll update the root UI
// element of the entire XAML tree, so that all UI elements get the theme
// applied.
// Arguments:
// - arg: the ElementTheme to use as the new theme for the UI
// Return Value:
// - <none>
void IslandWindow::OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme)
{
_rootGrid.RequestedTheme(requestedTheme);
// Invalidate the window rect, so that we'll repaint any elements we're
// drawing ourselves to match the new theme
::InvalidateRect(_window.get(), nullptr, false);
}
// Method Description:
// - Updates our focus mode state. See _SetIsBorderless for more details.
// Arguments:
// - <none>
// Return Value:
// - <none>
void IslandWindow::FocusModeChanged(const bool focusMode)
{
// Do nothing if the value was unchanged.
if (focusMode == _borderless)
{
return;
}
_SetIsBorderless(focusMode);
}
// Method Description:
// - Updates our fullscreen state. See _SetIsFullscreen for more details.
// Arguments:
// - <none>
// Return Value:
// - <none>
void IslandWindow::FullscreenChanged(const bool fullscreen)
{
// Do nothing if the value was unchanged.
if (fullscreen == _fullscreen)
{
return;
}
_SetIsFullscreen(fullscreen);
}
// Method Description:
// - Enter or exit the "always on top" state. Before the window is created, this
// value will later be used when we create the window to create the window on
// top of all others. After the window is created, it will either enter the
// group of topmost windows, or exit the group of topmost windows.
// Arguments:
// - alwaysOnTop: whether we should be entering or exiting always on top mode.
// Return Value:
// - <none>
void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop)
{
_alwaysOnTop = alwaysOnTop;
const auto hwnd = GetHandle();
if (hwnd)
{
SetWindowPos(hwnd,
_alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
0, // the window dimensions are unused, because we're passing SWP_NOSIZE
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE);
}
}
// From GdiEngine::s_SetWindowLongWHelper
void _SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept
{
// SetWindowLong has strange error handling. On success, it returns the
// previous Window Long value and doesn't modify the Last Error state. To
// deal with this, we set the last error to 0/S_OK first, call it, and if
// the previous long was 0, we check if the error was non-zero before
// reporting. Otherwise, we'll get an "Error: The operation has completed
// successfully." and there will be another screenshot on the internet
// making fun of Windows. See:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms633591(v=vs.85).aspx
SetLastError(0);
LONG const lResult = SetWindowLongW(hWnd, nIndex, dwNewLong);
if (0 == lResult)
{
LOG_LAST_ERROR_IF(0 != GetLastError());
}
}
// Method Description:
// - This is a helper to figure out what the window styles should be, given the
// current state of flags like borderless mode and fullscreen mode.
// Arguments:
// - <none>
// Return Value:
// - a LONG with the appropriate flags set for our current window mode, to be used with GWL_STYLE
LONG IslandWindow::_getDesiredWindowStyle() const
{
auto windowStyle = GetWindowLongW(GetHandle(), GWL_STYLE);
// If we're both fullscreen and borderless, fullscreen mode takes precedence.
if (_fullscreen)
{
// When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies
// styles for non-fullscreen windows (e.g. caption bar), and add the
// WS_POPUP style to allow us to size ourselves to the monitor size.
// Do the reverse when restoring from fullscreen.
// Doing these modifications to that window will cause a vista-style
// window frame to briefly appear when entering and exiting fullscreen.
WI_ClearFlag(windowStyle, WS_BORDER);
WI_ClearFlag(windowStyle, WS_SIZEBOX);
WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW);
WI_SetFlag(windowStyle, WS_POPUP);
return windowStyle;
}
else if (_borderless)
{
// When moving to borderless, remove WS_OVERLAPPEDWINDOW, which
// specifies styles for non-fullscreen windows (e.g. caption bar), and
// add the WS_BORDER and WS_SIZEBOX styles. This allows us to still have
// a small resizing frame, but without a full titlebar, nor caption
// buttons.
WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW);
WI_ClearFlag(windowStyle, WS_POPUP);
WI_SetFlag(windowStyle, WS_BORDER);
WI_SetFlag(windowStyle, WS_SIZEBOX);
return windowStyle;
}
// Here, we're not in either fullscreen or borderless mode. Return to
// WS_OVERLAPPEDWINDOW.
WI_ClearFlag(windowStyle, WS_POPUP);
WI_ClearFlag(windowStyle, WS_BORDER);
WI_ClearFlag(windowStyle, WS_SIZEBOX);
WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW);
return windowStyle;
}
// Method Description:
// - Enable or disable focus mode. When entering focus mode, we'll
// need to manually hide the entire titlebar.
// - When we're entering focus we need to do some additional modification
// of our window styles. However, the NonClientIslandWindow very explicitly
// _doesn't_ need to do these steps.
// Arguments:
// - borderlessEnabled: If true, we're entering focus mode. If false, we're leaving.
// Return Value:
// - <none>
void IslandWindow::_SetIsBorderless(const bool borderlessEnabled)
{
_borderless = borderlessEnabled;
HWND const hWnd = GetHandle();
// First, modify regular window styles as appropriate
auto windowStyle = _getDesiredWindowStyle();
_SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle);
// Now modify extended window styles as appropriate
// When moving to fullscreen, remove the window edge style to avoid an
// ugly border when not focused.
auto exWindowStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen);
_SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
// Resize the window, with SWP_FRAMECHANGED, to trigger user32 to
// recalculate the non/client areas
const til::rectangle windowPos{ GetWindowRect() };
SetWindowPos(GetHandle(),
HWND_TOP,
windowPos.left<int>(),
windowPos.top<int>(),
windowPos.width<int>(),
windowPos.height<int>(),
SWP_SHOWWINDOW | SWP_FRAMECHANGED);
}
// Method Description:
// - Controls setting us into or out of fullscreen mode. Largely taken from
// Window::SetIsFullscreen in conhost.
// - When entering fullscreen mode, we'll save the current window size and
// location, and expand to take the entire monitor size. When leaving, we'll
// use that saved size to restore back to.
// Arguments:
// - fullscreenEnabled true if we should enable fullscreen mode, false to disable.
// Return Value:
// - <none>
void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
{
// It is possible to enter _SetIsFullscreen even if we're already in full
// screen. Use the old is in fullscreen flag to gate checks that rely on the
// current state.
const auto oldIsInFullscreen = _fullscreen;
_fullscreen = fullscreenEnabled;
HWND const hWnd = GetHandle();
// First, modify regular window styles as appropriate
auto windowStyle = _getDesiredWindowStyle();
_SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle);
// Now modify extended window styles as appropriate
// When moving to fullscreen, remove the window edge style to avoid an
// ugly border when not focused.
auto exWindowStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen);
_SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
// When entering/exiting fullscreen mode, we also need to backup/restore the
// current window size, and resize the window to match the new state.
_BackupWindowSizes(oldIsInFullscreen);
_ApplyWindowSize();
}
// Method Description:
// - Used in entering/exiting fullscreen mode. Saves the current window size,
// and the full size of the monitor, for use in _ApplyWindowSize.
// - Taken from conhost's Window::_BackupWindowSizes
// Arguments:
// - fCurrentIsInFullscreen: true if we're currently in fullscreen mode.
// Return Value:
// - <none>
void IslandWindow::_BackupWindowSizes(const bool fCurrentIsInFullscreen)
{
if (_fullscreen)
{
// Note: the current window size depends on the current state of the
// window. So don't back it up if we're already in full screen.
if (!fCurrentIsInFullscreen)
{
_nonFullscreenWindowSize = GetWindowRect();
}
// get and back up the current monitor's size
HMONITOR const hCurrentMonitor = MonitorFromWindow(GetHandle(), MONITOR_DEFAULTTONEAREST);
MONITORINFO currMonitorInfo;
currMonitorInfo.cbSize = sizeof(currMonitorInfo);
if (GetMonitorInfo(hCurrentMonitor, &currMonitorInfo))
{
_fullscreenWindowSize = currMonitorInfo.rcMonitor;
}
}
}
// Method Description:
// - Applys the appropriate window size for transitioning to/from fullscreen mode.
// - Taken from conhost's Window::_ApplyWindowSize
// Arguments:
// - <none>
// Return Value:
// - <none>
void IslandWindow::_ApplyWindowSize()
{
const auto newSize = _fullscreen ? _fullscreenWindowSize : _nonFullscreenWindowSize;
LOG_IF_WIN32_BOOL_FALSE(SetWindowPos(GetHandle(),
HWND_TOP,
newSize.left,
newSize.top,
newSize.right - newSize.left,
newSize.bottom - newSize.top,
SWP_FRAMECHANGED));
}
DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
DEFINE_EVENT(IslandWindow, WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>);

View file

@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "BaseWindow.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
class IslandWindow :
public BaseWindow<IslandWindow>
{
public:
IslandWindow() noexcept;
virtual ~IslandWindow() override;
virtual void MakeWindow() noexcept;
void Close();
virtual void OnSize(const UINT width, const UINT height);
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
void OnResize(const UINT width, const UINT height) override;
void OnMinimize() override;
void OnRestore() override;
virtual void OnAppInitialized();
virtual void SetContent(winrt::Windows::UI::Xaml::UIElement content);
virtual void OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
virtual SIZE GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept;
virtual void Initialize();
void SetCreateCallback(std::function<void(const HWND, const RECT)> pfn) noexcept;
void FocusModeChanged(const bool focusMode);
void FullscreenChanged(const bool fullscreen);
void SetAlwaysOnTop(const bool alwaysOnTop);
#pragma endregion
DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>);
WINRT_CALLBACK(MouseScrolled, winrt::delegate<void(til::point, int32_t)>);
protected:
void ForceResize()
{
// Do a quick resize to force the island to paint
const auto size = GetPhysicalSize();
OnSize(size.cx, size.cy);
}
HWND _interopWindowHandle;
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _source;
winrt::Windows::UI::Xaml::Controls::Grid _rootGrid;
std::function<void(const HWND, const RECT)> _pfnCreateCallback;
void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept;
[[nodiscard]] LRESULT _OnSizing(const WPARAM wParam, const LPARAM lParam);
bool _borderless{ false };
bool _fullscreen{ false };
bool _alwaysOnTop{ false };
RECT _fullscreenWindowSize;
RECT _nonFullscreenWindowSize;
virtual void _SetIsBorderless(const bool borderlessEnabled);
virtual void _SetIsFullscreen(const bool fullscreenEnabled);
void _BackupWindowSizes(const bool currentIsInFullscreen);
void _ApplyWindowSize();
LONG _getDesiredWindowStyle() const;
private:
// This minimum width allows for width the tabs fit
static constexpr long minimumWidth = 460L;
};

View file

@ -0,0 +1 @@


View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<!-- This file is copied into ut_app/TerminalApp.Unit.Tests.manifest as part
of the pre-build step for that project. Changes should only be made to the
WindowsTerminal version of the file. -->
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 1903 -->
<!-- See https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands -->
<!-- "maxversiontested" is CASE SENSITIVE. Do not change this.-->
<maxversiontested Id="10.0.18362.0"/>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
</assembly>

View file

@ -0,0 +1,94 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPICON ICON "..\\..\\..\\res\\terminal.ico"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_ERROR_DIALOG_TITLE "Error"
IDS_HELP_DIALOG_TITLE "Help"
IDS_ERROR_ARCHITECTURE_FORMAT
"Windows Terminal is designed to run on your system's native architecture (%s).\nYou are currently using the %s version.\n\nPlease use the version of Windows Terminal that matches your system's native architecture."
IDS_X86_ARCHITECTURE "i386"
END
STRINGTABLE
BEGIN
IDS_AMD64_ARCHITECTURE "AMD64"
IDS_ARM64_ARCHITECTURE "ARM64"
IDS_ARM_ARCHITECTURE "ARM"
IDS_UNKNOWN_ARCHITECTURE "Unknown"
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View file

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<PropertyGroup Label="Globals">
<ProjectGuid>{23a1f736-cd19-4196-980f-84bcd50cf783}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ScratchIsland</RootNamespace>
<ProjectName>ScratchIsland</ProjectName>
<TargetName>ScratchIsland</TargetName>
<ConfigurationType>Application</ConfigurationType>
<OpenConsoleUniversalApp>false</OpenConsoleUniversalApp>
<ApplicationType>Windows Store</ApplicationType>
<WindowsStoreApp>true</WindowsStoreApp>
<WindowsAppContainer>false</WindowsAppContainer>
<!-- IMPORTANT! Xaml Islands only works on >= 17709 -->
<!-- IMPORTANT! cppwinrt.pre.props specifies 17134 -->
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<!-- DON'T REDIRECT OUR OUTPUT -->
<NoOutputRedirection>true</NoOutputRedirection>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
<ClCompile>
<SDLCheck>true</SDLCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\src\inc;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\Console;$(OpenConsoleDir)\dep\Win32K;$(OpenConsoleDir)\dep\gsl\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile>
<!-- Manually include the generated TerminalCore header's path, because
adding a project reference will confuse msbuild, because TerminalCore
isn't a dll, it's a lib, and cppwinrt won't include a lib's header -->
<AdditionalIncludeDirectories>"$(OpenConsoleDir)src\cascadia\TerminalCore\lib\Generated Files";%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>gdi32.lib;dwmapi.lib;Shcore.lib;UxTheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<PropertyGroup>
<GenerateManifest>true</GenerateManifest>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<!-- Source Files -->
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="AppHost.h" />
<ClInclude Include="BaseWindow.h" />
<ClInclude Include="IslandWindow.h" />
<ClInclude Include="HostManager.h" />
<ClInclude Include="HostAndProcess.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="main.cpp" />
<ClCompile Include="AppHost.cpp" />
<ClCompile Include="IslandWindow.cpp" />
<ClCompile Include="HostManager.cpp" />
<ClCompile Include="HostAndProcess.cpp" />
</ItemGroup>
<ItemGroup>
<Midl Include="HostManager.idl" />
<Midl Include="HostAndProcess.idl" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ScratchIsland.rc" />
</ItemGroup>
<ItemGroup>
<Manifest Include="ScratchIsland.manifest" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<!-- Dependencies -->
<ItemGroup>
<!-- Even though we do have proper recursive dependencies, we want to keep some of these here
so that the AppX Manifest contains their activatable classes. -->
<!-- <ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettings\TerminalSettings.vcxproj" /> -->
<!-- <ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" /> -->
<!-- <ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" /> -->
<!-- <ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\TerminalApp.vcxproj" /> -->
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
<ProjectReference Include="..\ScratchWinRTServer\ScratchWinRTServer.vcxproj">
<Project>{d46d9547-f085-4645-b8f7-e8cd21559ab4}</Project>
</ProjectReference>
</ItemGroup>
<!--
This ItemGroup and the Globals PropertyGroup below it are required in order
to enable F5 debugging for the unpackaged application
-->
<ItemGroup>
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\debugger_general.xml" />
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\debugger_local_windows.xml" />
</ItemGroup>
<PropertyGroup Label="Globals">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.200609001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.200609001\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.200609001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.200609001\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.1-rc\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets'))" />
</Target>
<!-- Override GetPackagingOutputs to roll up all our dependencies.
This ensures that when the WAP packaging project asks what files go into
the package, we tell it.
This is a heavily stripped version of the one in Microsoft.*.AppxPackage.targets.
-->
<PropertyGroup>
<_ContinueOnError Condition="'$(BuildingProject)' == 'true'">true</_ContinueOnError>
<_ContinueOnError Condition="'$(BuildingProject)' != 'true'">false</_ContinueOnError>
</PropertyGroup>
<Target Name="GetPackagingOutputs" Returns="@(PackagingOutputs)">
<MSBuild
Projects="@(ProjectReferenceWithConfiguration)"
Targets="GetPackagingOutputs"
BuildInParallel="$(BuildInParallel)"
Properties="%(ProjectReferenceWithConfiguration.SetConfiguration); %(ProjectReferenceWithConfiguration.SetPlatform)"
Condition="'@(ProjectReferenceWithConfiguration)' != ''
and '%(ProjectReferenceWithConfiguration.BuildReference)' == 'true'
and '%(ProjectReferenceWithConfiguration.ReferenceOutputAssembly)' == 'true'"
ContinueOnError="$(_ContinueOnError)">
<Output TaskParameter="TargetOutputs" ItemName="_PackagingOutputsFromOtherProjects"/>
</MSBuild>
<ItemGroup>
<PackagingOutputs Include="@(_PackagingOutputsFromOtherProjects)" />
</ItemGroup>
<!-- **BEGIN VC LIBS HACK** -->
<PropertyGroup>
<ReasonablePlatform Condition="'$(Platform)'=='Win32'">x86</ReasonablePlatform>
<ReasonablePlatform Condition="'$(ReasonablePlatform)'==''">$(Platform)</ReasonablePlatform>
</PropertyGroup>
<ItemGroup Condition="'$(ScratchIslandOfficialBuild)'=='true'">
<!-- Add all the CRT libs as content; these must be inside a Target as they are wildcards. -->
<_OpenConsoleVCLibToCopy Include="$(VCToolsRedistInstallDir)\$(ReasonablePlatform)\Microsoft.VC142.CRT\*.dll" />
<PackagingOutputs Include="@(_OpenConsoleVCLibToCopy)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
<!-- **END VC LIBS HACK** -->
</Target>
<!-- <Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" /> -->
<Import Project="..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" />
</Project>

View file

@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "AppHost.h"
#include "resource.h"
using namespace winrt;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml::Hosting;
using namespace winrt::Windows::Foundation::Numerics;
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
// If Terminal is spawned by a shortcut that requests that it run in a new process group
// while attached to a console session, that request is nonsense. That request will, however,
// cause WT to start with Ctrl-C disabled. This wouldn't matter, because it's a Windows-subsystem
// application. Unfortunately, that state is heritable. In short, if you start WT using cmd in
// a weird way, ^C stops working _inside_ the terminal. Mad.
SetConsoleCtrlHandler(NULL, FALSE);
// Make sure to call this so we get WM_POINTER messages.
EnableMouseInPointer(true);
// !!! LOAD BEARING !!!
// We must initialize the main thread as a single-threaded apartment before
// constructing any Xaml objects. Failing to do so will cause some issues
// in accessibility somewhere down the line when a UIAutomation object will
// be queried on the wrong thread at the wrong time.
// We used to initialize as STA only _after_ initializing the application
// host, which loaded the settings. The settings needed to be loaded in MTA
// because we were using the Windows.Storage APIs. Since we're no longer
// doing that, we can safely init as STA before any WinRT dispatches.
winrt::init_apartment(winrt::apartment_type::single_threaded);
// Create the AppHost object, which will create both the window and the
// Terminal App. This MUST BE constructed before the Xaml manager as TermApp
// provides an implementation of Windows.UI.Xaml.Application.
AppHost host;
// Initialize the xaml content. This must be called AFTER the
// WindowsXamlManager is initialized.
host.Initialize();
MSG message;
while (GetMessage(&message, nullptr, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.200316.3" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.0.0" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.200609001" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.1-rc" targetFramework="native" />
<package id="Terminal.ThemeHelpers" version="0.2.200324001" targetFramework="native" />
</packages>

View file

@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View file

@ -0,0 +1,92 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- pch.h
Abstract:
- Contains external headers to include in the precompile phase of console build process.
- Avoid including internal project headers. Instead include them only in the classes that need them (helps with test project building).
--*/
#pragma once
// Ignore checked iterators warning from VC compiler.
#define _SCL_SECURE_NO_WARNINGS
// Block minwindef.h min/max macros to prevent <algorithm> conflict
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <unknwn.h>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#include <windows.h>
#include <UIAutomation.h>
#include <cstdlib>
#include <cstring>
#include <shellscalingapi.h>
#include <windowsx.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#define BLOCK_TIL
#include "../inc/LibraryIncludes.h"
// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
// SDK definition of this function, so the only fix is to undef it.
// from WinBase.h
// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
#include <wil/cppwinrt.h>
// Needed just for XamlIslands to work at all:
#include <winrt/Windows.system.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/windows.ui.core.h>
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
// Additional headers for various xaml features. We need:
// * Controls for grid
// * Media for ScaleTransform
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <windows.ui.xaml.media.dxinterop.h>
#include <wil/resource.h>
#include <wil/win32_helpers.h>
// Including TraceLogging essentials for the binary
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DECLARE_PROVIDER(g_hWindowsTerminalProvider);
#include <telemetry\ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
// For commandline argument processing
#include <shellapi.h>
#include <processenv.h>
#include <dcomp.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <dxgi1_3.h>
#include <d3d11.h>
#include <d2d1.h>
#include <d2d1_1.h>
#include <d2d1_2.h>
#include <d2d1_3.h>
#include <d2d1helper.h>
#include <dwrite.h>
#include <dwrite_1.h>
#include <dwrite_2.h>
#include <dwrite_3.h>
#include "til.h"

View file

@ -0,0 +1,24 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by WindowsTerminal.rc
//
#define IDI_APPICON 101
#define IDS_ERROR_DIALOG_TITLE 105
#define IDS_HELP_DIALOG_TITLE 106
#define IDS_ERROR_ARCHITECTURE_FORMAT 110
#define IDS_X86_ARCHITECTURE 111
#define IDS_AMD64_ARCHITECTURE 112
#define IDS_ARM64_ARCHITECTURE 113
#define IDS_ARM_ARCHITECTURE 114
#define IDS_UNKNOWN_ARCHITECTURE 115
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -0,0 +1,261 @@
#include "pch.h"
#include <argb.h>
#include <DefaultSettings.h>
#include "HostClass.h"
#include "HostClass.g.cpp"
// #include <wrl.h>
extern std::mutex m;
extern std::condition_variable cv;
extern bool dtored;
using namespace ::Microsoft::Console::Types;
using namespace ::Microsoft::Terminal::Core;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Input;
using namespace winrt::Windows::UI::Xaml::Automation::Peers;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::ViewManagement;
using namespace winrt::Windows::UI::Input;
using namespace winrt::Windows::System;
using namespace winrt::Microsoft::Terminal::Settings;
// using namespace winrt::Windows::ApplicationModel::DataTransfer;
namespace winrt::ScratchWinRTServer::implementation
{
HostClass::HostClass(const winrt::guid& g) :
_id{ g },
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false }
{
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
_settings = winrt::Microsoft::Terminal::Settings::TerminalSettings();
auto fontSize = _settings.FontSize();
const auto newSize = std::max<short>(gsl::narrow_cast<short>(fontSize), 1);
const auto fontFace = _settings.FontFace();
const auto fontWeight = _settings.FontWeight();
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false };
_desiredFont = { _actualFont };
}
HostClass::~HostClass()
{
printf("~HostClass()\n");
std::unique_lock<std::mutex> lk(m);
dtored = true;
cv.notify_one();
}
winrt::guid HostClass::Id()
{
return _id;
}
void HostClass::Attach(Windows::UI::Xaml::Controls::SwapChainPanel panel)
{
printf("Hey dummy, we're not using Attach() anymore\n");
}
void HostClass::BeginRendering()
{
_InitializeTerminal();
}
void HostClass::RenderEngineSwapChainChanged()
{
// This event is only registered during terminal initialization,
// so we don't need to check _initializedTerminal.
// We also don't lock for things that come back from the renderer.
auto chainHandle = _renderEngine->GetSwapChainHandle();
auto weakThis{ get_weak() };
// co_await winrt::resume_foreground(Dispatcher());
if (auto control{ weakThis.get() })
{
_AttachDxgiSwapChainToXaml(chainHandle);
}
}
void HostClass::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle)
{
// NOPE DONT DO THIS
// auto nativePanel = _panel.as<ISwapChainPanelNative2>();
// nativePanel->SetSwapChainHandle(swapChainHandle);
}
void HostClass::ThisIsInsane(uint64_t swapchainHandle)
{
HANDLE foo = (HANDLE)swapchainHandle;
_hSwapchain.reset(foo);
// _hSwapchain.put((HANDLE)swapchainHandle);
// _hSwapchain = (HANDLE)swapchainHandle;
}
bool HostClass::_InitializeTerminal()
{
{ // scope for terminalLock
auto terminalLock = _terminal->LockForWriting();
if (_initializedTerminal)
{
return false;
}
// const auto actualWidth = _panel.ActualWidth();
// const auto actualHeight = _panel.ActualHeight();
// const auto windowWidth = actualWidth * _panel.CompositionScaleX(); // Width() and Height() are NaN?
// const auto windowHeight = actualHeight * _panel.CompositionScaleY();
const auto actualWidth = 400; //_panel.ActualWidth();
const auto actualHeight = 150; //_panel.ActualHeight();
const auto windowWidth = 400.0; // actualWidth * _panel.CompositionScaleX(); // Width() and Height() are NaN?
const auto windowHeight = 150.0; // actualHeight * _panel.CompositionScaleY();
if (windowWidth == 0 || windowHeight == 0)
{
return false;
}
// First create the render thread.
// Then stash a local pointer to the render thread so we can initialize it and enable it
// to paint itself *after* we hand off its ownership to the renderer.
// We split up construction and initialization of the render thread object this way
// because the renderer and render thread have circular references to each other.
auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>();
auto* const localPointerToThread = renderThread.get();
// Now create the renderer and initialize the render thread.
_renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread));
::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer;
// _renderer->SetRendererEnteredErrorStateCallback([weakThis = get_weak()]() {
// if (auto strongThis{ weakThis.get() })
// {
// strongThis->_RendererEnteredErrorState();
// }
// });
THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get()));
// Set up the DX Engine
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
dxEngine->_swapChainHandle.swap(_hSwapchain);
_renderer->AddRenderEngine(dxEngine.get());
// Initialize our font with the renderer
// We don't have to care about DPI. We'll get a change message immediately if it's not 96
// and react accordingly.
// _UpdateFont(true); // <-- TODO
_renderer->TriggerFontChange(96, _desiredFont, _actualFont); // "UpdateFont"
const COORD windowSize{ static_cast<short>(windowWidth), static_cast<short>(windowHeight) };
// Fist set up the dx engine with the window size in pixels.
// Then, using the font, get the number of characters that can fit.
// Resize our terminal connection to match that size, and initialize the terminal with that size.
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize);
THROW_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
// Update DxEngine's SelectionBackground
// dxEngine->SetSelectionBackground(_settings.SelectionBackground());
const auto vp = dxEngine->GetViewportInCharacters(viewInPixels);
const auto width = vp.Width();
const auto height = vp.Height();
// _connection.Resize(height, width); // <-- TODO
// Override the default width and height to match the size of the swapChainPanel
// _settings.InitialCols(width); // <-- TODO
// _settings.InitialRows(height); // <-- TODO
_settings.DefaultBackground(til::color{ 255, 0, 255, 255 }); //rgba
_settings.DefaultForeground(til::color{ 0, 0, 0, 255 }); //rgba
_terminal->CreateFromSettings(_settings, renderTarget); // <-- TODO
dxEngine->SetRetroTerminalEffects(false);
dxEngine->SetForceFullRepaintRendering(false);
dxEngine->SetSoftwareRendering(false);
// // Update DxEngine's AntialiasingMode
// switch (_settings.AntialiasingMode())
// {
// case TextAntialiasingMode::Cleartype:
// dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
// break;
// case TextAntialiasingMode::Aliased:
// dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
// break;
// case TextAntialiasingMode::Grayscale:
// default:
// dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
// break;
// }
// // GH#5098: Inform the engine of the opacity of the default text background.
// if (_settings.UseAcrylic())
// {
// dxEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.TintOpacity()));
// }
THROW_IF_FAILED(dxEngine->Enable());
_renderEngine = std::move(dxEngine);
// _AttachDxgiSwapChainToXaml(_renderEngine->GetSwapChainHandle());
// Tell the DX Engine to notify us when the swap chain changes.
// We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems)
_renderEngine->SetCallback(std::bind(&HostClass::RenderEngineSwapChainChanged, this));
// auto bottom = _terminal->GetViewport().BottomExclusive();
// auto bufferHeight = bottom;
// ScrollBar().Maximum(bufferHeight - bufferHeight);
// ScrollBar().Minimum(0);
// ScrollBar().Value(0);
// ScrollBar().ViewportSize(bufferHeight);
localPointerToThread->EnablePainting();
// // Set up blinking cursor
// int blinkTime = GetCaretBlinkTime();
// if (blinkTime != INFINITE)
// {
// // Create a timer
// DispatcherTimer cursorTimer;
// cursorTimer.Interval(std::chrono::milliseconds(blinkTime));
// cursorTimer.Tick({ get_weak(), &TermControl::_CursorTimerTick });
// cursorTimer.Start();
// _cursorTimer.emplace(std::move(cursorTimer));
// }
// else
// {
// // The user has disabled cursor blinking
// _cursorTimer = std::nullopt;
// }
// // import value from WinUser (convert from milli-seconds to micro-seconds)
// _multiClickTimer = GetDoubleClickTime() * 1000;
// // Focus the control here. If we do it during control initialization, then
// // focus won't actually get passed to us. I believe this is because
// // we're not technically a part of the UI tree yet, so focusing us
// // becomes a no-op.
// this->Focus(FocusState::Programmatic);
_initializedTerminal = true;
} // scope for TerminalLock
// Start the connection outside of lock, because it could
// start writing output immediately.
// _connection.Start(); // <-- TODO
// Likewise, run the event handlers outside of lock (they could
// be reentrant)
// _InitializedHandlers(*this, nullptr);
_terminal->Write(L"Hello world from another process");
return true;
}
}

View file

@ -0,0 +1,52 @@
#pragma once
#include "HostClass.g.h"
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
#include <winrt/Microsoft.Terminal.Settings.h>
#include "../../renderer/base/Renderer.hpp"
#include "../../renderer/dx/DxRenderer.hpp"
#include "../../renderer/uia/UiaRenderer.hpp"
#include "../../cascadia/TerminalCore/Terminal.hpp"
namespace winrt::ScratchWinRTServer::implementation
{
struct HostClass : HostClassT<HostClass>
{
HostClass(const winrt::guid& g);
~HostClass();
void DoTheThing();
void Attach(Windows::UI::Xaml::Controls::SwapChainPanel panel);
void BeginRendering();
void RenderEngineSwapChainChanged();
void ThisIsInsane(uint64_t swapchainHandle);
private:
int _DoCount{ 0 };
winrt::guid _id;
wil::unique_handle _hSwapchain{ INVALID_HANDLE_VALUE };
Windows::UI::Xaml::Controls::SwapChainPanel _panel{ nullptr };
bool _initializedTerminal{ false };
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _connection;
std::unique_ptr<::Microsoft::Terminal::Core::Terminal> _terminal;
FontInfoDesired _desiredFont;
FontInfo _actualFont;
std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer;
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine;
winrt::Microsoft::Terminal::Settings::IControlSettings _settings;
void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle);
bool _InitializeTerminal();
};
}
namespace winrt::ScratchWinRTServer::factory_implementation
{
struct HostClass : HostClassT<HostClass, implementation::HostClass>
{
};
}

View file

@ -0,0 +1,15 @@
namespace ScratchWinRTServer
{
[default_interface] runtimeclass HostClass {
HostClass(Guid g);
Guid Id { get; };
void Attach(Windows.UI.Xaml.Controls.SwapChainPanel panel);
void BeginRendering();
void ThisIsInsane(UInt64 swapchainHandle);
};
}

View file

@ -0,0 +1,6 @@
#pragma once
struct __declspec(uuid("28578d33-c090-4279-9669-dbeea3f24bb0")) IMyComInterface : ::IUnknown
{
virtual HRESULT __stdcall Call() = 0;
};

View file

@ -0,0 +1,9 @@
// [
// uuid("BB64926F-1A4D-470D-BB8A-3D2CC4B035E4"),
// object,
// local
// ] interface IMyComInterface : IUnknown
// {
// HRESULT MyMethod();
// };

View file

@ -0,0 +1,11 @@
namespace ScratchWinRTServer
{
// [default_interface]
interface IScratchInterface
{
String DoTheThing();
};
}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<!--
To customize common C++/WinRT project properties:
* right-click the project node
* expand the Common Properties item
* select the C++/WinRT property page
For more advanced scenarios, and complete documentation, please see:
https://github.com/Microsoft/cppwinrt/tree/master/nuget
-->
<PropertyGroup />
<ItemDefinitionGroup />
</Project>

View file

@ -0,0 +1,11 @@
#include "pch.h"
#include "ScratchClass.h"
#include "ScratchClass.g.cpp"
namespace winrt::ScratchWinRTServer::implementation
{
ScratchClass::ScratchClass()
{
}
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "ScratchClass.g.h"
namespace winrt::ScratchWinRTServer::implementation
{
struct ScratchClass : public ScratchClassT<ScratchClass>
{
ScratchClass();
hstring DoTheThing()
{
return L"Hello there";
}
};
}
namespace winrt::ScratchWinRTServer::factory_implementation
{
struct ScratchClass : ScratchClassT<ScratchClass, implementation::ScratchClass>
{
};
}

View file

@ -0,0 +1,15 @@
namespace ScratchWinRTServer
{
[default_interface] runtimeclass ScratchClass // : IScratchInterface
{
ScratchClass();
String DoTheThing();
// Adding a Windows.UI.Xaml element will crash the server when the
// server tries to instantiate the element without a XAML host.
//
// Windows.UI.Xaml.Controls.Button MyButton { get; };
};
}

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 1903 -->
<!-- See https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands -->
<!-- "maxversiontested" is CASE SENSITIVE. Do not change this.-->
<maxversiontested Id="10.0.18362.0"/>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
<file name="ScratchWinRTServer.exe" hashalg="SHA1">
<activatableClass name="ScratchWinRTServer.ScratchClass" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1"></activatableClass>
</file>
<file name="TerminalSettings.dll" hashalg="SHA1">
<activatableClass name="Microsoft.Terminal.Settings.TerminalSettings" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1"></activatableClass>
</file>
</assembly>

View file

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
<MinimalCoreWin>true</MinimalCoreWin>
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{d46d9547-f085-4645-b8f7-e8cd21559ab4}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ScratchWinRTServer</RootNamespace>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="PropertySheet.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>_CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level4</WarningLevel>
<AdditionalOptions>%(AdditionalOptions) /permissive- /bigobj</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="ScratchClass.h" />
<ClInclude Include="HostClass.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ScratchClass.cpp" />
<ClCompile Include="HostClass.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="PropertySheet.props" />
<Text Include="readme.txt">
<DeploymentContent>false</DeploymentContent>
</Text>
</ItemGroup>
<ItemGroup>
<Midl Include="IScratchInterface.idl" />
<Midl Include="ScratchClass.idl" />
<Midl Include="HostClass.idl" />
<!-- <Midl Include="IMyComInterface.idl" /> -->
</ItemGroup>
<ItemGroup>
<Manifest Include="ScratchWinRTServer.manifest" />
</ItemGroup>
<ItemGroup>
<!-- <ProjectReference Include="..\ScratchWinRTServer\ScratchWinRTServer.vcxproj">
<Project>{d46d9547-f085-4645-b8f7-e8cd21559ab4}</Project>
</ProjectReference> -->
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\buffer\out\lib\bufferout.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\renderer\base\lib\base.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\renderer\dx\lib\dx.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\renderer\uia\lib\uia.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\terminal\parser\lib\parser.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\terminal\input\lib\terminalinput.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\cascadia\TerminalSettings\TerminalSettings.vcxproj">
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)src\cascadia\TerminalCore\lib\TerminalCore-lib.vcxproj" />
<ProjectReference Include="$(SolutionDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj">
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)\src\inc;$(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\Win32K;$(SolutionDir)\dep\gsl\include;$(SolutionDir)\dep\wil\include;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\libpopcnt;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<!-- <AdditionalIncludeDirectories>$(SolutionDir)\src\inc;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> -->
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
</ClCompile>
<Link>
<AdditionalDependencies>onecoreuap_apiset.lib;d3dcompiler.lib;dwmapi.lib;uxtheme.lib;shlwapi.lib;ntdll.lib;dcomp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200609.3\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Text Include="readme.txt" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,203 @@
#include "pch.h"
#include <winrt/ScratchWinRTServer.h>
#include "ScratchClass.h"
#include "HostClass.h"
using namespace winrt;
using namespace winrt::Windows::Foundation;
struct ScratchStringable : implements<ScratchStringable, IStringable, IClosable, winrt::ScratchWinRTServer::IScratchInterface>
{
hstring ToString()
{
return L"Hello from server, ScratchStringable";
}
hstring DoTheThing()
{
return L"Zhu Li! Do the thing!";
}
void Close() { printf("Closed ScratchStringable\n"); }
};
struct MyStringable : implements<MyStringable, IStringable>
{
hstring ToString()
{
return L"Hello from server, MyStringable";
}
};
struct MyStringableFactory : implements<MyStringableFactory, IClassFactory>
{
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
{
*result = nullptr;
if (outer)
{
return CLASS_E_NOAGGREGATION;
}
printf("Created MyStringable\n");
return make<MyStringable>().as(iid, result);
}
HRESULT __stdcall LockServer(BOOL) noexcept final
{
return S_OK;
}
};
struct ScratchStringableFactory : implements<ScratchStringableFactory, IClassFactory>
{
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
{
*result = nullptr;
if (outer)
{
return CLASS_E_NOAGGREGATION;
}
printf("Created ScratchStringable\n");
return make<ScratchStringable>().as(iid, result);
}
HRESULT __stdcall LockServer(BOOL) noexcept final
{
return S_OK;
}
};
struct ScratchClassFactory : implements<ScratchClassFactory, IClassFactory>
{
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
{
*result = nullptr;
if (outer)
{
return CLASS_E_NOAGGREGATION;
}
printf("\x1b[90mSERVER: Created ScratchClass\x1b[m\n");
return make<ScratchWinRTServer::implementation::ScratchClass>().as(iid, result);
}
HRESULT __stdcall LockServer(BOOL) noexcept final
{
return S_OK;
}
};
std::mutex m;
std::condition_variable cv;
bool dtored = false;
winrt::weak_ref<ScratchWinRTServer::implementation::HostClass> g_weak{ nullptr };
struct HostClassFactory : implements<HostClassFactory, IClassFactory>
{
HostClassFactory(winrt::guid g) :
_guid{ g } {};
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
{
*result = nullptr;
if (outer)
{
return CLASS_E_NOAGGREGATION;
}
if (!g_weak)
{
auto strong = make_self<ScratchWinRTServer::implementation::HostClass>(_guid);
g_weak = (*strong).get_weak();
return strong.as(iid, result);
}
else
{
auto strong = g_weak.get();
return strong.as(iid, result);
}
}
HRESULT __stdcall LockServer(BOOL) noexcept final
{
return S_OK;
}
private:
winrt::guid _guid;
};
// DAA16D7F-EF66-4FC9-B6F2-3E5B6D924576
static constexpr GUID MyStringable_clsid{
0xdaa16d7f,
0xef66,
0x4fc9,
{ 0xb6, 0xf2, 0x3e, 0x5b, 0x6d, 0x92, 0x45, 0x76 }
};
// EAA16D7F-EF66-4FC9-B6F2-3E5B6D924576
static constexpr GUID ScratchStringable_clsid{
0xeaa16d7f,
0xef66,
0x4fc9,
{ 0xb6, 0xf2, 0x3e, 0x5b, 0x6d, 0x92, 0x45, 0x76 }
};
// FAA16D7F-EF66-4FC9-B6F2-3E5B6D924576
static constexpr GUID ScratchClass_clsid{
0xfaa16d7f,
0xef66,
0x4fc9,
{ 0xb6, 0xf2, 0x3e, 0x5b, 0x6d, 0x92, 0x45, 0x76 }
};
int main(int argc, char** argv)
{
auto hOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0;
GetConsoleMode(hOut, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hOut, dwMode);
printf("\x1b[90mSERVER: args:[");
if (argc > 0)
{
for (int i = 0; i < argc; i++)
{
printf("%s,", argv[i]);
}
}
printf("]\x1b[m\n");
winrt::guid guidFromCmdline{};
if (argc > 1)
{
std::string guidString{ argv[1] };
auto canConvert = guidString.length() == 38 && guidString.front() == '{' && guidString.back() == '}';
if (canConvert)
{
std::wstring wideGuidStr{ til::u8u16(guidString) };
printf("\x1b[90mSERVER: Found GUID:%ls\x1b[m\n", wideGuidStr.c_str());
GUID result{};
THROW_IF_FAILED(IIDFromString(wideGuidStr.c_str(), &result));
guidFromCmdline = result;
}
}
if (guidFromCmdline == winrt::guid{})
{
printf("did not recieve GUID, early returning.");
return -1;
}
init_apartment();
DWORD registrationHostClass{};
check_hresult(CoRegisterClassObject(guidFromCmdline,
make<HostClassFactory>(guidFromCmdline).get(),
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&registrationHostClass));
printf("%d\n", registrationHostClass);
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] { return dtored; });
// printf("\x1b[90mSERVER: Press Enter me when you're done serving.\x1b[m");
// getchar();
printf("\x1b[90mSERVER: exiting %s\n\x1b[m", argv[1]);
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.200609.3" targetFramework="native" />
</packages>

View file

@ -0,0 +1 @@
#include "pch.h"

View file

@ -0,0 +1,35 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#define BLOCK_TIL
#include <wil/cppwinrt.h>
#undef max
#undef min
#include "LibraryIncludes.h"
#include <Unknwn.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Media.h>
#include <windows.ui.xaml.media.dxinterop.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"
#include <dxgi.h>
#include <dxgi1_2.h>
#include <dxgi1_3.h>
#include <d3d11.h>
#include <d2d1.h>
#include <d2d1_1.h>
#include <d2d1_2.h>
#include <d2d1_3.h>
#include <d2d1helper.h>
#include <dwrite.h>
#include <dwrite_1.h>
#include <dwrite_2.h>
#include <dwrite_3.h>

View file

@ -0,0 +1,30 @@
========================================================================
C++/WinRT ScratchWinRTServer Project Overview
========================================================================
This project demonstrates how to get started consuming Windows Runtime
classes directly from standard C++, using platform projection headers
generated from Windows SDK metadata files.
Steps to generate and consume SDK platform projection:
1. Build project initally to generate platform projection headers into
your Generated Files folder.
2. Include a projection namespace header in your pch.h, such as
<winrt/Windows.Foundation.h>.
3. Consume winrt namespace and any Windows Runtime namespaces, such as
winrt::Windows::Foundation, from source code.
4. Initialize apartment via init_apartment() and consume winrt classes.
Steps to generate and consume a projection from third party metadata:
1. Add a WinMD reference by right-clicking the References project node
and selecting "Add Reference...". In the Add References dialog,
browse to the component WinMD you want to consume and add it.
2. Build the project once to generate projection headers for the
referenced WinMD file under the "Generated Files" subfolder.
3. As above, include projection headers in pch or source code
to consume projected Windows Runtime classes.
========================================================================
Learn more about C++/WinRT here:
http://aka.ms/cppwinrt/
========================================================================