Compare commits

...

53 commits

Author SHA1 Message Date
Dustin L. Howett e5d124df49 Migrate spelling-0.0.19 changes from main 2021-05-21 12:18:25 -05:00
Mike Griese 7fc72ca820 An enum does in fact work across the process boundary 2021-05-21 12:18:25 -05:00
Mike Griese e2ca632ac5 mosc fixes to get this in a working state again 2021-05-21 12:14:06 -05:00
Mike Griese 62ea23a96a Merge branch 'dev/migrie/oop/sample-project' into dev/migrie/oop/the-whole-thing 2021-05-20 14:49:26 -05:00
Mike Griese ede169a926 Merge branch 'dev/migrie/interactivity-projection-000' into dev/migrie/oop/sample-project 2021-05-20 14:46:33 -05:00
Mike Griese 804a114fda this one's easy too 2021-05-20 14:45:10 -05:00
Mike Griese 559d1dee75 simple nits 2021-05-20 14:38:11 -05:00
Mike Griese 8bb1afca04 Merge remote-tracking branch 'origin/dev/migrie/oop/sample-project' into dev/migrie/oop/the-whole-thing 2021-05-13 08:47:56 -05:00
Mike Griese 6cc9f37098 make spellbot happy 2021-05-13 08:33:05 -05:00
Mike Griese 4a66f61c6e Merge branch 'dev/migrie/interactivity-projection-000' into dev/migrie/oop/sample-project 2021-05-13 08:27:03 -05:00
Mike Griese ff3b808dfb this is almost exclusively nits 2021-05-13 08:25:36 -05:00
Mike Griese 6f07004f39 some consts 2021-05-13 07:39:23 -05:00
Mike Griese 59e911d569 minor typo cleanup 2021-05-13 07:29:10 -05:00
Mike Griese 4efdf39254 This fixes nvda, so nowwe just have to polish 2021-05-13 05:53:20 -05:00
Mike Griese 21a6370ec5 fix the tests 2021-05-12 13:52:32 -05:00
Mike Griese 086710aaba Merge remote-tracking branch 'origin/main' into dev/migrie/interactivity-projection-000 2021-05-12 12:26:46 -05:00
Mike Griese 160533a427 this being missing was breaking the build 2021-05-10 16:41:12 -05:00
Mike Griese 4cbc522a8d Merge branch 'dev/migrie/oop/sample-project' into dev/migrie/oop/the-whole-thing 2021-05-10 11:15:34 -05:00
Mike Griese 6e3fadda66 Some cleanup for review 2021-05-10 07:58:19 -05:00
Mike Griese 71d445b7aa Add updates to the project from dev/migrie/oop/the-whole-thing 2021-05-10 07:21:49 -05:00
Mike Griese 07c731d06f Merge branch 'dev/migrie/interactivity-projection-000' into dev/migrie/oop/sample-project 2021-05-10 06:58:36 -05:00
Mike Griese b7b23a8e7d god I knew I left these behind 2021-05-07 11:29:07 -05:00
Mike Griese e340fe95c2 Merge branch 'dev/migrie/f/oop/use-dcomp-handle' into dev/migrie/interactivity-projection-000 2021-05-07 11:25:36 -05:00
Mike Griese 12b78f5066 Merge remote-tracking branch 'origin/main' into dev/migrie/f/oop/use-dcomp-handle 2021-05-07 11:25:08 -05:00
Mike Griese dace0c4cf7 a bit more cleanup 2021-05-07 11:24:47 -05:00
Mike Griese 08694567ff Some cleanup 2021-05-07 11:16:16 -05:00
Mike Griese 47410c9efb now this works! 2021-05-07 11:08:26 -05:00
Mike Griese 6e031e5257 I want to get the padding out of interactivity, but the control bounds are still wrong 2021-05-07 10:51:55 -05:00
Mike Griese 5e7d270fa2 Merge remote-tracking branch 'origin/main' into dev/migrie/interactivity-projection-000
# Conflicts:
#	src/cascadia/TerminalControl/ControlInteractivity.cpp
#	src/cascadia/TerminalControl/ControlInteractivity.h
#	src/cascadia/TerminalControl/TermControl.cpp
#	src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp
2021-05-07 09:50:07 -05:00
Mike Griese 03fb764d58 fix accessibility 2021-05-07 05:52:12 -05:00
Mike Griese a1ce7cb077 What a ridiculous hack 2021-05-07 05:41:03 -05:00
Mike Griese 13767210c9 Merge branch 'dev/migrie/f/oop/use-dcomp-handle' into dev/migrie/interactivity-projection-000 2021-05-06 15:41:08 -05:00
Mike Griese 445bdf6cad Do the delayload dance 2021-05-06 10:00:29 -05:00
Mike Griese 7654de9c31 MIght have accidentally broke razzle.cmd here 2021-05-06 07:53:11 -05:00
Mike Griese b8dc6eed7b heyo it works 2021-05-05 15:53:23 -05:00
Mike Griese 5af0255cf1 Revert "holy fuck this fixes it in the most ridiculous way possible"
This reverts commit 4475bdf86f.

I want to leave MouseButtonState declared in ControlCore
2021-05-05 11:23:30 -05:00
Mike Griese 4475bdf86f holy fuck this fixes it in the most ridiculous way possible 2021-05-05 11:23:05 -05:00
Mike Griese 1fcef41871 THIS WORKS, if you paste M.T.Core.winmd into the appx manually 2021-05-05 10:22:37 -05:00
Mike Griese b4f842ecba wt.exe can be started as a content process; lay foundations for control to use the GUID to identify a ContentProcess 2021-05-04 14:46:04 -05:00
Mike Griese ad71df3bb7 Some polish for the sample app 2021-05-04 12:05:22 -05:00
Mike Griese 761b69208d Embed a Terminal Control in the app, whoop whoop 2021-05-04 11:55:01 -05:00
Mike Griese 92478bbd62 rename this thing 2021-05-04 10:53:57 -05:00
Mike Griese 015c8a5411 After much work, a .sln that can be used to just test XI, with MUX 2021-05-04 10:52:08 -05:00
Mike Griese 62cbf30782 it builds and runs so I guess it's done now 2021-05-03 13:24:27 -05:00
Mike Griese d667f3b633 Use the HANDLE for the swapchainin the core projection 2021-05-03 12:18:07 -05:00
Mike Griese e20caae758 Merge branch 'dev/migrie/f/oop/use-dcomp-handle' into dev/migrie/interactivity-projection-000 2021-05-03 12:04:41 -05:00
Mike Griese 2e861d8a37 some minor cleanup 2021-05-03 09:35:49 -05:00
Mike Griese 21a97b6c80 Revert "Revert "Use DComp surface handle for Swap Chain management.""
This reverts commit c113b65d9b.

That commit reverted 30b8335479
2021-05-03 09:20:06 -05:00
Mike Griese d8cc047a7e GetHoveredCell/UpdateHoveredCell. 12 remain. 2021-04-30 10:41:31 -05:00
Mike Griese 4578c136a0 some comments that should have been in the previous commit. 16 errors remain. 2021-04-30 10:20:11 -05:00
Mike Griese 42b970b7f2 Totally upend the control AutomationPeer workings
Now we have an InteractivityAutomationPeer, which acts like the implementation for TermControlAutomationPeer.

  TermControlAutomationPeer is still needed though, because it implements FrameworkElementAutomationPeer, which is needed to hook up the AP to the actual UIA tree.

  So we split up the work into two halves, the bit that should be done by the core (the ITextProvider, the IControlAccessibilityInfo), vs the stuff that needs to be in the control (FrameworkElementAutomationPeer). IUiaEventDispatcher should probably be in the control as well, but that's a problem for future us.
2021-04-30 10:11:29 -05:00
Mike Griese 400b35f814 Only 24 more errors to go 2021-04-30 06:39:29 -05:00
Mike Griese e4478eec6a Only access ControlInteractivity through the projection 2021-04-29 12:03:30 -05:00
86 changed files with 4620 additions and 357 deletions

View file

@ -1,9 +1,15 @@
Apc
apc
calt
ccmp
changelog
cybersecurity
Apc
clickable
clig
copyable
dalet
Dcs
dcs
Dcs
dialytika
dje
downside
@ -11,7 +17,10 @@ downsides
dze
dzhe
Enum'd
Fitt
formattings
ftp
fvar
geeksforgeeks
ghe
gje
@ -23,9 +32,17 @@ hyperlinks
img
It'd
kje
liga
lje
locl
lorem
Llast
Lmid
Lorigin
maxed
mkmk
mru
noreply
nje
ogonek
ok'd
@ -33,18 +50,26 @@ 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

View file

@ -2,15 +2,20 @@ ACCEPTFILES
ACCESSDENIED
alignas
alignof
APPLYTOSUBMENUS
bitfield
bitfields
BUILDBRANCH
BUILDMSG
BUILDNUMBER
BYPOSITION
charconv
CLASSNOTAVAILABLE
cmdletbinding
COLORPROPERTY
colspan
COMDLG
comparand
cstdint
CXICON
CYICON
@ -20,9 +25,11 @@ DERR
dlldata
DONTADDTORECENT
DWORDLONG
enumset
environstrings
EXPCMDFLAGS
EXPCMDSTATE
filetime
FILTERSPEC
FORCEFILESYSTEM
FORCEMINIMIZE
@ -45,6 +52,7 @@ IBind
IBox
IClass
IComparable
IComparer
IConnection
ICustom
IDialog
@ -58,6 +66,8 @@ IObject
iosfwd
IPackage
IPeasant
isspace
ISetup
IStorage
istream
IStringable
@ -65,26 +75,40 @@ 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
@ -93,6 +117,7 @@ overridable
PAGESCROLL
PICKFOLDERS
pmr
rcx
REGCLS
RETURNCMD
rfind
@ -101,41 +126,54 @@ 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
@ -144,9 +182,13 @@ xlocmes
xlocmon
xlocnum
xloctime
XMax
xmemory
XParse
xpath
xstddef
xstring
xtree
xutility
YIcon
YMax

View file

@ -7,3 +7,4 @@ Iosevka
MDL
Monofur
Segoe
wght

View file

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

View file

@ -1,5 +1,6 @@
ACLs
ADMINS
advapi
altform
altforms
appendwttlogging
@ -7,6 +8,7 @@ appx
appxbundle
appxerror
appxmanifest
ATL
backplating
bitmaps
BOMs
@ -14,6 +16,7 @@ CPLs
cpptools
cppvsdbg
CPRs
cryptbase
DACL
DACLs
diffs
@ -23,14 +26,20 @@ DTDs
DWINRT
enablewttlogging
Intelli
IVisual
LKG
LOCKFILE
Lxss
mfcribbon
microsoft
microsoftonline
MSAA
msixbundle
MSVC
muxc
netcore
osgvsowi
PFILETIME
pgc
pgo
pgosweep
@ -38,10 +47,14 @@ powerrename
powershell
propkey
pscustomobject
QWORD
regedit
robocopy
SACLs
sdkddkver
Shobjidl
Skype
SRW
sxs
Sysinternals
sysnative
@ -56,6 +69,7 @@ Virtualization
visualstudio
vscode
VSTHRD
winsdkver
wlk
wslpath
wtl

View file

@ -31,6 +31,7 @@ Kourosh
kowalczyk
leonmsft
Lepilleur
lhecker
lukesampson
Manandhar
mbadolato
@ -52,6 +53,7 @@ oldnewthing
opengl
osgwiki
pabhojwa
panos
paulcam
pauldotknopf
PGP
@ -66,6 +68,7 @@ sonpham
stakx
thereses
Walisch
Wellons
Wirt
Wojciech
zadjii

View file

@ -2,10 +2,7 @@ AAAa
AAAAA
AAAAAAAAAAAAA
AAAAAABBBBBBCCC
AAAAABBBBBBBCCC
AAAAABBBBBBCCC
AAAAABCCCCCCCCC
AAAAADCCCCCCCCC
abcd
abcd
abcde
@ -27,6 +24,7 @@ BBBBBBBBBBBBBBDDDD
BBBBBCCC
BBBBCCCCC
BBGGRR
CCE
EFG
EFGh
QQQQQQQQQQABCDEFGHIJ

View file

@ -14,7 +14,6 @@ ACTIVEBORDER
ACTIVECAPTION
adaa
ADDALIAS
ADDB
ADDREF
addressof
ADDSTRING
@ -50,6 +49,7 @@ APARTMENTTHREADED
APCs
api
APIENTRY
apimswincoresynchl
apiset
APPBARDATA
appconsult
@ -105,6 +105,7 @@ autoscrolling
Autowrap
AVerify
AVI
AVX
awch
azuredevopspodcast
azzle
@ -114,6 +115,7 @@ Backgrounder
backgrounding
backport
backstory
barbaz
Batang
baz
Bazz
@ -163,9 +165,11 @@ BPBF
bpp
BPPF
branchconfig
brandings
BRK
Browsable
bsearch
Bspace
bstr
BTNFACE
buf
@ -183,12 +187,13 @@ bytebuffer
cac
cacafire
callee
cang
capslock
CARETBLINKINGENABLED
carlos
CARRIAGERETURN
cascadia
cassert
castsi
catid
cazamor
CBash
@ -267,9 +272,12 @@ cmder
CMDEXT
Cmdlet
cmdline
cmh
CMOUSEBUTTONS
cmp
cmpeq
cmt
cmw
cmyk
CNL
cnt
@ -379,6 +387,7 @@ cplusplus
cpp
CPPCORECHECK
cppcorecheckrules
cppm
cpprest
cpprestsdk
cppwinrt
@ -401,11 +410,13 @@ csbiex
csharp
CSHORT
CSIDL
Cspace
csproj
Csr
csrmsg
CSRSS
csrutil
css
cstdarg
cstddef
cstdio
@ -496,7 +507,7 @@ DEADCHAR
dealloc
Debian
debolden
debounce
debugtype
DECALN
DECANM
DECAUPSS
@ -504,6 +515,8 @@ DECAWM
DECCKM
DECCOLM
DECDHL
decdld
DECDLD
DECDWL
DECEKBD
DECID
@ -524,6 +537,7 @@ DECRC
DECREQTPARM
DECRLM
DECRQM
DECRQSS
DECRST
DECSASD
DECSC
@ -544,6 +558,7 @@ DECSTR
DECSWL
DECTCEM
Dedupe
deduplicate
deduplicated
DEFAPP
DEFAULTBACKGROUND
@ -653,6 +668,7 @@ dwriteglyphrundescriptionclustermap
dxgi
dxgidwm
dxinterop
dxsm
dxttbmp
eachother
eae
@ -756,7 +772,6 @@ filepath
FILESUBTYPE
FILESYSPATH
filesystem
FILETIME
FILETYPE
fileurl
FILEW
@ -772,11 +787,13 @@ FINDSTRINGEXACT
FINDUP
FIter
FIXEDCONVERTED
FIXEDFILEINFO
Flg
flyout
fmodern
fmtarg
fmtid
FNV
FOLDERID
FONTCHANGE
fontdlg
@ -785,6 +802,7 @@ FONTENUMPROC
FONTFACE
FONTFAMILY
FONTHEIGHT
FONTINFO
fontlist
FONTOK
FONTSIZE
@ -794,6 +812,7 @@ FONTTYPE
FONTWEIGHT
FONTWIDTH
FONTWINDOW
fooo
forceinline
FORCEOFFFEEDBACK
FORCEONFEEDBACK
@ -897,6 +916,7 @@ github
gitlab
gle
globals
GLYPHENTRY
gmail
GMEM
GNUC
@ -945,6 +965,7 @@ hdrstop
HEIGHTSCROLL
hfile
hfont
hfontresource
hglobal
hhh
HHmm
@ -980,7 +1001,7 @@ hostlib
Hostx
HPA
HPAINTBUFFER
hpcon
HPCON
hpj
hpp
HPR
@ -1019,6 +1040,7 @@ IAction
IApi
IApplication
IBase
ICache
icacls
iccex
icch
@ -1112,6 +1134,7 @@ interop
interoperability
inthread
intptr
intrin
intsafe
INVALIDARG
INVALIDATERECT
@ -1164,6 +1187,7 @@ IWin
IWindow
IXaml
IXMP
ixx
jconcpp
JOBOBJECT
JOBOBJECTINFOCLASS
@ -1208,6 +1232,7 @@ KLF
KLMNO
KLMNOPQRST
KLMNOPQRSTQQQQQ
KPRIORITY
KVM
langid
LANGUAGELIST
@ -1256,6 +1281,7 @@ lnkd
lnkfile
LNM
LOADONCALL
loadu
LOBYTE
localappdata
localhost
@ -1263,6 +1289,7 @@ locsrc
locstudio
Loewen
LOGFONT
LOGFONTA
LOGFONTW
logissue
lowercased
@ -1367,7 +1394,6 @@ MEASUREITEM
megamix
memallocator
memcmp
memcopy
memcpy
memmove
memset
@ -1417,6 +1443,7 @@ MOUSEFIRST
MOUSEHWHEEL
MOUSEMOVE
mousewheel
movemask
MOVESTART
msb
msbuild
@ -1443,11 +1470,13 @@ MSVCRTD
MSVS
msys
msysgit
MTSM
mui
Mul
multiline
munged
munges
murmurhash
mutex
mutexes
muxes
@ -1498,6 +1527,7 @@ nfe
nlength
Nls
NLSMODE
nnn
NOACTIVATE
NOAPPLYNOW
NOCLIP
@ -1578,6 +1608,7 @@ NTVDM
ntverp
NTWIN
nuget
nullability
nullness
nullonfailure
nullopt
@ -1612,6 +1643,7 @@ onecoreuapuuid
onecoreuuid
ONECOREWINDOWS
onehalf
oneseq
ONLCR
openbash
opencode
@ -1642,6 +1674,7 @@ oss
ostream
ostringstream
ouicompat
OUnter
outdir
outfile
Outof
@ -1652,6 +1685,7 @@ Outptr
OVERLAPPEDWINDOW
OWNDC
OWNERDRAWFIXED
packagename
packageuwp
PACKCOORD
PACKVERSION
@ -1676,6 +1710,7 @@ pcch
PCCHAR
PCCONSOLE
PCD
pcg
pch
PCHAR
PCIDLIST
@ -1771,6 +1806,7 @@ POSX
POSXSCROLL
POSYSCROLL
ppci
PPEB
ppf
ppguid
ppidl
@ -1849,7 +1885,6 @@ psp
PSPCB
psr
PSTR
psuedoconsole
psz
ptch
ptr
@ -1922,6 +1957,7 @@ realloc
reamapping
rects
redef
redefinable
Redir
redirector
redist
@ -1943,7 +1979,7 @@ REGSTR
reingest
Relayout
RELBINPATH
Remoting
remoting
renamer
renderengine
rendersize
@ -1964,11 +2000,12 @@ resx
retval
rfa
rfc
rfid
rftp
rgb
rgba
RGBCOLOR
rgbi
rgch
rgci
rgfae
rgfte
@ -1985,9 +2022,11 @@ rhs
RIGHTALIGN
RIGHTBUTTON
riid
Rike
RIPMSG
RIS
RMENU
rng
roadmap
robomac
roundtrip
@ -2033,7 +2072,6 @@ scanline
schemename
SCL
scm
scprintf
SCRBUF
SCRBUFSIZE
screenbuffer
@ -2044,8 +2082,6 @@ scriptload
Scrollable
scrollback
scrollbar
Scrolldown
Scrolldownpage
Scroller
SCROLLFORWARD
SCROLLINFO
@ -2053,8 +2089,6 @@ scrolllock
scrolloffset
SCROLLSCALE
SCROLLSCREENBUFFER
Scrollup
Scrolluppage
scursor
sddl
sdeleted
@ -2069,6 +2103,7 @@ selectany
SELECTEDFONT
SELECTSTRING
Selfhosters
SERIALIZERS
SERVERDLL
SETACTIVE
SETBUDDYINT
@ -2140,6 +2175,7 @@ SIGDN
SINGLEFLAG
SINGLETHREADED
siup
sixel
SIZEBOX
sizeof
SIZESCROLL
@ -2211,6 +2247,7 @@ stoi
stol
stoul
stoutapot
Stri
strikethrough
stringstream
STRINGTABLE
@ -2243,6 +2280,7 @@ SWMR
SWP
swprintf
SYMED
symlink
SYNCPAINT
sys
syscalls
@ -2309,7 +2347,6 @@ testmddefinition
testmode
testname
testnameprefix
testnetv
TESTNULL
testpass
testpasses
@ -2345,7 +2382,6 @@ TITLEISLINKNAME
TJson
TLambda
TLEN
Tlg
Tlgdata
TMAE
TMPF
@ -2420,7 +2456,6 @@ uapadmin
UAX
ubuntu
ucd
ucd
ucdxml
uch
UCHAR
@ -2529,6 +2564,7 @@ vcvarsall
vcxitems
vcxproj
vec
vectorized
VERCTRL
versioning
VERTBAR
@ -2546,13 +2582,13 @@ VMs
VPA
VPATH
VPR
VPrintf
VProc
VRaw
VREDRAW
vsc
vscprintf
VSCROLL
vsdevshell
vsinfo
vsnprintf
vso
@ -2661,6 +2697,7 @@ WINDOWPOSCHANGING
windowproc
windowrect
windowsapp
windowsdeveloper
windowsinternalstring
WINDOWSIZE
windowsx
@ -2692,6 +2729,7 @@ wixproj
wline
wlinestream
wmain
wmemory
WMSZ
wnd
WNDALLOC
@ -2747,6 +2785,7 @@ WTo
wtof
wtoi
WTs
WTSOFTFONT
wtw
wtypes
Wubi
@ -2773,10 +2812,10 @@ XCount
xdy
XEncoding
xes
Xes
xff
XFile
XFORM
xIcon
XManifest
XMath
XMFLOAT
@ -2784,8 +2823,6 @@ xml
xmlns
xor
xorg
xorg
Xpath
XPosition
XResource
xsd
@ -2811,6 +2848,7 @@ YCast
YCENTER
YCount
YDPI
yIcon
yml
YOffset
YPosition
@ -2818,6 +2856,7 @@ YSize
YSubstantial
YVIRTUALSCREEN
YWalk
zamora
ZCmd
ZCtrl
zsh

View file

@ -1,5 +1,7 @@
http
www
easyrgb
php
ecma
rapidtables
WCAG
@ -11,6 +13,7 @@ leonerd
fixterms
winui
appshellintegration
mdtauk
cppreference
gfycat
Guake

View file

@ -23,3 +23,5 @@ VERIFY_ARE_EQUAL\(L"[^"]+"
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
std::memory_order_[\w]+
D2DERR_SHADER_COMPILE_FAILED
TIL_FEATURE_[0-9A-Z_]+
vcvars\w*

View file

@ -1,19 +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:
build:
spelling:
name: Spell checking
runs-on: ubuntu-latest
steps:
- name: checkout-merge
if: "contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2.0.0
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.0.0
- uses: check-spelling/check-spelling@v0.0.18
uses: actions/checkout@v2
- uses: check-spelling/check-spelling@v0.0.19

221
Samples.sln Normal file
View file

@ -0,0 +1,221 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134
MinimumVisualStudioVersion = 10.0.40219.1
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Package", "samples\ScratchIslandApp\Package\Package.wapproj", "{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleAppLib", "samples\ScratchIslandApp\SampleApp\SampleAppLib.vcxproj", "{A4394404-37F7-41C1-802B-49788D3720E3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleApp", "samples\ScratchIslandApp\SampleApp\dll\SampleApp.vcxproj", "{26C51792-41A3-4FE0-AB5E-8B69D557BF91}"
ProjectSection(ProjectDependencies) = postProject
{A4394404-37F7-41C1-802B-49788D3720E3} = {A4394404-37F7-41C1-802B-49788D3720E3}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowExe", "samples\ScratchIslandApp\WindowExe\WindowExe.vcxproj", "{B4427499-9FDE-4208-B456-5BC580637633}"
ProjectSection(ProjectDependencies) = postProject
{26C51792-41A3-4FE0-AB5E-8B69D557BF91} = {26C51792-41A3-4FE0-AB5E-8B69D557BF91}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common Props", "Common Props", "{53DD5520-E64C-4C06-B472-7CE62CA539C9}"
ProjectSection(SolutionItems) = preProject
src\common.build.post.props = src\common.build.post.props
src\common.build.pre.props = src\common.build.pre.props
src\common.build.tests.props = src\common.build.tests.props
common.openconsole.props = common.openconsole.props
src\cppwinrt.build.post.props = src\cppwinrt.build.post.props
src\cppwinrt.build.pre.props = src\cppwinrt.build.pre.props
src\wap-common.build.post.props = src\wap-common.build.post.props
src\wap-common.build.pre.props = src\wap-common.build.pre.props
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxproj", "{6BAE5851-50D5-4934-8D5E-30361A8A40F3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types", "src\types\lib\types.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820263}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|ARM64 = AuditMode|ARM64
AuditMode|x64 = AuditMode|x64
AuditMode|x86 = AuditMode|x86
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Fuzzing|ARM64 = Fuzzing|ARM64
Fuzzing|x64 = Fuzzing|x64
Fuzzing|x86 = Fuzzing|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.ActiveCfg = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Build.0 = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Deploy.0 = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.ActiveCfg = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Build.0 = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Deploy.0 = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.ActiveCfg = Release|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Build.0 = Release|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Deploy.0 = Release|x86
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.ActiveCfg = AuditMode|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.Build.0 = AuditMode|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.Build.0 = AuditMode|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.Build.0 = Debug|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.ActiveCfg = Debug|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.Build.0 = Debug|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.ActiveCfg = Debug|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.Build.0 = Debug|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.Build.0 = Fuzzing|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.ActiveCfg = Release|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.Build.0 = Release|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.ActiveCfg = Release|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.Build.0 = Release|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.ActiveCfg = Release|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.Build.0 = Release|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.ActiveCfg = AuditMode|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.Build.0 = AuditMode|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.Build.0 = AuditMode|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.ActiveCfg = Debug|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.Build.0 = Debug|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.ActiveCfg = Debug|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.Build.0 = Debug|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.ActiveCfg = Debug|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.Build.0 = Debug|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.Build.0 = Fuzzing|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.ActiveCfg = Release|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.Build.0 = Release|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.ActiveCfg = Release|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.Build.0 = Release|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.ActiveCfg = Release|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.Build.0 = Release|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.ActiveCfg = AuditMode|x64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.Build.0 = AuditMode|x64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.Build.0 = AuditMode|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.Build.0 = Debug|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.ActiveCfg = Debug|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.Build.0 = Debug|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.ActiveCfg = Debug|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.Build.0 = Debug|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.Build.0 = Fuzzing|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.ActiveCfg = Release|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.Build.0 = Release|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.ActiveCfg = Release|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.Build.0 = Release|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.ActiveCfg = Release|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.Build.0 = Release|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.ActiveCfg = AuditMode|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.Build.0 = AuditMode|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.Build.0 = AuditMode|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.ActiveCfg = Debug|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.Build.0 = Debug|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.ActiveCfg = Debug|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.Build.0 = Debug|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.ActiveCfg = Debug|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.Build.0 = Debug|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.Build.0 = Fuzzing|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.ActiveCfg = Release|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.Build.0 = Release|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.ActiveCfg = Release|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.Build.0 = Release|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.ActiveCfg = Release|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.Build.0 = Release|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.ActiveCfg = AuditMode|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.Build.0 = AuditMode|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.Build.0 = AuditMode|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.ActiveCfg = Debug|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.Build.0 = Debug|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.ActiveCfg = Debug|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.Build.0 = Debug|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.ActiveCfg = Debug|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.Build.0 = Debug|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.Build.0 = Fuzzing|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.ActiveCfg = Release|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.Build.0 = Release|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.ActiveCfg = Release|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.Build.0 = Release|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.ActiveCfg = Release|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
{18D09A24-8240-42D6-8CB6-236EEE820263} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {05EAE315-9188-4D7B-B889-7D5F480A8915}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap uap3">
<Identity
Name="ScratchApplication"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Version="1.0.0.0" />
<Properties>
<DisplayName>Sample App</DisplayName>
<PublisherDisplayName>A Lone Developer</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.18362.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="ms-resource:AppName"
Description="ms-resource:AppDescription"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile
Wide310x150Logo="Images\Wide310x150Logo.png"
Square71x71Logo="Images\SmallTile.png"
Square310x310Logo="Images\LargeTile.png"
ShortName="ms-resource:AppShortName">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo"/>
<uap:ShowOn Tile="wide310x150Logo"/>
<uap:ShowOn Tile="square310x310Logo"/>
</uap:ShowNameOnTiles>
</uap:DefaultTile>
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

View file

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.pre.props" />
<PropertyGroup Label="Configuration">
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion>
<!--
These two properties are very important!
Without them, msbuild will stomp MinVersion and MaxVersionTested in the
Package.appxmanifest and replace them with whatever our values for
TargetPlatformMinVersion and TargetPlatformVersion are.
-->
<AppxOSMinVersionReplaceManifestVersion>false</AppxOSMinVersionReplaceManifestVersion>
<AppxOSMaxVersionTestedReplaceManifestVersion>false</AppxOSMaxVersionTestedReplaceManifestVersion>
</PropertyGroup>
<PropertyGroup>
<ProjectGuid>cf31505e-3bae-4c0a-81d7-f1eb279f40bb</ProjectGuid>
<EntryPointProjectUniqueName>..\WindowExe\WindowExe.vcxproj</EntryPointProjectUniqueName>
<DebuggerType>NativeOnly</DebuggerType>
</PropertyGroup>
<PropertyGroup Condition="!Exists('Package_TemporaryKey.pfx')">
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
<AppxBundle>Never</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="Exists('Package_TemporaryKey.pfx')">
<AppxPackageSigningEnabled>true</AppxPackageSigningEnabled>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<PackageCertificateKeyFile>Package_TemporaryKey.pfx</PackageCertificateKeyFile>
</PropertyGroup>
<ItemGroup Condition="Exists('Package_TemporaryKey.pfx')">
<None Include="Package_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<!-- Resources -->
<!-- This resw only defines things that are used in this package's AppxManifest,
so it's not in the common resource items. -->
<PRIResource Include="Resources\en-US\Resources.resw" />
<PRIResource Include="Resources\Resources.resw" />
<OCResourceDirectory Include="Resources" />
</ItemGroup>
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
<ItemGroup>
<ProjectReference Include="..\WindowExe\WindowExe.vcxproj" />
<!-- <ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj" /> -->
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)TerminalConnection\TerminalConnection.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">
<ItemGroup>
<!-- Stomp all "SourceProject" values for all incoming dependencies to flatten the package. -->
<_TemporaryFilteredWapProjOutput Include="@(_FilteredNonWapProjProjectOutput)" />
<_FilteredNonWapProjProjectOutput Remove="@(_TemporaryFilteredWapProjOutput)" />
<_FilteredNonWapProjProjectOutput Include="@(_TemporaryFilteredWapProjOutput)">
<!-- Blank the SourceProject here to vend all files into the root of the package. -->
<SourceProject>
</SourceProject>
</_FilteredNonWapProjProjectOutput>
</ItemGroup>
</Target>
<!-- Move all the PRI files that would be packaged into the appx into _PriFile so that
GenerateProjectPriFile catches them. This requires us to move payload collection
up before GenerateProjectPriFile, when it is typically _after_ it (because the
DesktopBridge project type is built to only prepare the payload during appx manifest
generation.
Since PRI file generation is _before_ manifest generation (for possibly obvious or
important reasons), that doesn't work for us.
-->
<PropertyGroup>
<!-- Only for MSBuild versions < 16.3.0 -->
<_GenerateProjectPriFileDependsOn Condition="$(MSBuildVersion) &lt; '16.3.0'">OpenConsoleLiftDesktopBridgePriFiles;$(_GenerateProjectPriFileDependsOn)</_GenerateProjectPriFileDependsOn>
</PropertyGroup>
<Target Name="OpenConsoleLiftDesktopBridgePriFiles" DependsOnTargets="_ConvertItems">
<ItemGroup>
<_PriFile Include="@(_NonWapProjProjectOutput)" Condition="'%(Extension)' == '.pri'" />
<!-- Remove all other .pri files from the appx payload. -->
<AppxPackagePayload Remove="@(AppxPackagePayload)" Condition="'%(Extension)' == '.pri'" />
</ItemGroup>
</Target>
<!-- VS 16.3.0 added a rule to the WAP packaging project that removes all non-WAP payload, which we were relying on to
roll up our subproject resources. We have to suppress that rule but keep part of its logic, because that rule is
where the AppxPackagePayload items are created. -->
<PropertyGroup>
<WapProjBeforeGenerateAppxManifestDependsOn>
$([MSBuild]::Unescape('$(WapProjBeforeGenerateAppxManifestDependsOn.Replace('_RemoveAllNonWapUWPItems', '_OpenConsoleRemoveAllNonWapUWPItems'))'))
</WapProjBeforeGenerateAppxManifestDependsOn>
</PropertyGroup>
<Target Name="_OpenConsoleRemoveAllNonWapUWPItems">
<ItemGroup>
<AppxPackagePayload Include="@(WapProjPackageFile)" />
<AppxUploadPackagePayload Include="@(UploadWapProjPackageFile)" />
<!-- 16.3.0 - remove non-resources.pri PRI files since we just forced them back in. -->
<AppxPackagePayload Remove="@(AppxPackagePayload)" Condition="'%(Extension)' == '.pri' and '%(Filename)' != 'resources'" />
<AppxUploadPackagePayload Remove="@(AppxUploadPackagePayload)" Condition="'%(Extension)' == '.pri' and '%(Filename)' != 'resources'" />
</ItemGroup>
</Target>
<!-- **BEGIN VC LIBS HACK** -->
<!--
For our release builds, we're just going to integrate the UWPDesktop CRT into our package and delete the package dependencies.
It's very difficult for users who do not have access to the store to get our dependency packages, and we want to be robust
and deployable everywhere. Since these libraries can be redistributed, it's easiest if we simply redistribute them.
See also the "VC LIBS HACK" section in WindowsTerminal.vcxproj.
-->
<!-- This target removes the FrameworkSdkReferences from before the AppX package targets manifest generation happens.
This is part of the generic machinery that applies to every AppX. -->
<Target Name="_OpenConsoleStripAllDependenciesFromPackageFirstManifest" BeforeTargets="_GenerateCurrentProjectAppxManifest">
<ItemGroup Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
<FrameworkSdkReference Remove="@(FrameworkSdkReference)" />
</ItemGroup>
</Target>
<!-- This target removes the FrameworkSdkPackages from before the *desktop bridge* manifest generation happens. -->
<Target Name="_OpenConsoleStripAllDependenciesFromPackageSecondManifest" BeforeTargets="_GenerateDesktopBridgeAppxManifest" DependsOnTargets="_ResolveVCLibDependencies">
<ItemGroup Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
<FrameworkSdkPackage Remove="@(FrameworkSdkPackage)" />
</ItemGroup>
</Target>
<!-- **END VC LIBS HACK** -->
<!-- This is required to get the package dependency in the AppXManifest. -->
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppName" xml:space="preserve">
<value>Scratch XAML Island App</value>
</data>
<data name="AppShortName" xml:space="preserve">
<value>Scratch App</value>
</data>
</root>

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDescription" xml:space="preserve">
<value>A scratch app for XAML Islands tests</value>
</data>
</root>

View file

@ -0,0 +1,40 @@
#pragma once
namespace winrt::SampleApp::implementation
{
template<typename D, typename... I>
struct App_baseWithProvider : public App_base<D, ::winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider>
{
using IXamlType = ::winrt::Windows::UI::Xaml::Markup::IXamlType;
IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const& type)
{
return AppProvider()->GetXamlType(type);
}
IXamlType GetXamlType(::winrt::hstring const& fullName)
{
return AppProvider()->GetXamlType(fullName);
}
::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
{
return AppProvider()->GetXmlnsDefinitions();
}
private:
bool _contentLoaded{ false };
std::shared_ptr<XamlMetaDataProvider> _appProvider;
std::shared_ptr<XamlMetaDataProvider> AppProvider()
{
if (!_appProvider)
{
_appProvider = std::make_shared<XamlMetaDataProvider>();
}
return _appProvider;
}
};
template<typename D, typename... I>
using AppT2 = App_baseWithProvider<D, I...>;
}

View file

@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "App.h"
#include "App.g.cpp"
using namespace winrt;
using namespace winrt::Windows::ApplicationModel::Activation;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Navigation;
namespace winrt::SampleApp::implementation
{
App::App()
{
// This is the same trick that Initialize() is about to use to figure out whether we're coming
// from a UWP context or from a Win32 context
// See https://github.com/windows-toolkit/Microsoft.Toolkit.Win32/blob/52611c57d89554f357f281d0c79036426a7d9257/Microsoft.Toolkit.Win32.UI.XamlApplication/XamlApplication.cpp#L42
const auto dispatcherQueue = ::winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
if (dispatcherQueue)
{
_isUwp = true;
}
Initialize();
// Disable XAML's automatic backplating of text when in High Contrast
// mode: we want full control of and responsibility for the foreground
// and background colors that we draw in XAML.
HighContrastAdjustment(::winrt::Windows::UI::Xaml::ApplicationHighContrastAdjustment::None);
}
SampleAppLogic App::Logic()
{
static SampleAppLogic logic;
return logic;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
void App::OnLaunched(LaunchActivatedEventArgs const& /*e*/)
{
// if this is a UWP... it means its our problem to hook up the content to the window here.
if (_isUwp)
{
auto content = Window::Current().Content();
if (content == nullptr)
{
auto logic = Logic();
logic.Create();
auto page = logic.GetRoot().as<MyPage>();
Window::Current().Content(page);
Window::Current().Activate();
}
}
}
}

View file

@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "App.g.h"
#include "App.base.h"
namespace winrt::SampleApp::implementation
{
struct App : AppT2<App>
{
public:
App();
void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&);
SampleApp::SampleAppLogic Logic();
private:
bool _isUwp = false;
};
}
namespace winrt::SampleApp::factory_implementation
{
struct App : AppT<App, implementation::App>
{
};
}

View file

@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "SampleAppLogic.idl";
namespace SampleApp
{
// ADD ARBITRARY APP LOGIC TO SampleAppLogic.idl, NOT HERE.
// This is for XAML platform setup only.
[default_interface] runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
{
App();
SampleAppLogic Logic { get; };
}
}

View file

@ -0,0 +1,71 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Toolkit:XamlApplication x:Class="SampleApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TA="using:SampleApp"
xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:SampleApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<!--
If you want to prove this works, then add `RequestedTheme="Light"` to
the properties on the XamlApplication
-->
<Toolkit:XamlApplication.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Include the MUX Controls resources -->
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary>
<!--
We're going to apply this style to the root Grid acting
as the tab row, because we need to be able to set its
`Background` property to "{ThemeResource
ApplicationPageBackgroundThemeBrush}" so it will be colored
appropriately for the theme, regardless of what we set the
RequestedTheme to
-->
<Style x:Name="BackgroundGridThemeStyle"
TargetType="Grid">
<Setter Property="Background" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
</Style>
<!--
We need to manually create the error text brush as a
theme-dependent brush. SystemControlErrorTextForegroundBrush
is unfortunately static.
-->
<SolidColorBrush x:Name="ErrorTextBrush"
Color="{ThemeResource SystemErrorTextColor}" />
<!-- Suppress top padding -->
<Thickness x:Key="TabViewHeaderPadding">8,0,8,0</Thickness>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<!-- Define resources for Dark mode here -->
<SolidColorBrush x:Key="TabViewBackground"
Color="#FF333333" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<!-- Define resources for Light mode here -->
<SolidColorBrush x:Key="TabViewBackground"
Color="#FFCCCCCC" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Toolkit:XamlApplication.Resources>
</Toolkit:XamlApplication>

View file

@ -0,0 +1,190 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "MyPage.h"
#include "MySettings.h"
#include <LibraryResources.h>
#include "MyPage.g.cpp"
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
#include "..\..\..\src\types\inc\utils.hpp"
using namespace std::chrono_literals;
using namespace winrt::Microsoft::Terminal;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
namespace WUX = Windows::UI::Xaml;
using IInspectable = Windows::Foundation::IInspectable;
}
namespace winrt::SampleApp::implementation
{
MyPage::MyPage()
{
InitializeComponent();
}
void MyPage::Create()
{
TerminalConnection::EchoConnection conn{};
auto settings = winrt::make_self<ControlUnitTests::MockControlSettings>();
Control::TermControl control{ *settings, conn };
InProcContent().Children().Append(control);
// Once the control loads (and not before that), write some text for debugging:
control.Initialized([conn](auto&&, auto&&) {
conn.WriteInput(L"This TermControl is hosted in-proc...");
});
}
static wil::unique_process_information _createHostClassProcess(const winrt::guid& g)
{
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(g) };
std::wstring commandline{ fmt::format(L"windowsterminal.exe --content {}", 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(2000);
// 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::fire_and_forget MyPage::CreateClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs)
{
auto guidString = GuidInput().Text();
// Capture calling context.
winrt::apartment_context ui_thread;
co_await winrt::resume_background();
auto canConvert = guidString.size() == 38 && guidString.front() == '{' && guidString.back() == '}';
bool attached = false;
winrt::guid contentGuid{ ::Microsoft::Console::Utils::CreateGuid() };
if (canConvert)
{
GUID result{};
if (SUCCEEDED(IIDFromString(guidString.c_str(), &result)))
{
contentGuid = result;
attached = true;
}
}
if (!attached)
{
// 2. Spawn a Server.exe, with the guid on the commandline
auto piContent{ std::move(_createHostClassProcess(contentGuid)) };
}
Control::ContentProcess content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
TerminalConnection::ITerminalConnection conn{ nullptr };
Control::IControlSettings settings{ nullptr };
settings = *winrt::make_self<implementation::MySettings>();
if (!attached)
{
conn = TerminalConnection::EchoConnection{};
// settings = *winrt::make_self<implementation::MySettings>();
content.Initialize(settings, conn);
}
// Switch back to the UI thread.
co_await ui_thread;
Control::TermControl control{ contentGuid, settings, conn };
OutOfProcContent().Children().Append(control);
if (!attached)
{
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(contentGuid) };
GuidInput().Text(guidStr);
}
}
/*winrt::fire_and_forget MyPage::_attachToContent(winrt::guid contentGuid)
{
Control::ContentProcess content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
}*/
winrt::fire_and_forget MyPage::CreateOutOfProcTerminal()
{
// 1. Generate a GUID.
winrt::guid contentGuid{ ::Microsoft::Console::Utils::CreateGuid() };
// Capture calling context.
winrt::apartment_context ui_thread;
co_await winrt::resume_background();
// 2. Spawn a Server.exe, with the guid on the commandline
auto piContent{ std::move(_createHostClassProcess(contentGuid)) };
Control::ContentProcess content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
TerminalConnection::EchoConnection conn{};
auto settings = winrt::make_self<implementation::MySettings>();
Control::IControlSettings s = *settings;
if (s)
{
content.Initialize(s, conn);
// Switch back to the UI thread.
co_await ui_thread;
Control::TermControl control{ contentGuid, s, conn };
OutOfProcContent().Children().Append(control);
}
}
// Method Description:
// - Gets the title of the currently focused terminal control. If there
// isn't a control selected for any reason, returns "Windows Terminal"
// Arguments:
// - <none>
// Return Value:
// - the title of the focused control if there is one, else "Windows Terminal"
hstring MyPage::Title()
{
return { L"Sample Application" };
}
}

View file

@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "MyPage.g.h"
#include "../../../src/cascadia/inc/cppwinrt_utils.h"
namespace winrt::SampleApp::implementation
{
struct MyPage : MyPageT<MyPage>
{
public:
MyPage();
void Create();
hstring Title();
winrt::fire_and_forget CreateOutOfProcTerminal();
winrt::fire_and_forget CreateClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
// winrt::fire_and_forget _attachToContent(winrt::guid contentGuid);
private:
friend struct MyPageT<MyPage>; // for Xaml to bind events
};
}
namespace winrt::SampleApp::factory_implementation
{
BASIC_FACTORY(MyPage);
}

View file

@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace SampleApp
{
[default_interface] runtimeclass MyPage : Windows.UI.Xaml.Controls.Page
{
MyPage();
}
}

View file

@ -0,0 +1,61 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Page x:Class="SampleApp.MyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:SampleApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
xmlns:terminal="using:Microsoft.Terminal.Control"
mc:Ignorable="d">
<Grid x:Name="Root"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="GuidInput"
Width="400"
PlaceholderText="{}{guid here}" />
<Button x:Name="CreateOopControl"
Grid.Row="0"
Tapped="CreateClicked">
Create
</Button>
</StackPanel>
<Grid x:Name="TabContent"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid x:Name="InProcContent"
Grid.Column="0"
Padding="16"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#ff0000" />
<Grid x:Name="OutOfProcContent"
Grid.Column="1"
Padding="16"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#0000ff" />
</Grid>
</Grid>
</Page>

View file

@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "MySettings.h"
#include "MySettings.g.cpp"
namespace winrt::SampleApp::implementation
{
}

View file

@ -0,0 +1,97 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
--*/
#pragma once
#include "../../inc/cppwinrt_utils.h"
#include <DefaultSettings.h>
#include <conattrs.hpp>
#include "MySettings.g.h"
namespace winrt::SampleApp::implementation
{
struct MySettings : MySettingsT<MySettings>
{
public:
MySettings() = default;
// --------------------------- Core Settings ---------------------------
// All of these settings are defined in ICoreSettings.
WINRT_PROPERTY(til::color, DefaultForeground, DEFAULT_FOREGROUND);
WINRT_PROPERTY(til::color, DefaultBackground, DEFAULT_BACKGROUND);
WINRT_PROPERTY(til::color, SelectionBackground, DEFAULT_FOREGROUND);
WINRT_PROPERTY(int32_t, HistorySize, DEFAULT_HISTORY_SIZE);
WINRT_PROPERTY(int32_t, InitialRows, 30);
WINRT_PROPERTY(int32_t, InitialCols, 80);
WINRT_PROPERTY(bool, SnapOnInput, true);
WINRT_PROPERTY(bool, AltGrAliasing, true);
WINRT_PROPERTY(til::color, CursorColor, DEFAULT_CURSOR_COLOR);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Core::CursorStyle, CursorShape, winrt::Microsoft::Terminal::Core::CursorStyle::Vintage);
WINRT_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
WINRT_PROPERTY(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
WINRT_PROPERTY(bool, CopyOnSelect, false);
WINRT_PROPERTY(bool, InputServiceWarning, true);
WINRT_PROPERTY(bool, FocusFollowMouse, false);
WINRT_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, TabColor, nullptr);
WINRT_PROPERTY(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>, StartingTabColor, nullptr);
winrt::Microsoft::Terminal::Core::ICoreAppearance UnfocusedAppearance() { return {}; };
WINRT_PROPERTY(bool, TrimBlockSelection, false);
// ------------------------ End of Core Settings -----------------------
WINRT_PROPERTY(winrt::hstring, ProfileName);
WINRT_PROPERTY(bool, UseAcrylic, false);
WINRT_PROPERTY(double, TintOpacity, 0.5);
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas");
WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE);
WINRT_PROPERTY(winrt::Windows::UI::Text::FontWeight, FontWeight);
WINRT_PROPERTY(winrt::hstring, BackgroundImage);
WINRT_PROPERTY(double, BackgroundImageOpacity, 1.0);
WINRT_PROPERTY(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill);
WINRT_PROPERTY(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center);
WINRT_PROPERTY(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::IKeyBindings, KeyBindings, nullptr);
WINRT_PROPERTY(winrt::hstring, Commandline);
WINRT_PROPERTY(winrt::hstring, StartingDirectory);
WINRT_PROPERTY(winrt::hstring, StartingTitle);
WINRT_PROPERTY(bool, SuppressApplicationTitle);
WINRT_PROPERTY(winrt::hstring, EnvironmentVariables);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible);
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
WINRT_PROPERTY(bool, RetroTerminalEffect, false);
WINRT_PROPERTY(bool, ForceFullRepaintRendering, false);
WINRT_PROPERTY(bool, SoftwareRendering, false);
WINRT_PROPERTY(bool, ForceVTInput, false);
WINRT_PROPERTY(winrt::hstring, PixelShaderPath);
WINRT_PROPERTY(bool, DetectURLs, true);
private:
std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE> _ColorTable;
public:
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept { return _ColorTable.at(index); }
std::array<winrt::Microsoft::Terminal::Core::Color, 16> ColorTable() { return _ColorTable; }
void ColorTable(std::array<winrt::Microsoft::Terminal::Core::Color, 16> /*colors*/) {}
};
}
namespace winrt::SampleApp::factory_implementation
{
BASIC_FACTORY(MySettings);
}

View file

@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace SampleApp
{
[default_interface] runtimeclass MySettings : Microsoft.Terminal.Core.ICoreSettings,
Microsoft.Terminal.Control.IControlSettings,
Microsoft.Terminal.Core.ICoreAppearance,
Microsoft.Terminal.Control.IControlAppearance
{
MySettings();
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{a4394404-37f7-41c1-802b-49788d3720e3}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SampleApp</RootNamespace>
<ProjectName>SampleAppLib</ProjectName>
<TargetName>SampleAppLib</TargetName>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
<ConfigurationType>StaticLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
<!--
This is an override that, puzzlingly, _forces XBF (XAML binary) embedding_.
We have to do this to overcome a layout issue in the WAP packaging project.
When we do this, the XBF ends up in resources.pri.
-->
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
<XamlComponentResourceLocation>nested</XamlComponentResourceLocation>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<ItemDefinitionGroup>
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- HERE BE DRAGONS:
For any types that use XAML information, if their .idl and .h aren't
marked DependentUpon the corresponding .xaml file, XamlTypeInfo.g.h won't
pick it up correctly. -->
<ApplicationDefinition Include="App.xaml">
<SubType>Designer</SubType>
</ApplicationDefinition>
</ItemGroup>
<!-- When we add other user controls, they should go in here as so: -->
<ItemGroup>
<Page Include="MyPage.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="App.base.h" />
<ClInclude Include="MySettings.h" />
<ClInclude Include="MyPage.h">
<DependentUpon>MyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="App.h">
<DependentUpon>App.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="SampleAppLogic.h">
<DependentUpon>SampleAppLogic.idl</DependentUpon>
</ClInclude>
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="init.cpp" />
<ClCompile Include="MySettings.cpp" />
<ClCompile Include="MyPage.cpp">
<DependentUpon>MyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="App.cpp">
<DependentUpon>App.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="SampleAppLogic.cpp">
<DependentUpon>SampleAppLogic.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<!-- If you add idl files here, make sure to include their implementation's
header in SampleApp.vcxproj (as well as in this file) -->
<Midl Include="App.idl">
<DependentUpon>App.xaml</DependentUpon>
</Midl>
<Midl Include="SampleAppLogic.idl" />
<Midl Include="MySettings.idl" />
<Midl Include="MyPage.idl">
<DependentUpon>MyPage.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<PRIResource Include="Resources\en-US\Resources.resw" />
<OCResourceDirectory Include="Resources" />
<None Include="packages.config" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See
https://github.com/Microsoft/msbuild/issues/3746 - it looks like MsBuild
just has a bug in it.-->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>Warning</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
<!-- ========================== Other References ========================= -->
<ItemGroup>
<!-- Manually add references to each of our dependent winmds. Mark them as
private=false and CopyLocalSatelliteAssemblies=false, so that we don't
propagate them upwards (which can make referencing this project result in
duplicate type definitions)-->
<Reference Include="Microsoft.Terminal.Core">
<HintPath>$(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\ConTypes.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<!-- ========================= Globals ======================== -->
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<!--
By default, the PRI file will contain resource paths beginning with the
project name. Since we enabled XBF embedding, this *also* includes App.xbf.
Well, App.xbf is hardcoded by the framework to be found at the resource ROOT.
To make that happen, we have to disable the prepending of the project name
to the App xaml files.
-->
<PropertyGroup>
<_GenerateProjectPriFileDependsOn>OpenConsolePlaceAppXbfAtRootOfResourceTree;$(_GenerateProjectPriFileDependsOn)</_GenerateProjectPriFileDependsOn>
</PropertyGroup>
<Target Name="OpenConsolePlaceAppXbfAtRootOfResourceTree" DependsOnTargets="GetPackagingOutputs">
<ItemGroup>
<_RelocatedAppXamlData Include="@(PackagingOutputs)" Condition="'%(Filename)' == 'App' and ('%(Extension)' == '.xaml' or '%(Extension)' == '.xbf')" />
<PackagingOutputs Remove="@(_RelocatedAppXamlData)" />
<PackagingOutputs Include="@(_RelocatedAppXamlData)">
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>

View file

@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleAppLogic.h"
#include "SampleAppLogic.g.cpp"
#include <LibraryResources.h>
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::System;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
using IInspectable = Windows::Foundation::IInspectable;
}
namespace winrt::SampleApp::implementation
{
// Function Description:
// - Get the SampleAppLogic for the current active Xaml application, or null if there isn't one.
// Return value:
// - A pointer (bare) to the SampleAppLogic, or nullptr. The app logic outlives all other objects,
// unless the application is in a terrible way, so this is "safe."
SampleAppLogic* SampleAppLogic::Current() noexcept
try
{
if (auto currentXamlApp{ winrt::Windows::UI::Xaml::Application::Current().try_as<winrt::SampleApp::App>() })
{
if (auto SampleAppLogicPointer{ winrt::get_self<SampleAppLogic>(currentXamlApp.Logic()) })
{
return SampleAppLogicPointer;
}
}
return nullptr;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return nullptr;
}
SampleAppLogic::SampleAppLogic()
{
// For your own sanity, it's better to do setup outside the ctor.
// If you do any setup in the ctor that ends up throwing an exception,
// then it might look like App just failed to activate, which will
// cause you to chase down the rabbit hole of "why is App not
// registered?" when it definitely is.
// The MyPage has to be constructed during our construction, to
// make sure that there's a terminal page for callers of
// SetTitleBarContent
_root = winrt::make_self<MyPage>();
}
// Method Description:
// - Build the UI for the terminal app. Before this method is called, it
// should not be assumed that the SampleApp is usable. The Settings
// should be loaded before this is called, either with LoadSettings or
// GetLaunchDimensions (which will call LoadSettings)
// Arguments:
// - <none>
// Return Value:
// - <none>
void SampleAppLogic::Create()
{
_root->Create();
}
UIElement SampleAppLogic::GetRoot() noexcept
{
return _root.as<winrt::Windows::UI::Xaml::Controls::Control>();
}
hstring SampleAppLogic::Title()
{
return _root->Title();
}
}

View file

@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "SampleAppLogic.g.h"
#include "MyPage.h"
#include "../../../src/cascadia/inc/cppwinrt_utils.h"
namespace winrt::SampleApp::implementation
{
struct SampleAppLogic : SampleAppLogicT<SampleAppLogic>
{
public:
static SampleAppLogic* Current() noexcept;
SampleAppLogic();
~SampleAppLogic() = default;
void Create();
Windows::UI::Xaml::UIElement GetRoot() noexcept;
winrt::hstring Title();
private:
// If you add controls here, but forget to null them either here or in
// the ctor, you're going to have a bad time. It'll mysteriously fail to
// activate the SampleAppLogic.
// ALSO: If you add any UIElements as roots here, make sure they're
// updated in _ApplyTheme. The root currently is _root.
winrt::com_ptr<MyPage> _root{ nullptr };
};
}
namespace winrt::SampleApp::factory_implementation
{
struct SampleAppLogic : SampleAppLogicT<SampleAppLogic, implementation::SampleAppLogic>
{
};
}

View file

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace SampleApp
{
[default_interface] runtimeclass SampleAppLogic
{
SampleAppLogic();
void Create();
Windows.UI.Xaml.UIElement GetRoot();
String Title { get; };
}
}

View file

@ -0,0 +1,3 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View file

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{26c51792-41a3-4fe0-ab5e-8b69d557bf91}</ProjectGuid>
<ProjectName>SampleApp</ProjectName>
<RootNamespace>SampleApp</RootNamespace>
<!-- cppwinrt.build.pre.props depends on these settings: -->
<!-- build a dll, not exe (Application) -->
<ConfigurationType>DynamicLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<!-- sets a bunch of Windows Universal properties -->
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- DON'T PUT XAML FILES HERE! Put them in SampleAppLib.vcxproj -->
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<!-- Only put headers for winrt types in here. Don't put other header files
in here - put them in SampleAppLib.vcxproj instead! -->
<ClInclude Include="pch.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<!-- Don't put source files in here - put them in SampleAppLib.vcxproj instead! -->
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<!-- DON'T PUT IDL FILES HERE! Put them in App.vcxproj -->
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<None Include="$(ProjectName).def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!-- Reference SampleAppLib here, so we can use it's App.winmd as
our App.winmd. This didn't work correctly in VS2017, you'd need to
manually reference the lib -->
<ProjectReference Include="$(OpenConsoleDir)samples\ScratchIslandApp\SampleApp\SampleAppLib.vcxproj">
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<!-- Manually include the Terminal.Core winmd, so we know where those types
are defined. We don't want to include it as a project reference, because
that would make us link that lib into our own binary. -->
<Reference Include="Microsoft.Terminal.Core">
<HintPath>$(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>User32.lib;WindowsApp.lib;shell32.lib;WinMM.Lib;%(AdditionalDependencies)</AdditionalDependencies>
<!-- SampleAppLib contains a DllMain that we need to force the use of. -->
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>

View file

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

View file

@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// pch.h
// Header for platform projection include files
//
#pragma once
// This file can be empty - the pch.h in SampleApp/lib does the heavy lifting
// of including all the headers we need. As this project is just a dll wrapper,
// we don't actually need anything in here.

View file

@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation
// Licensed under the MIT license.
#include "pch.h"
#include <LibraryResources.h>
#include <WilErrorReporting.h>
// Note: Generate GUID using TlgGuid.exe tool
TRACELOGGING_DEFINE_PROVIDER(
g_hSampleAppProvider,
"Microsoft.Windows.Terminal.App",
// {24a1622f-7da7-5c77-3303-d850bd1ab2ed}
(0x24a1622f, 0x7da7, 0x5c77, 0x33, 0x03, 0xd8, 0x50, 0xbd, 0x1a, 0xb2, 0xed),
TraceLoggingOptionMicrosoftTelemetry());
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID /*reserved*/)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hInstDll);
TraceLoggingRegister(g_hSampleAppProvider);
Microsoft::Console::ErrorReporting::EnableFallbackFailureReporting(g_hSampleAppProvider);
break;
case DLL_PROCESS_DETACH:
if (g_hSampleAppProvider)
{
TraceLoggingUnregister(g_hSampleAppProvider);
}
break;
}
return TRUE;
}
UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"SampleApp/Resources")

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.2" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" 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,71 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// pch.h
// Header for platform projection include files
//
#pragma once
#define WIN32_LEAN_AND_MEAN
#define NOMCX
#define NOHELP
#define NOCOMM
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#define BLOCK_TIL
#include <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>
#include <unknwn.h>
#include <hstring.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.Metadata.h>
#include <winrt/Windows.Graphics.Display.h>
#include <winrt/windows.ui.core.h>
#include <winrt/Windows.ui.input.h>
#include <winrt/Windows.UI.Text.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
#include <winrt/Windows.UI.Xaml.Data.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/Windows.UI.Xaml.Media.Animation.h>
#include <winrt/Windows.ui.xaml.input.h>
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.ViewManagement.h"
#include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
#include <winrt/Windows.System.h>
// Including TraceLogging essentials for the binary
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DECLARE_PROVIDER(g_hSampleAppProvider);
#include <telemetry/ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
#include <shellapi.h>
#include <shobjidl_core.h>
#include <winrt/Microsoft.Terminal.Core.h>
#include <winrt/Microsoft.Terminal.Control.h>
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View file

@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleAppHost.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::Hosting;
using namespace winrt::Windows::Foundation::Numerics;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Console::Types;
SampleAppHost::SampleAppHost() noexcept :
_app{},
_logic{ nullptr }, // don't make one, we're going to take a ref on app's
_window{ nullptr }
{
_logic = _app.Logic(); // get a ref to app's logic
_window = std::make_unique<SampleIslandWindow>();
_window->MakeWindow();
}
SampleAppHost::~SampleAppHost()
{
// destruction order is important for proper teardown here
_window = nullptr;
_app.Close();
_app = 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 SampleAppHost::Initialize()
{
_window->Initialize();
_logic.Create();
_window->UpdateTitle(_logic.Title());
// Set up the content of the application. If the app has a custom titlebar,
// set that content as well.
_window->SetContent(_logic.GetRoot());
_window->OnAppInitialized();
// THIS IS A HACK
//
// We've got a weird crash that happens terribly inconsistently, but pretty
// readily on migrie's laptop, only in Debug mode. Apparently, there's some
// weird ref-counting magic that goes on during teardown, and our
// Application doesn't get closed quite right, which can cause us to crash
// into the debugger. This of course, only happens on exit, and happens
// somewhere in the XamlHost.dll code.
//
// Crazily, if we _manually leak the Application_ here, then the crash
// doesn't happen. This doesn't matter, because we really want the
// Application to live for _the entire lifetime of the process_, so the only
// time when this object would actually need to get cleaned up is _during
// exit_. So we can safely leak this Application object, and have it just
// get cleaned up normally when our process exits.
::winrt::SampleApp::App a{ _app };
::winrt::detach_abi(a);
}

View file

@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleIslandWindow.h"
class SampleAppHost
{
public:
SampleAppHost() noexcept;
virtual ~SampleAppHost();
void Initialize();
private:
std::unique_ptr<SampleIslandWindow> _window;
winrt::SampleApp::App _app;
winrt::SampleApp::SampleAppLogic _logic;
};

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,220 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleIslandWindow.h"
#include "../types/inc/Viewport.hpp"
#include "resource.h"
#include "icon.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_HOSTING_WINDOW_CLASS"
SampleIslandWindow::SampleIslandWindow() noexcept :
_interopWindowHandle{ nullptr },
_rootGrid{ nullptr },
_source{ nullptr }
{
}
SampleIslandWindow::~SampleIslandWindow()
{
_source.Close();
}
// Method Description:
// - Create the actual window that we'll use for the application.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SampleIslandWindow::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(0,
wc.lpszClassName,
L"ScratchApp",
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 SampleIslandWindow::Close()
{
PostQuitMessage(0);
}
// 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 SampleIslandWindow::_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;
ShowWindow(_window.get(), SW_SHOW);
UpdateWindow(_window.get());
UpdateWindowIconForActiveMetrics(_window.get());
}
void SampleIslandWindow::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 SampleIslandWindow::OnSize(const UINT width, const UINT height)
{
// update the interop window size
SetWindowPos(_interopWindowHandle, nullptr, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE);
if (_rootGrid)
{
const auto size = GetLogicalSize();
_rootGrid.Width(size.Width);
_rootGrid.Height(size.Height);
}
}
[[nodiscard]] LRESULT SampleIslandWindow::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;
}
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_THEMECHANGED:
UpdateWindowIconForActiveMetrics(_window.get());
return 0;
}
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 SampleIslandWindow::OnResize(const UINT width, const UINT height)
{
if (_interopWindowHandle)
{
OnSize(width, height);
}
}
// Method Description:
// - Called when the window is minimized to the taskbar.
void SampleIslandWindow::OnMinimize()
{
}
// Method Description:
// - Called when the window is restored from having been minimized.
void SampleIslandWindow::OnRestore()
{
}
void SampleIslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content)
{
_rootGrid.Children().Clear();
_rootGrid.Children().Append(content);
}
void SampleIslandWindow::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 SampleIslandWindow::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);
}

View file

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleBaseWindow.h"
#include "../../../src/cascadia/inc/cppwinrt_utils.h"
class SampleIslandWindow :
public BaseWindow<SampleIslandWindow>
{
public:
SampleIslandWindow() noexcept;
virtual ~SampleIslandWindow() 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 void Initialize();
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;
void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept;
};

View file

@ -0,0 +1,122 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SampleAppHost.h"
#include "resource.h"
#include "../types/inc/User32Utils.hpp"
#include <WilErrorReporting.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;
// Routine Description:
// - Takes an image architecture and locates a string resource that maps to that architecture.
// Arguments:
// - imageArchitecture - An IMAGE_FILE_MACHINE architecture enum value
// - See https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants
// Return Value:
// - A string value representing the human-readable name of this architecture.
static std::wstring ImageArchitectureToString(USHORT imageArchitecture)
{
// clang-format off
const auto id = imageArchitecture == IMAGE_FILE_MACHINE_I386 ? IDS_X86_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_AMD64 ? IDS_AMD64_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_ARM64 ? IDS_ARM64_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_ARM ? IDS_ARM_ARCHITECTURE :
IDS_UNKNOWN_ARCHITECTURE;
// clang-format on
return GetStringResource(id);
}
// Routine Description:
// - Blocks the user from launching the application with a message box dialog and early exit
// if the process architecture doesn't match the system platform native architecture.
// - This is because the conhost.exe must match the condrv.sys on the system and the PTY
// infrastructure that powers everything won't work if we have a mismatch.
// Arguments:
// - <none>
// Return Value:
// - <none>
static void EnsureNativeArchitecture()
{
USHORT processMachine{};
USHORT nativeMachine{};
THROW_IF_WIN32_BOOL_FALSE(IsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine));
if (processMachine != IMAGE_FILE_MACHINE_UNKNOWN && processMachine != nativeMachine)
{
const auto formatPattern = GetStringResource(IDS_ERROR_ARCHITECTURE_FORMAT);
const auto nativeArchitecture = ImageArchitectureToString(nativeMachine);
const auto processArchitecture = ImageArchitectureToString(processMachine);
auto buffer{ wil::str_printf<std::wstring>(formatPattern.data(), nativeArchitecture.data(), processArchitecture.data()) };
MessageBoxW(nullptr,
buffer.data(),
GetStringResource(IDS_ERROR_DIALOG_TITLE).data(),
MB_OK | MB_ICONERROR);
ExitProcess(0);
}
}
static bool _messageIsF7Keypress(const MSG& message)
{
return (message.message == WM_KEYDOWN || message.message == WM_SYSKEYDOWN) && message.wParam == VK_F7;
}
static bool _messageIsAltKeyup(const MSG& message)
{
return (message.message == WM_KEYUP || message.message == WM_SYSKEYUP) && message.wParam == VK_MENU;
}
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);
// Block the user from starting if they launched the incorrect architecture version of the project.
// This should only be applicable to developer versions. The package installation process
// should choose and install the correct one from the bundle.
EnsureNativeArchitecture();
// 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 SampleAppHost 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.
SampleAppHost 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 @@


View file

@ -0,0 +1,20 @@
<?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>
</assembly>

View file

@ -0,0 +1,97 @@
// 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"
IDI_APPICON_HC_BLACK ICON "..\\..\\..\\res\\terminal\\images\\terminal_contrast-black.ico"
IDI_APPICON_HC_WHITE ICON "..\\..\\..\\res\\terminal\\images\\terminal_contrast-white.ico"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_ERROR_DIALOG_TITLE "Error"
IDS_HELP_DIALOG_TITLE "Help"
IDS_ERROR_ARCHITECTURE_FORMAT
"This sample is designed to run on your system's native architecture (%s).\nYou are currently using the %s version.\n\nPlease use the version of this sample 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,224 @@
<?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.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<PropertyGroup Label="Globals">
<ProjectGuid>{b4427499-9fde-4208-b456-5bc580637633}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WindowExe</RootNamespace>
<ProjectName>WindowExe</ProjectName>
<TargetName>WindowExe</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>
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
</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>
<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="icon.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="SampleAppHost.h" />
<ClInclude Include="SampleBaseWindow.h" />
<ClInclude Include="SampleIslandWindow.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="icon.cpp" />
<ClCompile Include="SampleMain.cpp" />
<ClCompile Include="SampleAppHost.cpp" />
<ClCompile Include="SampleIslandWindow.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WindowExe.rc" />
</ItemGroup>
<ItemGroup>
<Manifest Include="WindowExe.manifest" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<ProjectReference Include="$(OpenConsoleDir)samples\ScratchIslandApp\SampleApp\dll\SampleApp.vcxproj" />
</ItemGroup>
<!-- ========================== Other References ========================= -->
<ItemGroup>
<!--
!! LOAD BEARING !!
Make sure these winmd's are all Private=true,
CopyLocalSatelliteAssemblies=true, at this layer. Those will force the
packaging project to actually include those winmd's in our final package. If
they're missing, then WinRT will have a hard time marshalling those types
across a process boundary.
Particularly tricky is Microsoft.Terminal.Core.winmd. That winmd doesn't
have its own DLL (it doesn't have any activatable classes, only structs and
interfaces). However, it too is necessary for Terminal.Control to be able to
marshall the Core types across the boundary.
-->
<Reference Include="Microsoft.Terminal.Core">
<HintPath>$(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)TerminalConnection\TerminalConnection.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Control">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd</HintPath>
<Implementation>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.dll</Implementation>
<IsWinMDFile>true</IsWinMDFile>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</Reference>
</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.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<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="'$(WindowExeOfficialBuild)'=='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** -->
<!-- **BEGIN TERMINAL CONNECTION HACK** -->
<!-- This is the same as the above VC libs hack, but for TerminalConnection.
TerminalConnection depends on cpprest*.dll, and if we don't include it in
the packaging output, we'll crash as soon as we try to load
TerminalConnection.dll.
The Sample sln needs to do this manually - the real exe has a
ProjectReference to TerminalConnection.vcxproj and can figure this out on
its own. -->
<ItemGroup>
<_TerminalConnectionDlls Include="$(OpenConsoleCommonOutDir)\TerminalConnection\*.dll" />
<PackagingOutputs Include="@(_TerminalConnectionDlls)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
<!-- **END TERMINAL CONNECTION HACK** -->
<!-- Same thing again here, with WindowsTerminal.exe -->
<ItemGroup>
<_WindowsTerminalExe Include="$(OpenConsoleCommonOutDir)\WindowsTerminal\*.exe" />
<PackagingOutputs Include="@(_WindowsTerminalExe)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
<Import Project="..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" />
</Project>

View file

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "resource.h"
static int _GetActiveAppIconResource()
{
auto iconResource{ IDI_APPICON };
HIGHCONTRASTW hcInfo{};
hcInfo.cbSize = sizeof(hcInfo);
if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(hcInfo), &hcInfo, 0))
{
if (WI_IsFlagSet(hcInfo.dwFlags, HCF_HIGHCONTRASTON))
{
iconResource = IDI_APPICON_HC_BLACK;
if (0x00FFFFFF == GetSysColor(COLOR_WINDOW)) // white window color == white high contrast
{
iconResource = IDI_APPICON_HC_WHITE;
}
}
}
return iconResource;
}
void UpdateWindowIconForActiveMetrics(HWND window)
{
auto iconResource{ MAKEINTRESOURCEW(_GetActiveAppIconResource()) };
// These handles are loaded with LR_SHARED, so they are safe to "leak".
HANDLE smallIcon{ LoadImageW(wil::GetModuleInstanceHandle(), iconResource, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) };
LOG_LAST_ERROR_IF_NULL(smallIcon);
HANDLE largeIcon{ LoadImageW(wil::GetModuleInstanceHandle(), iconResource, IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_SHARED) };
LOG_LAST_ERROR_IF_NULL(largeIcon);
if (smallIcon)
{
SendMessageW(window, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(smallIcon));
}
if (largeIcon)
{
SendMessageW(window, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(largeIcon));
}
}

View file

@ -0,0 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
void UpdateWindowIconForActiveMetrics(HWND window);

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.2" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" 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,82 @@
/*++
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
#define NOMCX
#define NOHELP
#define NOCOMM
#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>
#include <ShObjIdl.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.Xaml.Hosting.h>
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
// Additional headers for various xaml features. We need:
// * Core so we can resume_foreground with CoreDispatcher
// * Controls for grid
// * Media for ScaleTransform
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/SampleApp.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 <WinUser.h>
#include "til.h"

View file

@ -0,0 +1,27 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by WindowsTerminal.rc
//
#define IDI_APPICON 101
#define IDI_APPICON_HC_BLACK 102
#define IDI_APPICON_HC_WHITE 103
#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,60 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "ContentProcess.h"
#include "ContentProcess.g.cpp"
namespace winrt::Microsoft::Terminal::Control::implementation
{
ContentProcess::ContentProcess() {}
void ContentProcess::Initialize(Control::IControlSettings settings, TerminalConnection::ITerminalConnection connection)
{
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
}
Control::ControlInteractivity ContentProcess::GetInteractivity()
{
return _interactivity;
}
uint64_t ContentProcess::RequestSwapChainHandle(const uint64_t pid)
{
auto ourPid = GetCurrentProcessId();
HANDLE ourHandle = reinterpret_cast<HANDLE>(_interactivity.Core().SwapChainHandle());
if (pid == ourPid)
{
return reinterpret_cast<uint64_t>(ourHandle);
}
wil::unique_handle hWindowProcess{ OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
static_cast<DWORD>(pid)) };
if (hWindowProcess.get() == nullptr)
{
const auto gle = GetLastError();
gle;
// TODO! tracelog an error here
return 0;
}
HANDLE theirHandle{ nullptr };
BOOL success = DuplicateHandle(GetCurrentProcess(),
ourHandle,
hWindowProcess.get(),
&theirHandle,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
if (!success)
{
const auto gle = GetLastError();
gle;
// TODO! tracelog an error here
return 0;
}
return reinterpret_cast<uint64_t>(theirHandle);
}
}

View file

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "ContentProcess.g.h"
#include "ControlInteractivity.h"
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct ContentProcess : ContentProcessT<ContentProcess>
{
ContentProcess();
void Initialize(Control::IControlSettings settings, TerminalConnection::ITerminalConnection connection);
Control::ControlInteractivity GetInteractivity();
uint64_t RequestSwapChainHandle(const uint64_t pid);
private:
Control::ControlInteractivity _interactivity{ nullptr };
};
}
namespace winrt::Microsoft::Terminal::Control::factory_implementation
{
BASIC_FACTORY(ContentProcess);
}

View file

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "ControlInteractivity.idl";
namespace Microsoft.Terminal.Control
{
runtimeclass ContentProcess {
ContentProcess();
void Initialize(IControlSettings settings,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
ControlInteractivity GetInteractivity();
UInt64 RequestSwapChainHandle(UInt64 pid);
};
}

View file

@ -426,7 +426,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Updates last hovered cell, renders / removes rendering of hyper-link if required
// Arguments:
// - terminalPosition: The terminal position of the pointer
void ControlCore::UpdateHoveredCell(const std::optional<til::point>& terminalPosition)
void ControlCore::SetHoveredCell(Core::Point pos)
{
_updateHoveredCell(std::optional<til::point>{ pos });
}
void ControlCore::ClearHoveredCell()
{
_updateHoveredCell(std::nullopt);
}
void ControlCore::_updateHoveredCell(const std::optional<til::point> terminalPosition)
{
if (terminalPosition == _lastHoveredCell)
{
@ -477,7 +486,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return winrt::hstring{ _terminal->GetHyperlinkAtPosition(pos) };
}
winrt::hstring ControlCore::GetHoveredUriText() const
winrt::hstring ControlCore::HoveredUriText() const
{
auto lock = _terminal->LockForReading(); // Lock for the duration of our reads.
if (_lastHoveredCell.has_value())
@ -487,9 +496,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return {};
}
std::optional<til::point> ControlCore::GetHoveredCell() const
Windows::Foundation::IReference<Core::Point> ControlCore::HoveredCell() const
{
return _lastHoveredCell;
return _lastHoveredCell.has_value() ? Windows::Foundation::IReference<Core::Point>{ _lastHoveredCell.value() } : nullptr;
}
// Method Description:
@ -515,6 +524,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_desiredFont = { _actualFont };
// Update the terminal core with its new Core settings
Core::ICoreSettings coreSettings = _settings.try_as<Core::ICoreSettings>();
Core::ICoreAppearance coreAppearance = _settings.try_as<Core::ICoreAppearance>();
if (!coreSettings)
{
OutputDebugString(L"Failed to get core settings");
}
if (!coreAppearance)
{
OutputDebugString(L"Failed to get coreAppearance");
}
_terminal->UpdateSettings(_settings);
if (!_initializedTerminal)
@ -893,6 +912,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _actualFont;
}
winrt::Windows::Foundation::Size ControlCore::FontSize() const noexcept
{
const auto fontSize = GetFont().GetSize();
return {
::base::saturated_cast<float>(fontSize.X),
::base::saturated_cast<float>(fontSize.Y)
};
}
winrt::hstring ControlCore::FontFaceName() const noexcept
{
return winrt::hstring{ GetFont().GetFaceName() };
}
uint16_t ControlCore::FontWeight() const noexcept
{
return static_cast<uint16_t>(GetFont().GetWeight());
}
til::size ControlCore::FontSizeInDips() const
{
const til::size fontSize{ GetFont().GetSize() };
@ -1075,10 +1112,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _settings.CopyOnSelect();
}
std::vector<std::wstring> ControlCore::SelectedText(bool trimTrailingWhitespace) const
Windows::Foundation::Collections::IVector<winrt::hstring> ControlCore::SelectedText(bool trimTrailingWhitespace) const
{
// RetrieveSelectedTextFromBuffer will lock while it's reading
return _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace).text;
auto internalResult{ _terminal->RetrieveSelectedTextFromBuffer(trimTrailingWhitespace).text };
auto result = winrt::single_threaded_vector<winrt::hstring>();
for (const auto& row : internalResult)
{
result.Append(winrt::hstring{ row });
}
return result;
}
::Microsoft::Console::Types::IUiaData* ControlCore::GetUiaData() const
@ -1122,7 +1167,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlCore::SetBackgroundOpacity(const float opacity)
void ControlCore::SetBackgroundOpacity(const double opacity)
{
if (_renderEngine)
{
@ -1173,7 +1218,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
HANDLE ControlCore::GetSwapChainHandle() const
uint64_t ControlCore::SwapChainHandle() const
{
// This is called by:
// * TermControl::RenderEngineSwapChainChanged, who is only registered
@ -1181,7 +1226,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// * TermControl::_InitializeTerminal, after the call to Initialize, for
// _AttachDxgiSwapChainToXaml.
// In both cases, we'll have a _renderEngine by then.
return _renderEngine->GetSwapChainHandle();
return reinterpret_cast<uint64_t>(_renderEngine->GetSwapChainHandle());
}
void ControlCore::_rendererWarning(const HRESULT hr)

View file

@ -49,15 +49,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void UpdateAppearance(const IControlAppearance& newAppearance);
void SizeChanged(const double width, const double height);
void ScaleChanged(const double scale);
HANDLE GetSwapChainHandle() const;
uint64_t SwapChainHandle() const;
void AdjustFontSize(int fontSizeDelta);
void ResetFontSize();
FontInfo GetFont() const;
til::size FontSizeInDips() const;
winrt::Windows::Foundation::Size FontSize() const noexcept;
winrt::hstring FontFaceName() const noexcept;
uint16_t FontWeight() const noexcept;
til::color BackgroundColor() const;
void SetBackgroundOpacity(const float opacity);
void SetBackgroundOpacity(const double opacity);
void SendInput(const winrt::hstring& wstr);
void PasteText(const winrt::hstring& hstr);
@ -68,10 +72,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ResumeRendering();
void UpdatePatternLocations();
void UpdateHoveredCell(const std::optional<til::point>& terminalPosition);
void SetHoveredCell(Core::Point terminalPosition);
void ClearHoveredCell();
winrt::hstring GetHyperlink(const til::point position) const;
winrt::hstring GetHoveredUriText() const;
std::optional<til::point> GetHoveredCell() const;
winrt::hstring HoveredUriText() const;
Windows::Foundation::IReference<Core::Point> HoveredCell() const;
::Microsoft::Console::Types::IUiaData* GetUiaData() const;
@ -120,7 +125,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool HasSelection() const;
bool CopyOnSelect() const;
std::vector<std::wstring> SelectedText(bool trimTrailingWhitespace) const;
Windows::Foundation::Collections::IVector<winrt::hstring> SelectedText(bool trimTrailingWhitespace) const;
void SetSelectionAnchor(til::point const& position);
void SetEndSelectionPoint(til::point const& position);
@ -233,6 +238,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _raiseReadOnlyWarning();
void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine);
void _connectionOutputHandler(const hstring& hstr);
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
friend class ControlUnitTests::ControlCoreTests;
friend class ControlUnitTests::ControlInteractivityTests;

View file

@ -8,9 +8,97 @@ import "EventArgs.idl";
namespace Microsoft.Terminal.Control
{
// This is a mirror of
// ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState,
// but projectable.
// !! LOAD BEARING !! If you make this a struct with Booleans (like they
// make the most sense as), then the app will crash trying to toss one of
// these across the process boundary. I haven't the damndest idea why.
[flags]
enum MouseButtonState
{
IsLeftButtonDown = 0x1,
IsMiddleButtonDown = 0x2,
IsRightButtonDown = 0x4
};
[default_interface] runtimeclass ControlCore : ICoreState
{
ControlCore(IControlSettings settings,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
Boolean Initialize(Double actualWidth,
Double actualHeight,
Double compositionScale);
void UpdateSettings(IControlSettings settings);
void UpdateAppearance(IControlAppearance appearance);
UInt64 SwapChainHandle { get; };
Windows.Foundation.Size FontSize { get; };
String FontFaceName { get; };
UInt16 FontWeight { get; };
Boolean TrySendKeyEvent(Int16 vkey,
Int16 scanCode,
Microsoft.Terminal.Core.ControlKeyStates modifiers,
Boolean keyDown);
Boolean SendCharEvent(Char ch,
Int16 scanCode,
Microsoft.Terminal.Core.ControlKeyStates modifiers);
void SendInput(String text);
void PasteText(String text);
void SetHoveredCell(Microsoft.Terminal.Core.Point terminalPosition);
void ClearHoveredCell();
void ResetFontSize();
void AdjustFontSize(Int32 fontSizeDelta);
void SizeChanged(Double width, Double height);
void ScaleChanged(Double scale);
void ToggleShaderEffects();
void ToggleReadOnlyMode();
Microsoft.Terminal.Core.Point CursorPosition { get; };
void ResumeRendering();
void BlinkAttributeTick();
void UpdatePatternLocations();
void Search(String text, Boolean goForward, Boolean caseSensitive);
void SetBackgroundOpacity(Double opacity);
Microsoft.Terminal.Core.Color BackgroundColor { get; };
Boolean HasSelection { get; };
IVector<String> SelectedText(Boolean trimTrailingWhitespace);
String HoveredUriText { get; };
Windows.Foundation.IReference<Microsoft.Terminal.Core.Point> HoveredCell { get; };
void Close();
void BlinkCursor();
Boolean IsInReadOnlyMode { get; };
Boolean CursorOn;
void EnablePainting();
event FontSizeChangedEventArgs FontSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, CopyToClipboardEventArgs> CopyToClipboard;
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> WarningBell;
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> BackgroundColorChanged;
event Windows.Foundation.TypedEventHandler<Object, ScrollPositionChangedArgs> ScrollPositionChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> CursorPositionChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> TaskbarProgressChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> ConnectionStateChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> HoveredHyperlinkChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> RendererEnteredErrorState;
event Windows.Foundation.TypedEventHandler<Object, Object> SwapChainChanged;
event Windows.Foundation.TypedEventHandler<Object, RendererWarningArgs> RendererWarning;
event Windows.Foundation.TypedEventHandler<Object, NoticeEventArgs> RaiseNotice;
event Windows.Foundation.TypedEventHandler<Object, TransparencyChangedEventArgs> TransparencyChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> ReceivedOutput;
};
}

View file

@ -8,13 +8,15 @@
#include <unicode.hpp>
#include <Utf16Parser.hpp>
#include <Utils.h>
#include <WinUser.h>
#include <LibraryResources.h>
#include "../../types/inc/GlyphWidth.hpp"
#include "../../types/inc/Utils.hpp"
#include "../../buffer/out/search.h"
#include "InteractivityAutomationPeer.h"
#include "ControlInteractivity.g.cpp"
#include "TermControl.h"
using namespace ::Microsoft::Console::Types;
using namespace ::Microsoft::Console::VirtualTerminal;
@ -27,6 +29,15 @@ static constexpr unsigned int MAX_CLICK_COUNT = 3;
namespace winrt::Microsoft::Terminal::Control::implementation
{
static constexpr TerminalInput::MouseButtonState toInternalMouseState(const Control::MouseButtonState& state)
{
return TerminalInput::MouseButtonState{
WI_IsFlagSet(state, MouseButtonState::IsLeftButtonDown),
WI_IsFlagSet(state, MouseButtonState::IsMiddleButtonDown),
WI_IsFlagSet(state, MouseButtonState::IsRightButtonDown)
};
}
ControlInteractivity::ControlInteractivity(IControlSettings settings,
TerminalConnection::ITerminalConnection connection) :
_touchAnchor{ std::nullopt },
@ -37,6 +48,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core = winrt::make_self<ControlCore>(settings, connection);
}
// Method Description:
// - Updates our internal settings. These settings should be
// interactivity-specific. Right now, we primarily update _rowsToScroll
// with the current value of SPI_GETWHEELSCROLLLINES.
// Arguments:
// - <none>
// Return Value:
// - <none>
void ControlInteractivity::UpdateSettings()
{
_updateSystemParameterSettings();
@ -50,9 +69,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_multiClickTimer = GetDoubleClickTime() * 1000;
}
winrt::com_ptr<ControlCore> ControlInteractivity::GetCore()
Control::ControlCore ControlInteractivity::Core()
{
return _core;
return *_core;
}
// Method Description:
@ -87,9 +106,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void ControlInteractivity::GainFocus()
{
// GH#5421: Enable the UiaEngine before checking for the SearchBox
// That way, new selections are notified to automation clients.
if (_uiaEngine.get())
{
THROW_IF_FAILED(_uiaEngine->Enable());
}
_updateSystemParameterSettings();
}
void ControlInteractivity::LostFocus()
{
if (_uiaEngine.get())
{
THROW_IF_FAILED(_uiaEngine->Disable());
}
}
// Method Description
// - Updates internal params based on system parameters
void ControlInteractivity::_updateSystemParameterSettings() noexcept
@ -156,7 +190,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core->PasteText(winrt::hstring{ wstr });
}
void ControlInteractivity::PointerPressed(TerminalInput::MouseButtonState buttonState,
void ControlInteractivity::PointerPressed(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const uint64_t timestamp,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
@ -170,7 +204,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// GH#9396: we prioritize hyper-link over VT mouse events
auto hyperlink = _core->GetHyperlink(terminalPosition);
if (buttonState.isLeftButtonDown &&
if (WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown) &&
ctrlEnabled && !hyperlink.empty())
{
const auto clickCount = _numberOfClicks(pixelPosition, timestamp);
@ -182,9 +216,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
else if (_canSendVTMouseInput(modifiers))
{
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, toInternalMouseState(buttonState));
}
else if (buttonState.isLeftButtonDown)
else if (WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown))
{
const auto clickCount = _numberOfClicks(pixelPosition, timestamp);
// This formula enables the number of clicks to cycle properly
@ -219,7 +253,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_singleClickTouchdownPos = std::nullopt;
}
}
else if (buttonState.isRightButtonDown)
else if (WI_IsFlagSet(buttonState, MouseButtonState::IsRightButtonDown))
{
// CopyOnSelect right click always pastes
if (_core->CopyOnSelect() || !_core->HasSelection())
@ -238,7 +272,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_touchAnchor = contactPoint;
}
void ControlInteractivity::PointerMoved(TerminalInput::MouseButtonState buttonState,
void ControlInteractivity::PointerMoved(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const bool focused,
@ -249,9 +283,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Short-circuit isReadOnly check to avoid warning dialog
if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers))
{
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, toInternalMouseState(buttonState));
}
else if (focused && buttonState.isLeftButtonDown)
else if (focused && WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown))
{
if (_singleClickTouchdownPos)
{
@ -279,7 +313,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
SetEndSelectionPoint(pixelPosition);
}
_core->UpdateHoveredCell(terminalPosition);
_core->SetHoveredCell(terminalPosition);
}
void ControlInteractivity::TouchMoved(const til::point newTouchPoint,
@ -319,7 +353,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void ControlInteractivity::PointerReleased(TerminalInput::MouseButtonState buttonState,
void ControlInteractivity::PointerReleased(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const til::point pixelPosition)
@ -328,7 +362,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Short-circuit isReadOnly check to avoid warning dialog
if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers))
{
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, toInternalMouseState(buttonState));
return;
}
@ -366,7 +400,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool ControlInteractivity::MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const int32_t delta,
const til::point pixelPosition,
const TerminalInput::MouseButtonState state)
const Control::MouseButtonState buttonState)
{
const til::point terminalPosition = _getTerminalPosition(pixelPosition);
@ -382,7 +416,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
WM_MOUSEWHEEL,
modifiers,
::base::saturated_cast<short>(delta),
state);
toInternalMouseState(buttonState));
}
const auto ctrlPressed = modifiers.IsCtrlPressed();
@ -398,7 +432,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
else
{
_mouseScrollHandler(delta, pixelPosition, state.isLeftButtonDown);
_mouseScrollHandler(delta, pixelPosition, WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown));
}
return false;
}
@ -557,4 +591,36 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Convert the location in pixels to characters within the current viewport.
return til::point{ pixelPosition / fontSize };
}
// Method Description:
// - Creates an automation peer for the Terminal Control, enabling
// accessibility on our control.
// - Our implementation implements the ITextProvider pattern, and the
// IControlAccessibilityInfo, to connect to the UiaEngine, which must be
// attached to the core's renderer.
// - The TermControlAutomationPeer will connect this to the UI tree.
// Arguments:
// - None
// Return Value:
// - The automation peer for our control
Control::InteractivityAutomationPeer ControlInteractivity::OnCreateAutomationPeer()
try
{
auto autoPeer = winrt::make_self<implementation::InteractivityAutomationPeer>(this);
_uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(autoPeer.get());
_core->AttachUiaEngine(_uiaEngine.get());
return *autoPeer;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return nullptr;
}
::Microsoft::Console::Types::IUiaData* ControlInteractivity::GetUiaData() const
{
return _core->GetUiaData();
}
}

View file

@ -23,11 +23,6 @@
#include "ControlCore.h"
namespace Microsoft::Console::VirtualTerminal
{
struct MouseButtonState;
}
namespace ControlUnitTests
{
class ControlCoreTests;
@ -43,19 +38,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TerminalConnection::ITerminalConnection connection);
void GainFocus();
void LostFocus();
void UpdateSettings();
void Initialize();
winrt::com_ptr<ControlCore> GetCore();
Control::ControlCore Core();
Control::InteractivityAutomationPeer OnCreateAutomationPeer();
::Microsoft::Console::Types::IUiaData* GetUiaData() const;
#pragma region Input Methods
void PointerPressed(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState,
void PointerPressed(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const uint64_t timestamp,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const til::point pixelPosition);
void TouchPressed(const til::point contactPoint);
void PointerMoved(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState,
void PointerMoved(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const bool focused,
@ -63,7 +62,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TouchMoved(const til::point newTouchPoint,
const bool focused);
void PointerReleased(::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState buttonState,
void PointerReleased(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const til::point pixelPosition);
@ -72,7 +71,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const int32_t delta,
const til::point pixelPosition,
const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state);
const Control::MouseButtonState state);
void UpdateScrollbar(const double newValue);
@ -83,7 +82,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void RequestPasteTextFromClipboard();
void SetEndSelectionPoint(const til::point pixelPosition);
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);
TYPED_EVENT(ScrollPositionChanged, IInspectable, Control::ScrollPositionChangedArgs);
private:
// NOTE: _uiaEngine must be ordered before _core.
//
// ControlCore::AttachUiaEngine receives a IRenderEngine as a raw pointer, which we own.
// We must ensure that we first destroy the ControlCore before the UiaEngine instance
// in order to safely resolve this unsafe pointer dependency. Otherwise a deallocated
// IRenderEngine is accessed when ControlCore calls Renderer::TriggerTeardown.
// (C++ class members are destroyed in reverse order.)
std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine;
winrt::com_ptr<ControlCore> _core{ nullptr };
unsigned int _rowsToScroll;
double _internalScrollbarPosition{ 0.0 };
@ -129,10 +141,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _sendPastedTextToConnection(std::wstring_view wstr);
til::point _getTerminalPosition(const til::point& pixelPosition);
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);
TYPED_EVENT(ScrollPositionChanged, IInspectable, Control::ScrollPositionChangedArgs);
friend class ControlUnitTests::ControlCoreTests;
friend class ControlUnitTests::ControlInteractivityTests;
};

View file

@ -5,6 +5,8 @@ import "ICoreState.idl";
import "IControlSettings.idl";
import "ControlCore.idl";
import "EventArgs.idl";
import "InteractivityAutomationPeer.idl";
namespace Microsoft.Terminal.Control
{
@ -13,5 +15,51 @@ namespace Microsoft.Terminal.Control
{
ControlInteractivity(IControlSettings settings,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
ControlCore Core { get; };
void UpdateSettings();
void Initialize();
void GainFocus();
void LostFocus();
InteractivityAutomationPeer OnCreateAutomationPeer();
Boolean CopySelectionToClipboard(Boolean singleLine, Windows.Foundation.IReference<CopyFormat> formats);
void RequestPasteTextFromClipboard();
void SetEndSelectionPoint(Microsoft.Terminal.Core.Point point);
void PointerPressed(MouseButtonState buttonState,
UInt32 pointerUpdateKind,
UInt64 timestamp,
Microsoft.Terminal.Core.ControlKeyStates modifiers,
Microsoft.Terminal.Core.Point pixelPosition);
void TouchPressed(Microsoft.Terminal.Core.Point contactPoint);
void PointerMoved(MouseButtonState buttonState,
UInt32 pointerUpdateKind,
Microsoft.Terminal.Core.ControlKeyStates modifiers,
Boolean focused,
Microsoft.Terminal.Core.Point pixelPosition);
void TouchMoved(Microsoft.Terminal.Core.Point newTouchPoint,
Boolean focused);
void PointerReleased(MouseButtonState buttonState,
UInt32 pointerUpdateKind,
Microsoft.Terminal.Core.ControlKeyStates modifiers,
Microsoft.Terminal.Core.Point pixelPosition);
void TouchReleased();
Boolean MouseWheel(Microsoft.Terminal.Core.ControlKeyStates modifiers,
Int32 delta,
Microsoft.Terminal.Core.Point pixelPosition,
MouseButtonState state);
void UpdateScrollbar(Double newValue);
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
event Windows.Foundation.TypedEventHandler<Object, ScrollPositionChangedArgs> ScrollPositionChanged;
event Windows.Foundation.TypedEventHandler<Object, PasteFromClipboardEventArgs> PasteFromClipboard;
};
}

View file

@ -17,6 +17,7 @@ namespace Microsoft.Terminal.Control
Int32 ScrollOffset { get; };
Int32 ViewHeight { get; };
Int32 BufferHeight { get; };
Boolean BracketedPasteEnabled { get; };

View file

@ -0,0 +1,208 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include <UIAutomationCore.h>
#include <LibraryResources.h>
#include "InteractivityAutomationPeer.h"
#include "InteractivityAutomationPeer.g.cpp"
#include "XamlUiaTextRange.h"
#include "../types/UiaTracing.h"
using namespace Microsoft::Console::Types;
using namespace winrt::Windows::UI::Xaml::Automation::Peers;
using namespace winrt::Windows::Graphics::Display;
namespace UIA
{
using ::ITextRangeProvider;
using ::SupportedTextSelection;
}
namespace XamlAutomation
{
using winrt::Windows::UI::Xaml::Automation::SupportedTextSelection;
using winrt::Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple;
using winrt::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider;
}
namespace winrt::Microsoft::Terminal::Control::implementation
{
InteractivityAutomationPeer::InteractivityAutomationPeer(Control::implementation::ControlInteractivity* owner) :
_interactivity{ owner }
{
THROW_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, _interactivity->GetUiaData(), this));
};
void InteractivityAutomationPeer::SetControlBounds(const Windows::Foundation::Rect bounds)
{
_controlBounds = til::rectangle{ til::math::rounding, bounds };
}
void InteractivityAutomationPeer::SetControlPadding(const Core::Padding padding)
{
_controlPadding = padding;
}
// Method Description:
// - Signals the ui automation client that the terminal's selection has
// changed and should be updated
// - We will raise a new event, for out embedding control to be able to
// raise the event. AutomationPeer by itself doesn't hook up to the
// eventing mechanism, we need the FrameworkAutomationPeer to do that.
// Arguments:
// - <none>
// Return Value:
// - <none>
void InteractivityAutomationPeer::SignalSelectionChanged()
{
_SelectionChangedHandlers(*this, nullptr);
}
// Method Description:
// - Signals the ui automation client that the terminal's output has changed
// and should be updated
// - We will raise a new event, for out embedding control to be able to
// raise the event. AutomationPeer by itself doesn't hook up to the
// eventing mechanism, we need the FrameworkAutomationPeer to do that.
// Arguments:
// - <none>
// Return Value:
// - <none>
void InteractivityAutomationPeer::SignalTextChanged()
{
_TextChangedHandlers(*this, nullptr);
}
// Method Description:
// - Signals the ui automation client that the cursor's state has changed
// and should be updated
// - We will raise a new event, for out embedding control to be able to
// raise the event. AutomationPeer by itself doesn't hook up to the
// eventing mechanism, we need the FrameworkAutomationPeer to do that.
// Arguments:
// - <none>
// Return Value:
// - <none>
void InteractivityAutomationPeer::SignalCursorChanged()
{
_CursorChangedHandlers(*this, nullptr);
}
#pragma region ITextProvider
com_array<XamlAutomation::ITextRangeProvider> InteractivityAutomationPeer::GetSelection()
{
SAFEARRAY* pReturnVal;
THROW_IF_FAILED(_uiaProvider->GetSelection(&pReturnVal));
return WrapArrayOfTextRangeProviders(pReturnVal);
}
com_array<XamlAutomation::ITextRangeProvider> InteractivityAutomationPeer::GetVisibleRanges()
{
SAFEARRAY* pReturnVal;
THROW_IF_FAILED(_uiaProvider->GetVisibleRanges(&pReturnVal));
return WrapArrayOfTextRangeProviders(pReturnVal);
}
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::RangeFromChild(XamlAutomation::IRawElementProviderSimple childElement)
{
UIA::ITextRangeProvider* returnVal;
// ScreenInfoUiaProvider doesn't actually use parameter, so just pass in nullptr
THROW_IF_FAILED(_uiaProvider->RangeFromChild(/* IRawElementProviderSimple */ nullptr,
&returnVal));
const auto parentProvider = this->ProviderFromPeer(*this);
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
return xutr.as<XamlAutomation::ITextRangeProvider>();
}
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
{
UIA::ITextRangeProvider* returnVal;
THROW_IF_FAILED(_uiaProvider->RangeFromPoint({ screenLocation.X, screenLocation.Y }, &returnVal));
const auto parentProvider = this->ProviderFromPeer(*this);
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
return xutr.as<XamlAutomation::ITextRangeProvider>();
}
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::DocumentRange()
{
UIA::ITextRangeProvider* returnVal;
THROW_IF_FAILED(_uiaProvider->get_DocumentRange(&returnVal));
const auto parentProvider = this->ProviderFromPeer(*this);
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
return xutr.as<XamlAutomation::ITextRangeProvider>();
}
XamlAutomation::SupportedTextSelection InteractivityAutomationPeer::SupportedTextSelection()
{
UIA::SupportedTextSelection returnVal;
THROW_IF_FAILED(_uiaProvider->get_SupportedTextSelection(&returnVal));
return static_cast<XamlAutomation::SupportedTextSelection>(returnVal);
}
#pragma endregion
#pragma region IControlAccessibilityInfo
COORD InteractivityAutomationPeer::GetFontSize() const
{
return til::size{ til::math::rounding, _interactivity->Core().FontSize() };
}
RECT InteractivityAutomationPeer::GetBounds() const
{
return _controlBounds;
}
HRESULT InteractivityAutomationPeer::GetHostUiaProvider(IRawElementProviderSimple** provider)
{
RETURN_HR_IF(E_INVALIDARG, provider == nullptr);
*provider = nullptr;
return S_OK;
}
RECT InteractivityAutomationPeer::GetPadding() const
{
return _controlPadding;
}
double InteractivityAutomationPeer::GetScaleFactor() const
{
return DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
}
void InteractivityAutomationPeer::ChangeViewport(const SMALL_RECT NewWindow)
{
_interactivity->UpdateScrollbar(NewWindow.Top);
}
#pragma endregion
// Method Description:
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
// Arguments:
// - SAFEARRAY of UIA::UiaTextRange (ITextRangeProviders)
// Return Value:
// - com_array of Xaml Wrapped UiaTextRange (ITextRangeProviders)
com_array<XamlAutomation::ITextRangeProvider> InteractivityAutomationPeer::WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges)
{
// transfer ownership of UiaTextRanges to this new vector
auto providers = SafeArrayToOwningVector<::Microsoft::Terminal::TermControlUiaTextRange>(textRanges);
int count = gsl::narrow<int>(providers.size());
std::vector<XamlAutomation::ITextRangeProvider> vec;
vec.reserve(count);
auto parentProvider = this->ProviderFromPeer(*this);
for (int i = 0; i < count; i++)
{
auto xutr = make_self<XamlUiaTextRange>(providers[i].detach(), parentProvider);
vec.emplace_back(xutr.as<XamlAutomation::ITextRangeProvider>());
}
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
return result;
}
}

View file

@ -0,0 +1,85 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- InteractivityAutomationPeer.h
Abstract:
- This module provides UI Automation access to the ControlInteractivity,
to support both automation tests and accessibility (screen
reading) applications.
- See TermControlAutomationPeer for more details on how UIA is implemented.
- This is the primary implementation of the ITextProvider interface, for the
TermControlAutomationPeer. The TermControlAutomationPeer will be attached to
the actual UI tree, via FrameworkElementAutomationPeer. However, the
ControlInteractivity is totally oblivious to the UI tree that might be hosting
it. So this class implements the actual text pattern for the buffer, because
it has access to the buffer. TermControlAutomationPeer can then call the
methods on this class to expose the implementation in the actual UI tree.
Author(s):
- Mike Griese (migrie), May 2021
--*/
#pragma once
#include "ControlInteractivity.h"
#include "InteractivityAutomationPeer.g.h"
#include "../types/TermControlUiaProvider.hpp"
#include "../types/IUiaEventDispatcher.h"
#include "../types/IControlAccessibilityInfo.h"
namespace winrt::Microsoft::Terminal::Control::implementation
{
struct InteractivityAutomationPeer :
public InteractivityAutomationPeerT<InteractivityAutomationPeer>,
::Microsoft::Console::Types::IUiaEventDispatcher,
::Microsoft::Console::Types::IControlAccessibilityInfo
{
public:
InteractivityAutomationPeer(Microsoft::Terminal::Control::implementation::ControlInteractivity* owner);
void SetControlBounds(const Windows::Foundation::Rect bounds);
void SetControlPadding(const Core::Padding padding);
#pragma region IUiaEventDispatcher
void SignalSelectionChanged() override;
void SignalTextChanged() override;
void SignalCursorChanged() override;
#pragma endregion
#pragma region ITextProvider Pattern
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider RangeFromPoint(Windows::Foundation::Point screenLocation);
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider RangeFromChild(Windows::UI::Xaml::Automation::Provider::IRawElementProviderSimple childElement);
com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> GetVisibleRanges();
com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> GetSelection();
Windows::UI::Xaml::Automation::SupportedTextSelection SupportedTextSelection();
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider DocumentRange();
#pragma endregion
#pragma region IControlAccessibilityInfo Pattern
// Inherited via IControlAccessibilityInfo
virtual COORD GetFontSize() const override;
virtual RECT GetBounds() const override;
virtual RECT GetPadding() const override;
virtual double GetScaleFactor() const override;
virtual void ChangeViewport(SMALL_RECT NewWindow) override;
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
#pragma endregion
TYPED_EVENT(SelectionChanged, IInspectable, IInspectable);
TYPED_EVENT(TextChanged, IInspectable, IInspectable);
TYPED_EVENT(CursorChanged, IInspectable, IInspectable);
private:
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
til::rectangle _controlBounds{};
til::rectangle _controlPadding{};
winrt::com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges);
};
}

View file

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Control
{
[default_interface] runtimeclass InteractivityAutomationPeer :
Windows.UI.Xaml.Automation.Peers.AutomationPeer,
Windows.UI.Xaml.Automation.Provider.ITextProvider
{
void SetControlBounds(Windows.Foundation.Rect bounds);
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
event Windows.Foundation.TypedEventHandler<Object, Object> SelectionChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> TextChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> CursorChanged;
}
}

View file

@ -8,7 +8,6 @@
#include <unicode.hpp>
#include <Utf16Parser.hpp>
#include <Utils.h>
#include <WinUser.h>
#include <LibraryResources.h>
#include "../../types/inc/GlyphWidth.hpp"
#include "../../types/inc/Utils.hpp"
@ -44,10 +43,17 @@ constexpr const auto TerminalWarningBellInterval = std::chrono::milliseconds(100
DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::CopyFormat);
DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::MouseButtonState);
namespace winrt::Microsoft::Terminal::Control::implementation
{
TermControl::TermControl(IControlSettings settings,
TerminalConnection::ITerminalConnection connection) :
TermControl(winrt::guid{}, settings, connection) {}
TermControl::TermControl(winrt::guid contentGuid,
IControlSettings settings,
TerminalConnection::ITerminalConnection connection) :
_initializedTerminal{ false },
_settings{ settings },
_closing{ false },
@ -62,33 +68,45 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
InitializeComponent();
_interactivity = winrt::make_self<ControlInteractivity>(settings, connection);
_core = _interactivity->GetCore();
if (contentGuid != winrt::guid{})
{
_contentProc = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
if (_contentProc != nullptr)
{
_interactivity = _contentProc.GetInteractivity();
}
}
if (_interactivity == nullptr)
{
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
}
_core = _interactivity.Core();
// Use a manual revoker on the output event, so we can immediately stop
// worrying about it on destruction.
_coreOutputEventToken = _core->ReceivedOutput({ this, &TermControl::_coreReceivedOutput });
_coreOutputEventToken = _core.ReceivedOutput({ this, &TermControl::_coreReceivedOutput });
// These events might all be triggered by the connection, but that
// should be drained and closed before we complete destruction. So these
// are safe.
_core->ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged });
_core->WarningBell({ this, &TermControl::_coreWarningBell });
_core->CursorPositionChanged({ this, &TermControl::_CursorPositionChanged });
_core.ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged });
_core.WarningBell({ this, &TermControl::_coreWarningBell });
_core.CursorPositionChanged({ this, &TermControl::_CursorPositionChanged });
// This event is specifically triggered by the renderer thread, a BG thread. Use a weak ref here.
_core->RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState });
_core.RendererEnteredErrorState({ get_weak(), &TermControl::_RendererEnteredErrorState });
// These callbacks can only really be triggered by UI interactions. So
// they don't need weak refs - they can't be triggered unless we're
// alive.
_core->BackgroundColorChanged({ this, &TermControl::_BackgroundColorChangedHandler });
_core->FontSizeChanged({ this, &TermControl::_coreFontSizeChanged });
_core->TransparencyChanged({ this, &TermControl::_coreTransparencyChanged });
_core->RaiseNotice({ this, &TermControl::_coreRaisedNotice });
_core->HoveredHyperlinkChanged({ this, &TermControl::_hoveredHyperlinkChanged });
_interactivity->OpenHyperlink({ this, &TermControl::_HyperlinkHandler });
_interactivity->ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged });
_core.BackgroundColorChanged({ this, &TermControl::_BackgroundColorChangedHandler });
_core.FontSizeChanged({ this, &TermControl::_coreFontSizeChanged });
_core.TransparencyChanged({ this, &TermControl::_coreTransparencyChanged });
_core.RaiseNotice({ this, &TermControl::_coreRaisedNotice });
_core.HoveredHyperlinkChanged({ this, &TermControl::_hoveredHyperlinkChanged });
_interactivity.OpenHyperlink({ this, &TermControl::_HyperlinkHandler });
_interactivity.ScrollPositionChanged({ this, &TermControl::_ScrollPositionChanged });
// Initialize the terminal only once the swapchainpanel is loaded - that
// way, we'll be able to query the real pixel size it got on layout
@ -124,7 +142,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
[weakThis = get_weak()]() {
if (auto control{ weakThis.get() })
{
control->_core->UpdatePatternLocations();
control->_core.UpdatePatternLocations();
}
},
UpdatePatternLocationsInterval,
@ -185,16 +203,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// If a text is selected inside terminal, use it to populate the search box.
// If the search box already contains a value, it will be overridden.
if (_core->HasSelection())
if (_core.HasSelection())
{
// Currently we populate the search box only if a single line is selected.
// Empirically, multi-line selection works as well on sample scenarios,
// but since code paths differ, extra work is required to ensure correctness.
auto bufferText = _core->SelectedText(true);
if (bufferText.size() == 1)
auto bufferText = _core.SelectedText(true);
if (bufferText.Size() == 1)
{
const auto selectedLine{ til::at(bufferText, 0) };
_searchBox->PopulateTextbox(selectedLine.data());
const auto selectedLine{ bufferText.GetAt(0) };
_searchBox->PopulateTextbox(selectedLine);
}
}
@ -215,7 +233,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
else
{
_core->Search(_searchBox->TextBox().Text(), goForward, false);
_core.Search(_searchBox->TextBox().Text(), goForward, false);
}
}
@ -232,7 +250,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const bool goForward,
const bool caseSensitive)
{
_core->Search(text, goForward, caseSensitive);
_core.Search(text, goForward, caseSensitive);
}
// Method Description:
@ -301,7 +319,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
_core->UpdateSettings(_settings);
_core.UpdateSettings(_settings);
// Update our control settings
_ApplyUISettings(_settings);
@ -360,7 +378,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
foregroundBrush.Color(static_cast<til::color>(newAppearance.DefaultForeground()));
TSFInputControl().Foreground(foregroundBrush);
_core->UpdateAppearance(newAppearance);
_core.UpdateAppearance(newAppearance);
}
// Method Description:
@ -371,12 +389,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
void TermControl::SendInput(const winrt::hstring& wstr)
{
_core->SendInput(wstr);
_core.SendInput(wstr);
}
void TermControl::ToggleShaderEffects()
{
_core->ToggleShaderEffects();
_core.ToggleShaderEffects();
}
// Method Description:
@ -399,7 +417,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_changeBackgroundColor(bg);
// Apply padding as swapChainPanel's margin
auto newMargin = _ParseThicknessFromPadding(newSettings.Padding());
auto newMargin = ParseThicknessFromPadding(newSettings.Padding());
SwapChainPanel().Margin(newMargin);
TSFInputControl().Margin(newMargin);
@ -420,7 +438,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
ScrollBar().Visibility(Visibility::Visible);
}
_interactivity->UpdateSettings();
_interactivity.UpdateSettings();
if (_automationPeer)
{
_automationPeer.SetControlPadding(Core::Padding{ newMargin.Left,
newMargin.Top,
newMargin.Right,
newMargin.Bottom });
}
}
// Method Description:
@ -469,7 +494,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// GH#5098: Inform the engine of the new opacity of the default text background.
_core->SetBackgroundOpacity(::base::saturated_cast<float>(_settings.TintOpacity()));
_core.SetBackgroundOpacity(::base::saturated_cast<float>(_settings.TintOpacity()));
}
else
{
@ -477,7 +502,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
RootGrid().Background(solidColor);
// GH#5098: Inform the engine of the new opacity of the default text background.
_core->SetBackgroundOpacity(1.0f);
_core.SetBackgroundOpacity(1.0f);
}
}
@ -490,7 +515,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_BackgroundColorChangedHandler(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
{
til::color newBgColor{ _core->BackgroundColor() };
til::color newBgColor{ _core.BackgroundColor() };
_changeBackgroundColor(newBgColor);
}
@ -525,37 +550,26 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Return Value:
// - The automation peer for our control
Windows::UI::Xaml::Automation::Peers::AutomationPeer TermControl::OnCreateAutomationPeer()
try
{
if (_initializedTerminal && !_closing) // only set up the automation peer if we're ready to go live
{
// create a custom automation peer with this code pattern:
// (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers)
auto autoPeer = winrt::make_self<implementation::TermControlAutomationPeer>(this);
_uiaEngine = std::make_unique<::Microsoft::Console::Render::UiaEngine>(autoPeer.get());
_core->AttachUiaEngine(_uiaEngine.get());
_automationPeer = *autoPeer;
return _automationPeer;
if (const auto& interactivityAutoPeer{ _interactivity.OnCreateAutomationPeer() })
{
auto autoPeer = winrt::make_self<implementation::TermControlAutomationPeer>(this, interactivityAutoPeer);
_automationPeer = *autoPeer;
return *autoPeer;
}
}
return nullptr;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
return nullptr;
}
::Microsoft::Console::Types::IUiaData* TermControl::GetUiaData() const
{
return _core->GetUiaData();
}
// This is needed for TermControlAutomationPeer. We probably could find a
// clever way around asking the core for this.
til::point TermControl::GetFontSize() const
{
return _core->GetFont().GetSize();
return til::point{ til::math::rounding, _core.FontSize().Width, _core.FontSize().Height };
}
const Windows::UI::Xaml::Thickness TermControl::GetPadding()
@ -565,7 +579,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TerminalConnection::ConnectionState TermControl::ConnectionState() const
{
return _core->ConnectionState();
return _core.ConnectionState();
}
winrt::fire_and_forget TermControl::RenderEngineSwapChainChanged(IInspectable /*sender*/, IInspectable /*args*/)
@ -579,7 +593,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (auto control{ weakThis.get() })
{
const auto chainHandle = _core->GetSwapChainHandle();
// TODO! very good chance we leak this handle
const HANDLE chainHandle = reinterpret_cast<HANDLE>(control->_contentProc ?
control->_contentProc.RequestSwapChainHandle(GetCurrentProcessId()) :
control->_core.SwapChainHandle());
_AttachDxgiSwapChainToXaml(chainHandle);
}
}
@ -629,7 +646,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle)
{
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative2>();
nativePanel->SetSwapChainHandle(swapChainHandle);
LOG_IF_FAILED(nativePanel->SetSwapChainHandle(swapChainHandle));
}
bool TermControl::_InitializeTerminal()
@ -656,23 +673,29 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// after Enable, then it'll be possible to paint the frame once
// _before_ the warning handler is set up, and then warnings from
// the first paint will be ignored!
_core->RendererWarning({ get_weak(), &TermControl::_RendererWarning });
_core.RendererWarning({ get_weak(), &TermControl::_RendererWarning });
const auto coreInitialized = _core->Initialize(panelWidth,
panelHeight,
panelScaleX);
if (!coreInitialized)
const bool inProc = _contentProc == nullptr;
const auto coreInitialized = _core.Initialize(panelWidth,
panelHeight,
panelScaleX);
if (!coreInitialized && inProc)
{
return false;
}
_interactivity->Initialize();
_interactivity.Initialize();
_AttachDxgiSwapChainToXaml(_core->GetSwapChainHandle());
// TODO! very good chance we leak this handle
const HANDLE chainHandle = reinterpret_cast<HANDLE>(_contentProc ?
_contentProc.RequestSwapChainHandle(GetCurrentProcessId()) :
_core.SwapChainHandle());
_AttachDxgiSwapChainToXaml(chainHandle);
// 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)
_core->SwapChainChanged({ get_weak(), &TermControl::RenderEngineSwapChainChanged });
_core.SwapChainChanged({ get_weak(), &TermControl::RenderEngineSwapChainChanged });
// !! LOAD BEARING !!
// Make sure you enable painting _AFTER_ calling _AttachDxgiSwapChainToXaml
@ -682,9 +705,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// issues where the Renderer starts trying to paint before we've
// actually attached the swapchain to anything, and the DxEngine is not
// prepared to handle that.
_core->EnablePainting();
_core.EnablePainting();
auto bufferHeight = _core->BufferHeight();
auto bufferHeight = _core.BufferHeight();
ScrollBar().Maximum(bufferHeight - bufferHeight);
ScrollBar().Minimum(0);
@ -761,7 +784,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
modifiers |= ControlKeyStates::EnhancedKey;
}
const bool handled = _core->SendCharEvent(ch, scanCode, modifiers);
const bool handled = _core.SendCharEvent(ch, scanCode, modifiers);
e.Handled(handled);
}
@ -773,7 +796,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool TermControl::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
{
// Short-circuit isReadOnly check to avoid warning dialog
if (_core->IsInReadOnlyMode())
if (_core.IsInReadOnlyMode())
{
return false;
}
@ -859,7 +882,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
// Short-circuit isReadOnly check to avoid warning dialog
if (_core->IsInReadOnlyMode())
if (_core.IsInReadOnlyMode())
{
e.Handled(!keyDown || _TryHandleKeyBinding(vkey, scanCode, modifiers));
return;
@ -991,17 +1014,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// This will prevent the system from trying to get the character out
// of it and sending us a CharacterReceived event.
const auto handled = vkey ?
_core->TrySendKeyEvent(vkey,
scanCode,
modifiers,
keyDown) :
_core.TrySendKeyEvent(vkey,
scanCode,
modifiers,
keyDown) :
true;
if (_cursorTimer.has_value())
{
// Manually show the cursor when a key is pressed. Restarting
// the timer prevents flickering.
_core->CursorOn(true);
_core.CursorOn(true);
_cursorTimer.value().Start();
}
@ -1055,16 +1078,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
const auto contactRect = point.Properties().ContactRect();
auto anchor = til::point{ til::math::rounding, contactRect.X, contactRect.Y };
_interactivity->TouchPressed(anchor);
_interactivity.TouchPressed(anchor);
}
else
{
const auto cursorPosition = point.Position();
_interactivity->PointerPressed(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
point.Timestamp(),
ControlKeyStates{ args.KeyModifiers() },
_toTerminalOrigin(cursorPosition));
_interactivity.PointerPressed(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
point.Timestamp(),
ControlKeyStates{ args.KeyModifiers() },
_toTerminalOrigin(cursorPosition));
}
args.Handled(true);
@ -1099,11 +1122,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (type == Windows::Devices::Input::PointerDeviceType::Mouse ||
type == Windows::Devices::Input::PointerDeviceType::Pen)
{
_interactivity->PointerMoved(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()),
_focused,
pixelPosition);
_interactivity.PointerMoved(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()),
_focused,
pixelPosition);
if (_focused && point.Properties().IsLeftButtonPressed())
{
@ -1136,7 +1159,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto contactRect = point.Properties().ContactRect();
til::point newTouchPoint{ til::math::rounding, contactRect.X, contactRect.Y };
_interactivity->TouchMoved(newTouchPoint, _focused);
_interactivity.TouchMoved(newTouchPoint, _focused);
}
args.Handled(true);
@ -1167,14 +1190,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (type == Windows::Devices::Input::PointerDeviceType::Mouse ||
type == Windows::Devices::Input::PointerDeviceType::Pen)
{
_interactivity->PointerReleased(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()),
pixelPosition);
_interactivity.PointerReleased(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()),
pixelPosition);
}
else if (type == Windows::Devices::Input::PointerDeviceType::Touch)
{
_interactivity->TouchReleased();
_interactivity.TouchReleased();
}
_TryStopAutoScroll(ptr.PointerId());
@ -1202,10 +1225,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto point = args.GetCurrentPoint(*this);
auto result = _interactivity->MouseWheel(ControlKeyStates{ args.KeyModifiers() },
point.Properties().MouseWheelDelta(),
_toTerminalOrigin(point.Position()),
TermControl::GetPressedMouseButtons(point));
auto result = _interactivity.MouseWheel(ControlKeyStates{ args.KeyModifiers() },
point.Properties().MouseWheelDelta(),
_toTerminalOrigin(point.Position()),
TermControl::GetPressedMouseButtons(point));
if (result)
{
args.Handled(true);
@ -1229,10 +1252,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const bool rightButtonDown)
{
const auto modifiers = _GetPressedModifierKeys();
TerminalInput::MouseButtonState state{ leftButtonDown,
midButtonDown,
rightButtonDown };
return _interactivity->MouseWheel(modifiers, delta, _toTerminalOrigin(location), state);
Control::MouseButtonState state{};
WI_SetFlagIf(state, Control::MouseButtonState::IsLeftButtonDown, leftButtonDown);
WI_SetFlagIf(state, Control::MouseButtonState::IsMiddleButtonDown, midButtonDown);
WI_SetFlagIf(state, Control::MouseButtonState::IsRightButtonDown, rightButtonDown);
return _interactivity.MouseWheel(modifiers, delta, _toTerminalOrigin(location), state);
}
// Method Description:
@ -1280,7 +1306,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - none
void TermControl::ResetFontSize()
{
_core->ResetFontSize();
_core.ResetFontSize();
}
// Method Description:
@ -1289,7 +1315,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - fontSizeDelta: The amount to increase or decrease the font size by.
void TermControl::AdjustFontSize(int fontSizeDelta)
{
_core->AdjustFontSize(fontSizeDelta);
_core.AdjustFontSize(fontSizeDelta);
}
void TermControl::_ScrollbarChangeHandler(Windows::Foundation::IInspectable const& /*sender*/,
@ -1304,7 +1330,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
const auto newValue = args.NewValue();
_interactivity->UpdateScrollbar(newValue);
_interactivity.UpdateScrollbar(newValue);
// User input takes priority over terminal events so cancel
// any pending scroll bar update if the user scrolls.
@ -1450,10 +1476,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// GH#5421: Enable the UiaEngine before checking for the SearchBox
// That way, new selections are notified to automation clients.
if (_uiaEngine.get())
{
THROW_IF_FAILED(_uiaEngine->Enable());
}
_interactivity.GainFocus();
// If the searchbox is focused, we don't want TSFInputControl to think
// it has focus so it doesn't intercept IME input. We also don't want the
@ -1471,7 +1494,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_cursorTimer.has_value())
{
// When the terminal focuses, show the cursor immediately
_core->CursorOn(true);
_core.CursorOn(true);
_cursorTimer.value().Start();
}
@ -1480,8 +1503,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_blinkTimer.value().Start();
}
_interactivity->GainFocus();
// Only update the appearance here if an unfocused config exists -
// if an unfocused config does not exist then we never would have switched
// appearances anyway so there's no need to switch back upon gaining focus
@ -1507,10 +1528,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_focused = false;
if (_uiaEngine.get())
{
THROW_IF_FAILED(_uiaEngine->Disable());
}
_interactivity.LostFocus();
if (TSFInputControl() != nullptr)
{
@ -1520,7 +1538,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (_cursorTimer.has_value())
{
_cursorTimer.value().Stop();
_core->CursorOn(false);
_core.CursorOn(false);
}
if (_blinkTimer.has_value())
@ -1550,7 +1568,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
const auto newSize = e.NewSize();
_core->SizeChanged(newSize.Width, newSize.Height);
_core.SizeChanged(newSize.Width, newSize.Height);
if (_automationPeer)
{
_automationPeer.UpdateControlBounds();
}
}
// Method Description:
@ -1585,7 +1608,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
const auto scaleX = sender.CompositionScaleX();
_core->ScaleChanged(scaleX);
_core.ScaleChanged(scaleX);
}
// Method Description:
@ -1598,7 +1621,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
if (!_closing)
{
_core->BlinkCursor();
_core.BlinkCursor();
}
}
@ -1612,7 +1635,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
if (!_closing)
{
_core->BlinkAttributeTick();
_core.BlinkAttributeTick();
}
}
@ -1622,7 +1645,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - cursorPosition: in pixels, relative to the origin of the control
void TermControl::_SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition)
{
_interactivity->SetEndSelectionPoint(_toTerminalOrigin(cursorPosition));
_interactivity.SetEndSelectionPoint(_toTerminalOrigin(cursorPosition));
}
// Method Description:
@ -1669,7 +1692,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
hstring TermControl::Title()
{
return _core->Title();
return _core.Title();
}
hstring TermControl::GetProfileName() const
@ -1679,12 +1702,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
hstring TermControl::WorkingDirectory() const
{
return _core->WorkingDirectory();
return _core.WorkingDirectory();
}
bool TermControl::BracketedPasteEnabled() const noexcept
{
return _core->BracketedPasteEnabled();
return _core.BracketedPasteEnabled();
}
// Method Description:
@ -1702,21 +1725,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return false;
}
return _interactivity->CopySelectionToClipboard(singleLine, formats);
return _interactivity.CopySelectionToClipboard(singleLine, formats);
}
// Method Description:
// - Initiate a paste operation.
void TermControl::PasteTextFromClipboard()
{
_interactivity->RequestPasteTextFromClipboard();
_interactivity.RequestPasteTextFromClipboard();
}
void TermControl::Close()
{
if (!_closing.exchange(true))
{
_core->ReceivedOutput(_coreOutputEventToken);
_core.ReceivedOutput(_coreOutputEventToken);
_RestorePointerCursorHandlers(*this, nullptr);
@ -1733,7 +1756,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TSFInputControl().Close();
_autoScrollTimer.Stop();
_core->Close();
_core.Close();
}
}
@ -1746,9 +1769,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
ScrollBar().Value(viewTop);
}
int TermControl::ScrollOffset()
int TermControl::ScrollOffset() const
{
return _core->ScrollOffset();
return _core.ScrollOffset();
}
// Function Description:
@ -1757,7 +1780,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - The height of the terminal in lines of text
int TermControl::ViewHeight() const
{
return _core->ViewHeight();
return _core.ViewHeight();
}
int TermControl::BufferHeight() const
{
return _core.BufferHeight();
}
// Function Description:
@ -1856,7 +1884,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
double height = rows * fontSize.Y;
auto thickness = _ParseThicknessFromPadding(padding);
auto thickness = ParseThicknessFromPadding(padding);
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
width += scale * (thickness.Left + thickness.Right);
height += scale * (thickness.Top + thickness.Bottom);
@ -1874,8 +1902,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - The dimensions of a single character of this control, in DIPs
winrt::Windows::Foundation::Size TermControl::CharacterDimensions() const
{
const auto fontSize = _core->GetFont().GetSize();
return { gsl::narrow_cast<float>(fontSize.X), gsl::narrow_cast<float>(fontSize.Y) };
return _core.FontSize();
}
// Method Description:
@ -1891,9 +1918,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
if (_initializedTerminal)
{
const auto fontSize = _core->GetFont().GetSize();
double width = fontSize.X;
double height = fontSize.Y;
const auto fontSize = _core.FontSize();
double width = fontSize.Width;
double height = fontSize.Height;
// Reserve additional space if scrollbar is intended to be visible
if (_settings.ScrollState() == ScrollbarState::Visible)
{
@ -1936,8 +1963,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - A dimension that would be aligned to the character grid.
float TermControl::SnapDimensionToGrid(const bool widthOrHeight, const float dimension)
{
const auto fontSize = _core->GetFont().GetSize();
const auto fontDimension = widthOrHeight ? fontSize.X : fontSize.Y;
const auto fontSize = _core.FontSize();
const auto fontDimension = widthOrHeight ? fontSize.Width : fontSize.Height;
const auto padding = GetPadding();
auto nonTerminalArea = gsl::narrow_cast<float>(widthOrHeight ?
@ -1964,7 +1991,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Four Double values provide independent padding for 4 sides of the bounding rectangle
// Return Value:
// - Windows::UI::Xaml::Thickness object
Windows::UI::Xaml::Thickness TermControl::_ParseThicknessFromPadding(const hstring padding)
Windows::UI::Xaml::Thickness TermControl::ParseThicknessFromPadding(const hstring padding)
{
const wchar_t singleCharDelim = L',';
std::wstringstream tokenStream(padding.c_str());
@ -2097,7 +2124,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
_core->SendInput(text);
_core.SendInput(text);
}
// Method Description:
@ -2117,7 +2144,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
const til::point cursorPos = _core->CursorPosition();
const til::point cursorPos = _core.CursorPosition();
Windows::Foundation::Point p = { ::base::ClampedNumeric<float>(cursorPos.x()),
::base::ClampedNumeric<float>(cursorPos.y()) };
eventArgs.CurrentPosition(p);
@ -2133,11 +2160,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_FontInfoHandler(const IInspectable& /*sender*/,
const FontInfoEventArgs& eventArgs)
{
const auto fontInfo = _core->GetFont();
eventArgs.FontSize(CharacterDimensions());
eventArgs.FontFace(fontInfo.GetFaceName());
eventArgs.FontFace(_core.FontFaceName());
::winrt::Windows::UI::Text::FontWeight weight;
weight.Weight = static_cast<uint16_t>(fontInfo.GetWeight());
weight.Weight = _core.FontWeight();
eventArgs.FontWeight(weight);
}
@ -2179,7 +2205,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
try
{
Windows::Foundation::Uri link{ co_await e.DataView().GetApplicationLinkAsync() };
_core->PasteText(link.AbsoluteUri());
_core.PasteText(link.AbsoluteUri());
}
CATCH_LOG();
}
@ -2188,7 +2214,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
try
{
Windows::Foundation::Uri link{ co_await e.DataView().GetWebLinkAsync() };
_core->PasteText(link.AbsoluteUri());
_core.PasteText(link.AbsoluteUri());
}
CATCH_LOG();
}
@ -2197,7 +2223,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
try
{
auto text{ co_await e.DataView().GetTextAsync() };
_core->PasteText(text);
_core.PasteText(text);
}
CATCH_LOG();
}
@ -2238,7 +2264,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
allPaths += fullPath;
}
_core->PasteText(winrt::hstring{ allPaths });
_core.PasteText(winrt::hstring{ allPaths });
}
}
}
@ -2333,7 +2359,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
// It's already loaded if we get here, so just hide it.
RendererFailedNotice().Visibility(Visibility::Collapsed);
_core->ResumeRendering();
_core.ResumeRendering();
}
IControlSettings TermControl::Settings() const
@ -2352,7 +2378,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// hypothetical future where we allow an application to set the tab
// color with VT sequences like they're currently allowed to with the
// title.
return _core->TabColor();
return _core.TabColor();
}
// Method Description:
@ -2361,7 +2387,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - The taskbar state of this control
const size_t TermControl::TaskbarState() const noexcept
{
return _core->TaskbarState();
return _core.TaskbarState();
}
// Method Description:
@ -2370,7 +2396,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - The taskbar progress of this control
const size_t TermControl::TaskbarProgress() const noexcept
{
return _core->TaskbarProgress();
return _core.TaskbarProgress();
}
// Method Description:
@ -2379,15 +2405,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - True if the mode is read-only
bool TermControl::ReadOnly() const noexcept
{
return _core->IsInReadOnlyMode();
return _core.IsInReadOnlyMode();
}
// Method Description:
// - Toggles the read-only flag, raises event describing the value change
void TermControl::ToggleReadOnly()
{
_core->ToggleReadOnlyMode();
_ReadOnlyChangedHandlers(*this, winrt::box_value(_core->IsInReadOnlyMode()));
_core.ToggleReadOnlyMode();
_ReadOnlyChangedHandlers(*this, winrt::box_value(_core.IsInReadOnlyMode()));
}
// Method Description:
@ -2396,9 +2422,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Arguments:
// - sender: not used
// - args: event data
void TermControl::_PointerExitedHandler(Windows::Foundation::IInspectable const& /*sender*/, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& /*e*/)
void TermControl::_PointerExitedHandler(Windows::Foundation::IInspectable const& /*sender*/,
Windows::UI::Xaml::Input::PointerRoutedEventArgs const& /*e*/)
{
_core->UpdateHoveredCell(std::nullopt);
_core.ClearHoveredCell();
}
winrt::fire_and_forget TermControl::_hoveredHyperlinkChanged(IInspectable sender,
@ -2408,10 +2435,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
co_await resume_foreground(Dispatcher());
if (auto self{ weakThis.get() })
{
auto lastHoveredCell = _core->GetHoveredCell();
if (lastHoveredCell.has_value())
auto lastHoveredCell = _core.HoveredCell();
if (lastHoveredCell)
{
const auto uriText = _core->GetHoveredUriText();
const auto uriText = _core.HoveredUriText();
if (!uriText.empty())
{
// Update the tooltip with the URI
@ -2426,8 +2453,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Compute the location of the top left corner of the cell in DIPS
const til::size marginsInDips{ til::math::rounding, GetPadding().Left, GetPadding().Top };
const til::point startPos{ *lastHoveredCell };
const til::size fontSize{ _core->GetFont().GetSize() };
const til::point startPos{ lastHoveredCell.Value() };
const til::size fontSize{ til::math::rounding, _core.FontSize() };
const til::point posInPixels{ startPos * fontSize };
const til::point posInDIPs{ posInPixels / SwapChainPanel().CompositionScaleX() };
const til::point locationInDIPs{ posInDIPs + marginsInDips };
@ -2463,11 +2490,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_RaiseNoticeHandlers(*this, eventArgs);
}
TerminalInput::MouseButtonState TermControl::GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point)
Control::MouseButtonState TermControl::GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point)
{
return TerminalInput::MouseButtonState{ point.Properties().IsLeftButtonPressed(),
point.Properties().IsMiddleButtonPressed(),
point.Properties().IsRightButtonPressed() };
Control::MouseButtonState state{};
WI_SetFlagIf(state, Control::MouseButtonState::IsLeftButtonDown, point.Properties().IsLeftButtonPressed());
WI_SetFlagIf(state, Control::MouseButtonState::IsMiddleButtonDown, point.Properties().IsMiddleButtonPressed());
WI_SetFlagIf(state, Control::MouseButtonState::IsRightButtonDown, point.Properties().IsRightButtonPressed());
return state;
}
unsigned int TermControl::GetPointerUpdateKind(const winrt::Windows::UI::Input::PointerPoint point)

View file

@ -25,6 +25,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
struct TermControl : TermControlT<TermControl>
{
TermControl(winrt::guid contentGuid, IControlSettings settings, TerminalConnection::ITerminalConnection connection);
TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection);
winrt::fire_and_forget UpdateSettings();
@ -49,7 +50,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
TerminalConnection::ConnectionState ConnectionState() const;
int ScrollOffset();
int ScrollOffset() const;
int ViewHeight() const;
int BufferHeight() const;
@ -84,7 +85,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
~TermControl();
Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer();
::Microsoft::Console::Types::IUiaData* GetUiaData() const;
const Windows::UI::Xaml::Thickness GetPadding();
IControlSettings Settings() const;
@ -102,19 +102,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool ReadOnly() const noexcept;
void ToggleReadOnly();
static ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point);
static Control::MouseButtonState GetPressedMouseButtons(const winrt::Windows::UI::Input::PointerPoint point);
static unsigned int GetPointerUpdateKind(const winrt::Windows::UI::Input::PointerPoint point);
static Windows::UI::Xaml::Thickness ParseThicknessFromPadding(const hstring padding);
// -------------------------------- WinRT Events ---------------------------------
// clang-format off
WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs);
FORWARDED_TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs, _core, CopyToClipboard);
FORWARDED_TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs, _core, TitleChanged);
FORWARDED_TYPED_EVENT(TabColorChanged, IInspectable, IInspectable, _core, TabColorChanged);
FORWARDED_TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable, _core, TaskbarProgressChanged);
FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable, _core, ConnectionStateChanged);
FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs, _interactivity, PasteFromClipboard);
PROJECTED_FORWARDED_TYPED_EVENT(CopyToClipboard, IInspectable, Control::CopyToClipboardEventArgs, _core, CopyToClipboard);
PROJECTED_FORWARDED_TYPED_EVENT(TitleChanged, IInspectable, Control::TitleChangedEventArgs, _core, TitleChanged);
PROJECTED_FORWARDED_TYPED_EVENT(TabColorChanged, IInspectable, IInspectable, _core, TabColorChanged);
PROJECTED_FORWARDED_TYPED_EVENT(SetTaskbarProgress, IInspectable, IInspectable, _core, TaskbarProgressChanged);
PROJECTED_FORWARDED_TYPED_EVENT(ConnectionStateChanged, IInspectable, IInspectable, _core, ConnectionStateChanged);
PROJECTED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs, _interactivity, PasteFromClipboard);
TYPED_EVENT(OpenHyperlink, IInspectable, Control::OpenHyperlinkEventArgs);
TYPED_EVENT(RaiseNotice, IInspectable, Control::NoticeEventArgs);
@ -139,11 +141,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// IRenderEngine is accessed when ControlCore calls Renderer::TriggerTeardown.
// (C++ class members are destroyed in reverse order.)
// Further, the TermControlAutomationPeer must be destructed after _uiaEngine!
winrt::Windows::UI::Xaml::Automation::Peers::AutomationPeer _automationPeer{ nullptr };
std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine;
Control::TermControlAutomationPeer _automationPeer{ nullptr };
Control::ControlCore _core{ nullptr };
Control::ControlInteractivity _interactivity{ nullptr };
Control::ContentProcess _contentProc{ nullptr };
winrt::com_ptr<ControlCore> _core;
winrt::com_ptr<ControlInteractivity> _interactivity;
winrt::com_ptr<SearchBoxControl> _searchBox;
IControlSettings _settings;
@ -227,8 +229,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _TryStopAutoScroll(const uint32_t pointerId);
void _UpdateAutoScroll(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
static Windows::UI::Xaml::Thickness _ParseThicknessFromPadding(const hstring padding);
void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;

View file

@ -15,6 +15,10 @@ namespace Microsoft.Terminal.Control
IMouseWheelListener,
ICoreState
{
TermControl(Guid contentGuid,
IControlSettings settings,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
TermControl(IControlSettings settings,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);

View file

@ -30,13 +30,42 @@ namespace XamlAutomation
namespace winrt::Microsoft::Terminal::Control::implementation
{
TermControlAutomationPeer::TermControlAutomationPeer(winrt::Microsoft::Terminal::Control::implementation::TermControl* owner) :
TermControlAutomationPeer::TermControlAutomationPeer(TermControl* owner,
Control::InteractivityAutomationPeer impl) :
TermControlAutomationPeerT<TermControlAutomationPeer>(*owner), // pass owner to FrameworkElementAutomationPeer
_termControl{ owner }
_termControl{ owner },
_contentAutomationPeer{ impl }
{
THROW_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, _termControl->GetUiaData(), this));
UpdateControlBounds();
// Listen for UIA signalling events from the implementation. We need to
// be the one to actually raise these automation events, so they go
// through the UI tree correctly.
_contentAutomationPeer.SelectionChanged([this](auto&&, auto&&) { SignalSelectionChanged(); });
_contentAutomationPeer.TextChanged([this](auto&&, auto&&) { SignalTextChanged(); });
_contentAutomationPeer.CursorChanged([this](auto&&, auto&&) { SignalCursorChanged(); });
};
// Method Description:
// - Inform the interactivity layer about the bounds of the control.
// IControlAccessibilityInfo needs to know this information, but it cannot
// ask us directly.
// Arguments:
// - <none>
// Return Value:
// - <none>
void TermControlAutomationPeer::UpdateControlBounds()
{
// FrameworkElementAutomationPeer has this great GetBoundingRectangle
// method that's seemingly impossible to recreate just from the
// UserControl itself. Weird. But we can use it handily here!
_contentAutomationPeer.SetControlBounds(GetBoundingRectangle());
}
void TermControlAutomationPeer::SetControlPadding(const Core::Padding padding)
{
_contentAutomationPeer.SetControlPadding(padding);
}
// Method Description:
// - Signals the ui automation client that the terminal's selection has changed and should be updated
// Arguments:
@ -167,106 +196,36 @@ namespace winrt::Microsoft::Terminal::Control::implementation
#pragma region ITextProvider
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::GetSelection()
{
SAFEARRAY* pReturnVal;
THROW_IF_FAILED(_uiaProvider->GetSelection(&pReturnVal));
return WrapArrayOfTextRangeProviders(pReturnVal);
return _contentAutomationPeer.GetSelection();
}
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::GetVisibleRanges()
{
SAFEARRAY* pReturnVal;
THROW_IF_FAILED(_uiaProvider->GetVisibleRanges(&pReturnVal));
return WrapArrayOfTextRangeProviders(pReturnVal);
return _contentAutomationPeer.GetVisibleRanges();
}
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::RangeFromChild(XamlAutomation::IRawElementProviderSimple childElement)
{
UIA::ITextRangeProvider* returnVal;
// ScreenInfoUiaProvider doesn't actually use parameter, so just pass in nullptr
THROW_IF_FAILED(_uiaProvider->RangeFromChild(/* IRawElementProviderSimple */ nullptr,
&returnVal));
auto parentProvider = this->ProviderFromPeer(*this);
auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
return xutr.as<XamlAutomation::ITextRangeProvider>();
return _contentAutomationPeer.RangeFromChild(childElement);
}
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
{
UIA::ITextRangeProvider* returnVal;
THROW_IF_FAILED(_uiaProvider->RangeFromPoint({ screenLocation.X, screenLocation.Y }, &returnVal));
auto parentProvider = this->ProviderFromPeer(*this);
auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
return xutr.as<XamlAutomation::ITextRangeProvider>();
return _contentAutomationPeer.RangeFromPoint(screenLocation);
}
XamlAutomation::ITextRangeProvider TermControlAutomationPeer::DocumentRange()
{
UIA::ITextRangeProvider* returnVal;
THROW_IF_FAILED(_uiaProvider->get_DocumentRange(&returnVal));
auto parentProvider = this->ProviderFromPeer(*this);
auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
return xutr.as<XamlAutomation::ITextRangeProvider>();
return _contentAutomationPeer.DocumentRange();
}
XamlAutomation::SupportedTextSelection TermControlAutomationPeer::SupportedTextSelection()
{
UIA::SupportedTextSelection returnVal;
THROW_IF_FAILED(_uiaProvider->get_SupportedTextSelection(&returnVal));
return static_cast<XamlAutomation::SupportedTextSelection>(returnVal);
return _contentAutomationPeer.SupportedTextSelection();
}
#pragma endregion
#pragma region IControlAccessibilityInfo
COORD TermControlAutomationPeer::GetFontSize() const
{
return _termControl->GetFontSize();
}
RECT TermControlAutomationPeer::GetBounds() const
{
auto rect = GetBoundingRectangle();
return {
gsl::narrow_cast<LONG>(rect.X),
gsl::narrow_cast<LONG>(rect.Y),
gsl::narrow_cast<LONG>(rect.X + rect.Width),
gsl::narrow_cast<LONG>(rect.Y + rect.Height)
};
}
HRESULT TermControlAutomationPeer::GetHostUiaProvider(IRawElementProviderSimple** provider)
{
RETURN_HR_IF(E_INVALIDARG, provider == nullptr);
*provider = nullptr;
return S_OK;
}
RECT TermControlAutomationPeer::GetPadding() const
{
auto padding = _termControl->GetPadding();
return {
gsl::narrow_cast<LONG>(padding.Left),
gsl::narrow_cast<LONG>(padding.Top),
gsl::narrow_cast<LONG>(padding.Right),
gsl::narrow_cast<LONG>(padding.Bottom)
};
}
double TermControlAutomationPeer::GetScaleFactor() const
{
return DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
}
void TermControlAutomationPeer::ChangeViewport(const SMALL_RECT NewWindow)
{
_termControl->ScrollViewport(NewWindow.Top);
}
#pragma endregion
// Method Description:
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
// Arguments:

View file

@ -20,13 +20,17 @@ Abstract:
Author(s):
- Carlos Zamora (CaZamor) 2019
Modifications:
- May 2021: Pulled the core logic of ITextProvider implementation into the
InteractivityAutomationPeer, to support tab tear out.
--*/
#pragma once
#include "TermControl.h"
#include "ControlInteractivity.h"
#include "TermControlAutomationPeer.g.h"
#include <winrt/Microsoft.Terminal.Control.h>
#include "../types/TermControlUiaProvider.hpp"
#include "../types/IUiaEventDispatcher.h"
#include "../types/IControlAccessibilityInfo.h"
@ -35,11 +39,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
struct TermControlAutomationPeer :
public TermControlAutomationPeerT<TermControlAutomationPeer>,
::Microsoft::Console::Types::IUiaEventDispatcher,
::Microsoft::Console::Types::IControlAccessibilityInfo
::Microsoft::Console::Types::IUiaEventDispatcher
{
public:
TermControlAutomationPeer(Microsoft::Terminal::Control::implementation::TermControl* owner);
TermControlAutomationPeer(Microsoft::Terminal::Control::implementation::TermControl* owner,
Control::InteractivityAutomationPeer implementation);
void UpdateControlBounds();
void SetControlPadding(const Core::Padding padding);
#pragma region FrameworkElementAutomationPeer
hstring GetClassNameCore() const;
@ -67,21 +74,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider DocumentRange();
#pragma endregion
#pragma region IControlAccessibilityInfo Pattern
// Inherited via IControlAccessibilityInfo
virtual COORD GetFontSize() const override;
virtual RECT GetBounds() const override;
virtual RECT GetPadding() const override;
virtual double GetScaleFactor() const override;
virtual void ChangeViewport(SMALL_RECT NewWindow) override;
virtual HRESULT GetHostUiaProvider(IRawElementProviderSimple** provider) override;
#pragma endregion
RECT GetBoundingRectWrapped();
private:
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
winrt::Microsoft::Terminal::Control::implementation::TermControl* _termControl;
Control::InteractivityAutomationPeer _contentAutomationPeer;
winrt::com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges);
};
}

View file

@ -9,5 +9,8 @@ namespace Microsoft.Terminal.Control
Windows.UI.Xaml.Automation.Peers.FrameworkElementAutomationPeer,
Windows.UI.Xaml.Automation.Provider.ITextProvider
{
void UpdateControlBounds();
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
}
}

View file

@ -28,6 +28,9 @@
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="ContentProcess.h">
<DependentUpon>ContentProcess.idl</DependentUpon>
</ClInclude>
<ClInclude Include="ControlCore.h">
<DependentUpon>ControlCore.idl</DependentUpon>
</ClInclude>
@ -49,6 +52,9 @@
<ClInclude Include="TermControlAutomationPeer.h">
<DependentUpon>TermControlAutomationPeer.idl</DependentUpon>
</ClInclude>
<ClInclude Include="InteractivityAutomationPeer.h">
<DependentUpon>InteractivityAutomationPeer.idl</DependentUpon>
</ClInclude>
<ClInclude Include="ThrottledFunc.h" />
<ClInclude Include="TSFInputControl.h">
<DependentUpon>TSFInputControl.xaml</DependentUpon>
@ -60,6 +66,9 @@
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ContentProcess.cpp">
<DependentUpon>ContentProcess.idl</DependentUpon>
</ClCompile>
<ClCompile Include="ControlCore.cpp">
<DependentUpon>ControlCore.idl</DependentUpon>
</ClCompile>
@ -86,10 +95,14 @@
<ClCompile Include="TermControlAutomationPeer.cpp">
<DependentUpon>TermControlAutomationPeer.idl</DependentUpon>
</ClCompile>
<ClCompile Include="InteractivityAutomationPeer.cpp">
<DependentUpon>InteractivityAutomationPeer.idl</DependentUpon>
</ClCompile>
<ClCompile Include="XamlUiaTextRange.cpp" />
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<Midl Include="ContentProcess.idl" />
<Midl Include="ControlCore.idl" />
<Midl Include="ControlInteractivity.idl" />
<Midl Include="ICoreState.idl" />
@ -106,6 +119,7 @@
<DependentUpon>TermControl.xaml</DependentUpon>
</Midl>
<Midl Include="TermControlAutomationPeer.idl" />
<Midl Include="InteractivityAutomationPeer.idl" />
<Midl Include="IMouseWheelListener.idl" />
<Midl Include="TSFInputControl.idl">
<DependentUpon>TSFInputControl.xaml</DependentUpon>

View file

@ -57,4 +57,6 @@
TRACELOGGING_DECLARE_PROVIDER(g_hTerminalControlProvider);
#include <telemetry/ProjectTelemetry.h>
#include <WinUser.h>
#include "til.h"

View file

@ -82,6 +82,20 @@ public:
}
#endif
#ifdef WINRT_Microsoft_Terminal_Core_H
constexpr ControlKeyStates(const winrt::Microsoft::Terminal::Core::ControlKeyStates& projKeyStates) :
ControlKeyStates(projKeyStates.Value)
{
}
operator winrt::Microsoft::Terminal::Core::ControlKeyStates() const noexcept
{
winrt::Microsoft::Terminal::Core::ControlKeyStates ret;
ret.Value = _value;
return ret;
}
#endif
constexpr DWORD Value() const noexcept
{
return _value;

View file

@ -24,11 +24,38 @@ namespace Microsoft.Terminal.Core
UInt8 A;
};
// TerminalCore declares its own Color struct to avoid depending on
// Windows.UI. Windows.Foundation.Point also exists, but it's composed of
// floating-point coordinates, when we almost always need integer coordinates.
// It is supported by til::point for conversions in and out of WinRT land.
struct Point
{
Int32 X;
Int32 Y;
};
// Same thing here, but with padding. Can't use Windows.UI.Thickness, so
// we'll declare our own.
struct Padding {
Double Left;
Double Top;
Double Right;
Double Bottom;
};
// This is a projection of Microsoft::Terminal::Core::ControlKeyStates,
// for conversions in and out of WinRT land.
struct ControlKeyStates
{
UInt32 Value;
};
declare
{
// Forward declare this parameterized specialization so that it lives
// in TerminalCore instead of being flung to the winds of all IDL dependents.
interface Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>;
interface Windows.Foundation.IReference<Microsoft.Terminal.Core.Point>;
}
interface ICoreAppearance

View file

@ -260,8 +260,8 @@ namespace ControlUnitTests
// For this test, don't use any modifiers
const auto modifiers = ControlKeyStates();
const TerminalInput::MouseButtonState leftMouseDown{ true, false, false };
const TerminalInput::MouseButtonState noMouseDown{ false, false, false };
const Control::MouseButtonState leftMouseDown{ true, false, false };
const Control::MouseButtonState noMouseDown{ false, false, false };
const til::size fontSize{ 9, 21 };
@ -358,8 +358,8 @@ namespace ControlUnitTests
// For this test, don't use any modifiers
const auto modifiers = ControlKeyStates();
const TerminalInput::MouseButtonState leftMouseDown{ true, false, false };
const TerminalInput::MouseButtonState noMouseDown{ false, false, false };
const Control::MouseButtonState leftMouseDown{ true, false, false };
const Control::MouseButtonState noMouseDown{ false, false, false };
const til::size fontSize{ 9, 21 };
@ -444,7 +444,7 @@ namespace ControlUnitTests
const int delta = WHEEL_DELTA / 5;
const til::point mousePos{ 0, 0 };
TerminalInput::MouseButtonState state{ false, false, false };
Control::MouseButtonState state{ false, false, false };
interactivity->MouseWheel(modifiers, delta, mousePos, state); // 1/5
VERIFY_ARE_EQUAL(21, core->ScrollOffset());
@ -508,8 +508,8 @@ namespace ControlUnitTests
// For this test, don't use any modifiers
const auto modifiers = ControlKeyStates();
const TerminalInput::MouseButtonState leftMouseDown{ true, false, false };
const TerminalInput::MouseButtonState noMouseDown{ false, false, false };
const Control::MouseButtonState leftMouseDown{ true, false, false };
const Control::MouseButtonState noMouseDown{ false, false, false };
const til::size fontSize{ 9, 21 };

View file

@ -83,6 +83,96 @@ static bool _messageIsAltKeyup(const MSG& message)
return (message.message == WM_KEYUP || message.message == WM_SYSKEYUP) && message.wParam == VK_MENU;
}
static bool checkIfContentProcess(winrt::guid& contentProcessGuid)
{
std::vector<std::wstring> args;
if (auto commandline{ GetCommandLineW() })
{
int argc = 0;
// Get the argv, and turn them into a hstring array to pass to the app.
wil::unique_any<LPWSTR*, decltype(&::LocalFree), ::LocalFree> argv{ CommandLineToArgvW(commandline, &argc) };
if (argv)
{
for (auto& elem : wil::make_range(argv.get(), argc))
{
args.emplace_back(elem);
}
}
}
if (args.size() > 2 && args.at(1) == L"--content")
{
auto& guidString{ args.at(2) };
auto canConvert = guidString.length() == 38 && guidString.front() == '{' && guidString.back() == '}';
if (canConvert)
{
GUID result{};
THROW_IF_FAILED(IIDFromString(guidString.c_str(), &result));
contentProcessGuid = result;
return true;
}
}
return false;
}
std::mutex m;
std::condition_variable cv;
bool dtored = false;
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> 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)
{
winrt::Microsoft::Terminal::Control::ContentProcess strong{}; // = winrt::make<winrt::Microsoft::Terminal::Control::ContentProcess>();
winrt::weak_ref<winrt::Microsoft::Terminal::Control::ContentProcess> weak{ strong };
g_weak = 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;
};
static void doContentProcessThing(const winrt::guid& contentProcessGuid)
{
// !! LOAD BEARING !! - important to be a MTA
winrt::init_apartment();
DWORD registrationHostClass{};
check_hresult(CoRegisterClassObject(contentProcessGuid,
make<HostClassFactory>(contentProcessGuid).get(),
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&registrationHostClass));
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] { return dtored; });
}
int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
TraceLoggingRegister(g_hWindowsTerminalProvider);
@ -109,6 +199,17 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
// Make sure to call this so we get WM_POINTER messages.
EnableMouseInPointer(true);
winrt::guid contentProcessGuid{};
if (checkIfContentProcess(contentProcessGuid))
{
doContentProcessThing(contentProcessGuid);
// If we were told to not have a window, exit early. Make sure to use
// ExitProcess to die here. If you try just `return 0`, then
// the XAML app host will crash during teardown. ExitProcess avoids
// that.
ExitProcess(0);
}
// !!! 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

View file

@ -96,6 +96,12 @@ public:
winrt::event_token name(Windows::Foundation::TypedEventHandler<sender, args> const& h) { return handler->handlerName(h); } \
void name(winrt::event_token const& token) noexcept { handler->handlerName(token); }
// Same thing, but handler is a projected type, not an implementation
#define PROJECTED_FORWARDED_TYPED_EVENT(name, sender, args, handler, handlerName) \
public: \
winrt::event_token name(Windows::Foundation::TypedEventHandler<sender, args> const& h) { return handler.handlerName(h); } \
void name(winrt::event_token const& token) noexcept { handler.handlerName(token); }
// Use this macro to quick implement both the getter and setter for a property.
// This should only be used for simple types where there's no logic in the
// getter/setter beyond just accessing/updating the value.

View file

@ -338,6 +338,21 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
}
#endif
#ifdef WINRT_Microsoft_Terminal_Core_H
constexpr point(const winrt::Microsoft::Terminal::Core::Point& corePoint) :
point(corePoint.X, corePoint.Y)
{
}
operator winrt::Microsoft::Terminal::Core::Point() const noexcept
{
winrt::Microsoft::Terminal::Core::Point ret;
ret.X = x<int>();
ret.Y = y<int>();
return ret;
}
#endif
std::wstring to_string() const
{
return wil::str_printf<std::wstring>(L"(X:%td, Y:%td)", x(), y());

View file

@ -183,6 +183,14 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
}
// This template will convert to rectangle from anything that has a X, Y, Width, and Height field that are floating-point;
// a math type is required.
template<typename TilMath, typename TOther>
constexpr rectangle(TilMath, const TOther& other, std::enable_if_t<std::is_floating_point_v<decltype(std::declval<TOther>().X)> && std::is_floating_point_v<decltype(std::declval<TOther>().Y)> && std::is_floating_point_v<decltype(std::declval<TOther>().Width)> && std::is_floating_point_v<decltype(std::declval<TOther>().Height)>, int> /*sentinel*/ = 0) :
rectangle(til::point{ TilMath::template cast<ptrdiff_t>(other.X), TilMath::template cast<ptrdiff_t>(other.Y) }, til::size{ TilMath::template cast<ptrdiff_t>(other.Width), TilMath::template cast<ptrdiff_t>(other.Height) })
{
}
// This template will convert to rectangle from anything that has a left, top, right, and bottom field that are floating-point;
// a math type is required.
template<typename TilMath, typename TOther>
@ -875,6 +883,22 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
}
#endif
#ifdef WINRT_Microsoft_Terminal_Core_H
operator winrt::Microsoft::Terminal::Core::Padding() const noexcept
{
winrt::Microsoft::Terminal::Core::Padding ret;
THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(left()).AssignIfValid(&ret.Left));
THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(top()).AssignIfValid(&ret.Top));
THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(right()).AssignIfValid(&ret.Right));
THROW_HR_IF(E_ABORT, !base::MakeCheckedNum(bottom()).AssignIfValid(&ret.Bottom));
return ret;
}
constexpr rectangle(const winrt::Microsoft::Terminal::Core::Padding& padding) :
rectangle(til::math::rounding, padding)
{
}
#endif
std::wstring to_string() const
{
return wil::str_printf<std::wstring>(L"(L:%td, T:%td, R:%td, B:%td) [W:%td, H:%td]", left(), top(), right(), bottom(), width(), height());

View file

@ -21,7 +21,7 @@ rem Add nuget to PATH
set PATH=%PATH%%OPENCON%\dep\nuget;
rem Run nuget restore so you can use vswhere
nuget restore %OPENCON% -Verbosity quiet
nuget restore %OPENCON%\OpenConsole.sln -Verbosity quiet
rem Find vswhere
rem from https://github.com/microsoft/vs-setup-samples/blob/master/tools/vswhere.cmd