Compare commits
73 commits
main
...
dev/pabhoj
Author | SHA1 | Date | |
---|---|---|---|
eec8228924 | |||
1067d24986 | |||
ee358fad7f | |||
392be7bf37 | |||
f9fc1b0221 | |||
e2ec41fb9f | |||
ee6515bee1 | |||
f09e8cbafd | |||
6026c0e440 | |||
a1040b498c | |||
fab614cbfc | |||
e5d5669b30 | |||
840004f252 | |||
d7c5e7c13f | |||
44de0aa2d3 | |||
52c406d85c | |||
87e1ff0855 | |||
1335753337 | |||
7c57e627bf | |||
4254c62155 | |||
d8112e977d | |||
62131c02f7 | |||
74f600b0d2 | |||
1752f44af3 | |||
85f51adb9a | |||
f7c8a9acae | |||
1d37b71a61 | |||
3ecd86fefa | |||
730eafe33d | |||
b9451359b9 | |||
486642c52d | |||
a7d506b849 | |||
3a78622dc9 | |||
856486ec45 | |||
d2208fac43 | |||
3d75680f77 | |||
c6de9d5977 | |||
b028a04633 | |||
7fdef8789e | |||
051e0b0456 | |||
3eda960a8d | |||
9da26627ea | |||
bb66ec8292 | |||
f664608388 | |||
884c3f2e9d | |||
a91427a829 | |||
11772a05c9 | |||
8ac4140ad5 | |||
5cdd8610a0 | |||
89db208d76 | |||
a35c45cb9c | |||
4728a60718 | |||
e5df4d3e85 | |||
2bcbc45a5e | |||
b21255dbad | |||
758064c324 | |||
56d8e6a04c | |||
a4541a3d54 | |||
0c1d7365c4 | |||
5f822afb3b | |||
76efe47fac | |||
961f27ed42 | |||
6f5b499c62 | |||
f3dc0a230b | |||
d7a4c04099 | |||
b0959f10b6 | |||
74087d659a | |||
504c5c2110 | |||
e622876ab0 | |||
194f849448 | |||
bcf1720452 | |||
4a8d4b5396 | |||
ed00e4011b |
28
.github/actions/spelling/allow/allow.txt
vendored
28
.github/actions/spelling/allow/allow.txt
vendored
|
@ -1,10 +1,15 @@
|
|||
Apc
|
||||
apc
|
||||
calt
|
||||
ccmp
|
||||
changelog
|
||||
cybersecurity
|
||||
Apc
|
||||
clickable
|
||||
clig
|
||||
copyable
|
||||
dalet
|
||||
Dcs
|
||||
dcs
|
||||
Dcs
|
||||
dialytika
|
||||
dje
|
||||
downside
|
||||
|
@ -12,7 +17,10 @@ downsides
|
|||
dze
|
||||
dzhe
|
||||
Enum'd
|
||||
Fitt
|
||||
formattings
|
||||
ftp
|
||||
fvar
|
||||
geeksforgeeks
|
||||
ghe
|
||||
gje
|
||||
|
@ -24,9 +32,17 @@ hyperlinks
|
|||
img
|
||||
It'd
|
||||
kje
|
||||
liga
|
||||
lje
|
||||
locl
|
||||
lorem
|
||||
Llast
|
||||
Lmid
|
||||
Lorigin
|
||||
maxed
|
||||
mkmk
|
||||
mru
|
||||
noreply
|
||||
nje
|
||||
ogonek
|
||||
ok'd
|
||||
|
@ -34,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
|
||||
|
|
42
.github/actions/spelling/allow/apis.txt
vendored
42
.github/actions/spelling/allow/apis.txt
vendored
|
@ -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
|
||||
|
|
1
.github/actions/spelling/allow/fonts.txt
vendored
1
.github/actions/spelling/allow/fonts.txt
vendored
|
@ -7,3 +7,4 @@ Iosevka
|
|||
MDL
|
||||
Monofur
|
||||
Segoe
|
||||
wght
|
||||
|
|
8
.github/actions/spelling/allow/math.txt
vendored
8
.github/actions/spelling/allow/math.txt
vendored
|
@ -1,3 +1,11 @@
|
|||
atan
|
||||
CPrime
|
||||
HBar
|
||||
HPrime
|
||||
isnan
|
||||
LPrime
|
||||
LStep
|
||||
powf
|
||||
RSub
|
||||
sqrtf
|
||||
ULP
|
||||
|
|
13
.github/actions/spelling/allow/microsoft.txt
vendored
13
.github/actions/spelling/allow/microsoft.txt
vendored
|
@ -1,5 +1,6 @@
|
|||
ACLs
|
||||
ADMINS
|
||||
advapi
|
||||
altform
|
||||
altforms
|
||||
appendwttlogging
|
||||
|
@ -15,6 +16,7 @@ CPLs
|
|||
cpptools
|
||||
cppvsdbg
|
||||
CPRs
|
||||
cryptbase
|
||||
DACL
|
||||
DACLs
|
||||
diffs
|
||||
|
@ -24,14 +26,20 @@ DTDs
|
|||
DWINRT
|
||||
enablewttlogging
|
||||
Intelli
|
||||
IVisual
|
||||
LKG
|
||||
LOCKFILE
|
||||
Lxss
|
||||
mfcribbon
|
||||
microsoft
|
||||
microsoftonline
|
||||
MSAA
|
||||
msixbundle
|
||||
MSVC
|
||||
muxc
|
||||
netcore
|
||||
osgvsowi
|
||||
PFILETIME
|
||||
pgc
|
||||
pgo
|
||||
pgosweep
|
||||
|
@ -39,10 +47,14 @@ powerrename
|
|||
powershell
|
||||
propkey
|
||||
pscustomobject
|
||||
QWORD
|
||||
regedit
|
||||
robocopy
|
||||
SACLs
|
||||
sdkddkver
|
||||
Shobjidl
|
||||
Skype
|
||||
SRW
|
||||
sxs
|
||||
Sysinternals
|
||||
sysnative
|
||||
|
@ -57,6 +69,7 @@ Virtualization
|
|||
visualstudio
|
||||
vscode
|
||||
VSTHRD
|
||||
winsdkver
|
||||
wlk
|
||||
wslpath
|
||||
wtl
|
||||
|
|
3
.github/actions/spelling/allow/names.txt
vendored
3
.github/actions/spelling/allow/names.txt
vendored
|
@ -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
|
||||
|
|
73
.github/actions/spelling/expect/expect.txt
vendored
73
.github/actions/spelling/expect/expect.txt
vendored
|
@ -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
|
||||
|
@ -185,9 +189,11 @@ cacafire
|
|||
callee
|
||||
capslock
|
||||
CARETBLINKINGENABLED
|
||||
carlos
|
||||
CARRIAGERETURN
|
||||
cascadia
|
||||
cassert
|
||||
castsi
|
||||
catid
|
||||
cazamor
|
||||
CBash
|
||||
|
@ -266,9 +272,12 @@ cmder
|
|||
CMDEXT
|
||||
Cmdlet
|
||||
cmdline
|
||||
cmh
|
||||
CMOUSEBUTTONS
|
||||
cmp
|
||||
cmpeq
|
||||
cmt
|
||||
cmw
|
||||
cmyk
|
||||
CNL
|
||||
cnt
|
||||
|
@ -378,6 +387,7 @@ cplusplus
|
|||
cpp
|
||||
CPPCORECHECK
|
||||
cppcorecheckrules
|
||||
cppm
|
||||
cpprest
|
||||
cpprestsdk
|
||||
cppwinrt
|
||||
|
@ -400,11 +410,13 @@ csbiex
|
|||
csharp
|
||||
CSHORT
|
||||
CSIDL
|
||||
Cspace
|
||||
csproj
|
||||
Csr
|
||||
csrmsg
|
||||
CSRSS
|
||||
csrutil
|
||||
css
|
||||
cstdarg
|
||||
cstddef
|
||||
cstdio
|
||||
|
@ -495,7 +507,6 @@ DEADCHAR
|
|||
dealloc
|
||||
Debian
|
||||
debolden
|
||||
debounce
|
||||
debugtype
|
||||
DECALN
|
||||
DECANM
|
||||
|
@ -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
|
||||
|
@ -1416,6 +1443,7 @@ MOUSEFIRST
|
|||
MOUSEHWHEEL
|
||||
MOUSEMOVE
|
||||
mousewheel
|
||||
movemask
|
||||
MOVESTART
|
||||
msb
|
||||
msbuild
|
||||
|
@ -1442,11 +1470,13 @@ MSVCRTD
|
|||
MSVS
|
||||
msys
|
||||
msysgit
|
||||
MTSM
|
||||
mui
|
||||
Mul
|
||||
multiline
|
||||
munged
|
||||
munges
|
||||
murmurhash
|
||||
mutex
|
||||
mutexes
|
||||
muxes
|
||||
|
@ -1497,6 +1527,7 @@ nfe
|
|||
nlength
|
||||
Nls
|
||||
NLSMODE
|
||||
nnn
|
||||
NOACTIVATE
|
||||
NOAPPLYNOW
|
||||
NOCLIP
|
||||
|
@ -1577,6 +1608,7 @@ NTVDM
|
|||
ntverp
|
||||
NTWIN
|
||||
nuget
|
||||
nullability
|
||||
nullness
|
||||
nullonfailure
|
||||
nullopt
|
||||
|
@ -1611,6 +1643,7 @@ onecoreuapuuid
|
|||
onecoreuuid
|
||||
ONECOREWINDOWS
|
||||
onehalf
|
||||
oneseq
|
||||
ONLCR
|
||||
openbash
|
||||
opencode
|
||||
|
@ -1641,6 +1674,7 @@ oss
|
|||
ostream
|
||||
ostringstream
|
||||
ouicompat
|
||||
OUnter
|
||||
outdir
|
||||
outfile
|
||||
Outof
|
||||
|
@ -1651,6 +1685,7 @@ Outptr
|
|||
OVERLAPPEDWINDOW
|
||||
OWNDC
|
||||
OWNERDRAWFIXED
|
||||
packagename
|
||||
packageuwp
|
||||
PACKCOORD
|
||||
PACKVERSION
|
||||
|
@ -1675,6 +1710,7 @@ pcch
|
|||
PCCHAR
|
||||
PCCONSOLE
|
||||
PCD
|
||||
pcg
|
||||
pch
|
||||
PCHAR
|
||||
PCIDLIST
|
||||
|
@ -1770,6 +1806,7 @@ POSX
|
|||
POSXSCROLL
|
||||
POSYSCROLL
|
||||
ppci
|
||||
PPEB
|
||||
ppf
|
||||
ppguid
|
||||
ppidl
|
||||
|
@ -1920,6 +1957,7 @@ realloc
|
|||
reamapping
|
||||
rects
|
||||
redef
|
||||
redefinable
|
||||
Redir
|
||||
redirector
|
||||
redist
|
||||
|
@ -1941,7 +1979,7 @@ REGSTR
|
|||
reingest
|
||||
Relayout
|
||||
RELBINPATH
|
||||
Remoting
|
||||
remoting
|
||||
renamer
|
||||
renderengine
|
||||
rendersize
|
||||
|
@ -1962,9 +2000,11 @@ resx
|
|||
retval
|
||||
rfa
|
||||
rfc
|
||||
rfid
|
||||
rftp
|
||||
rgb
|
||||
rgba
|
||||
RGBCOLOR
|
||||
rgbi
|
||||
rgci
|
||||
rgfae
|
||||
|
@ -1982,9 +2022,11 @@ rhs
|
|||
RIGHTALIGN
|
||||
RIGHTBUTTON
|
||||
riid
|
||||
Rike
|
||||
RIPMSG
|
||||
RIS
|
||||
RMENU
|
||||
rng
|
||||
roadmap
|
||||
robomac
|
||||
roundtrip
|
||||
|
@ -2030,7 +2072,6 @@ scanline
|
|||
schemename
|
||||
SCL
|
||||
scm
|
||||
scprintf
|
||||
SCRBUF
|
||||
SCRBUFSIZE
|
||||
screenbuffer
|
||||
|
@ -2062,7 +2103,7 @@ selectany
|
|||
SELECTEDFONT
|
||||
SELECTSTRING
|
||||
Selfhosters
|
||||
serializers
|
||||
SERIALIZERS
|
||||
SERVERDLL
|
||||
SETACTIVE
|
||||
SETBUDDYINT
|
||||
|
@ -2134,6 +2175,7 @@ SIGDN
|
|||
SINGLEFLAG
|
||||
SINGLETHREADED
|
||||
siup
|
||||
sixel
|
||||
SIZEBOX
|
||||
sizeof
|
||||
SIZESCROLL
|
||||
|
@ -2205,6 +2247,7 @@ stoi
|
|||
stol
|
||||
stoul
|
||||
stoutapot
|
||||
Stri
|
||||
strikethrough
|
||||
stringstream
|
||||
STRINGTABLE
|
||||
|
@ -2237,6 +2280,7 @@ SWMR
|
|||
SWP
|
||||
swprintf
|
||||
SYMED
|
||||
symlink
|
||||
SYNCPAINT
|
||||
sys
|
||||
syscalls
|
||||
|
@ -2303,7 +2347,6 @@ testmddefinition
|
|||
testmode
|
||||
testname
|
||||
testnameprefix
|
||||
testnetv
|
||||
TESTNULL
|
||||
testpass
|
||||
testpasses
|
||||
|
@ -2339,7 +2382,6 @@ TITLEISLINKNAME
|
|||
TJson
|
||||
TLambda
|
||||
TLEN
|
||||
Tlg
|
||||
Tlgdata
|
||||
TMAE
|
||||
TMPF
|
||||
|
@ -2414,7 +2456,6 @@ uapadmin
|
|||
UAX
|
||||
ubuntu
|
||||
ucd
|
||||
ucd
|
||||
ucdxml
|
||||
uch
|
||||
UCHAR
|
||||
|
@ -2523,6 +2564,7 @@ vcvarsall
|
|||
vcxitems
|
||||
vcxproj
|
||||
vec
|
||||
vectorized
|
||||
VERCTRL
|
||||
versioning
|
||||
VERTBAR
|
||||
|
@ -2540,13 +2582,13 @@ VMs
|
|||
VPA
|
||||
VPATH
|
||||
VPR
|
||||
VPrintf
|
||||
VProc
|
||||
VRaw
|
||||
VREDRAW
|
||||
vsc
|
||||
vscprintf
|
||||
VSCROLL
|
||||
vsdevshell
|
||||
vsinfo
|
||||
vsnprintf
|
||||
vso
|
||||
|
@ -2655,6 +2697,7 @@ WINDOWPOSCHANGING
|
|||
windowproc
|
||||
windowrect
|
||||
windowsapp
|
||||
windowsdeveloper
|
||||
windowsinternalstring
|
||||
WINDOWSIZE
|
||||
windowsx
|
||||
|
@ -2686,6 +2729,7 @@ wixproj
|
|||
wline
|
||||
wlinestream
|
||||
wmain
|
||||
wmemory
|
||||
WMSZ
|
||||
wnd
|
||||
WNDALLOC
|
||||
|
@ -2741,6 +2785,7 @@ WTo
|
|||
wtof
|
||||
wtoi
|
||||
WTs
|
||||
WTSOFTFONT
|
||||
wtw
|
||||
wtypes
|
||||
Wubi
|
||||
|
@ -2767,10 +2812,10 @@ XCount
|
|||
xdy
|
||||
XEncoding
|
||||
xes
|
||||
Xes
|
||||
xff
|
||||
XFile
|
||||
XFORM
|
||||
xIcon
|
||||
XManifest
|
||||
XMath
|
||||
XMFLOAT
|
||||
|
@ -2778,8 +2823,6 @@ xml
|
|||
xmlns
|
||||
xor
|
||||
xorg
|
||||
xorg
|
||||
Xpath
|
||||
XPosition
|
||||
XResource
|
||||
xsd
|
||||
|
@ -2805,6 +2848,7 @@ YCast
|
|||
YCENTER
|
||||
YCount
|
||||
YDPI
|
||||
yIcon
|
||||
yml
|
||||
YOffset
|
||||
YPosition
|
||||
|
@ -2812,6 +2856,7 @@ YSize
|
|||
YSubstantial
|
||||
YVIRTUALSCREEN
|
||||
YWalk
|
||||
zamora
|
||||
ZCmd
|
||||
ZCtrl
|
||||
zsh
|
||||
|
|
3
.github/actions/spelling/expect/web.txt
vendored
3
.github/actions/spelling/expect/web.txt
vendored
|
@ -1,5 +1,7 @@
|
|||
http
|
||||
www
|
||||
easyrgb
|
||||
php
|
||||
ecma
|
||||
rapidtables
|
||||
WCAG
|
||||
|
@ -11,6 +13,7 @@ leonerd
|
|||
fixterms
|
||||
winui
|
||||
appshellintegration
|
||||
mdtauk
|
||||
cppreference
|
||||
gfycat
|
||||
Guake
|
||||
|
|
|
@ -23,3 +23,5 @@ VERIFY_ARE_EQUAL\(L"[^"]+"
|
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
|
||||
std::memory_order_[\w]+
|
||||
D2DERR_SHADER_COMPILE_FAILED
|
||||
TIL_FEATURE_[0-9A-Z_]+
|
||||
vcvars\w*
|
||||
|
|
|
@ -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
|
45
src/cascadia/TerminalApp/IPane.idl
Normal file
45
src/cascadia/TerminalApp/IPane.idl
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "LeafPane.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
struct SnapSizeResult
|
||||
{
|
||||
Single lower;
|
||||
Single higher;
|
||||
};
|
||||
|
||||
interface IPane
|
||||
{
|
||||
void FocusPane(UInt32 idNum);
|
||||
void FocusFirstChild();
|
||||
UInt32 GetLeafPaneCount();
|
||||
IPane GetActivePane();
|
||||
IPane FindFirstLeaf();
|
||||
Boolean HasFocusedChild();
|
||||
|
||||
Boolean ContainsReadOnly();
|
||||
|
||||
Windows.UI.Xaml.Controls.Grid GetRootElement();
|
||||
|
||||
void Shutdown();
|
||||
void ClearActive();
|
||||
void UpdateSettings(Microsoft.Terminal.Settings.Model.TerminalSettingsCreateResult settings, Guid profile);
|
||||
|
||||
void ResizeContent(Windows.Foundation.Size newSize);
|
||||
Single CalcSnappedDimensionSingle(Boolean widthOrHeight, Single dimension);
|
||||
Windows.Foundation.Size GetMinSize();
|
||||
|
||||
void Maximize(IPane paneToZoom);
|
||||
void Restore(IPane paneToUnzoom);
|
||||
|
||||
Windows.Foundation.IReference<Microsoft.Terminal.Settings.Model.SplitState> PreCalculateAutoSplit(IPane target, Windows.Foundation.Size parentSize);
|
||||
Windows.Foundation.IReference<Boolean> PreCalculateCanSplit(IPane target, Microsoft.Terminal.Settings.Model.SplitState splitType, Single splitSize, Windows.Foundation.Size availableSpace);
|
||||
|
||||
SnapSizeResult CalcSnappedDimension(Boolean widthOrHeight, Single fullSize);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<IPane, IPane> PaneTypeChanged;
|
||||
}
|
||||
}
|
699
src/cascadia/TerminalApp/LeafPane.cpp
Normal file
699
src/cascadia/TerminalApp/LeafPane.cpp
Normal file
|
@ -0,0 +1,699 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "LeafPane.h"
|
||||
#include "AppLogic.h"
|
||||
|
||||
#include <Mmsystem.h>
|
||||
|
||||
#include "LeafPane.g.cpp"
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Graphics::Display;
|
||||
using namespace winrt::Windows::UI;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::UI::Xaml::Media;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
using namespace TerminalApp;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush LeafPane::s_focusedBorderBrush = { nullptr };
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush LeafPane::s_unfocusedBorderBrush = { nullptr };
|
||||
|
||||
static constexpr float Half = 0.50f;
|
||||
static const int PaneBorderSize = 2;
|
||||
static const int CombinedPaneBorderSize = 2 * PaneBorderSize;
|
||||
|
||||
LeafPane::LeafPane()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
LeafPane::LeafPane(const GUID& profile, const TermControl& control, const bool lastFocused) :
|
||||
_control{ control },
|
||||
_lastActive{ lastFocused },
|
||||
_profile{ profile }
|
||||
{
|
||||
InitializeComponent();
|
||||
GridBorder().Child(_control);
|
||||
|
||||
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &LeafPane::_ControlConnectionStateChangedHandler });
|
||||
_warningBellToken = _control.WarningBell({ this, &LeafPane::_ControlWarningBellHandler });
|
||||
|
||||
// On the Pane's creation, lookup resources we'll use to theme the
|
||||
// Pane, including the brushed to use for the focused/unfocused border
|
||||
// color.
|
||||
_SetupResources();
|
||||
|
||||
// Use the unfocused border color as the pane background, so an actual color
|
||||
// appears behind panes as we animate them sliding in.
|
||||
Root().Background(s_unfocusedBorderBrush);
|
||||
|
||||
// Register an event with the control to have it inform us when it gains focus.
|
||||
_gotFocusRevoker = control.GotFocus(winrt::auto_revoke, { this, &LeafPane::_ControlGotFocusHandler });
|
||||
_lostFocusRevoker = control.LostFocus(winrt::auto_revoke, { this, &LeafPane::_ControlLostFocusHandler });
|
||||
}
|
||||
|
||||
void LeafPane::BorderTappedHandler(winrt::Windows::Foundation::IInspectable const& /*sender*/,
|
||||
winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs const& e)
|
||||
{
|
||||
FocusFirstChild();
|
||||
e.Handled(true);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - If this is the last focused pane, returns itself
|
||||
// - This Pane's control might not currently be focused, if the tab itself is
|
||||
// not currently focused
|
||||
// Return Value:
|
||||
// - nullptr if we're unfocused, else returns this
|
||||
IPane LeafPane::GetActivePane()
|
||||
{
|
||||
return _lastActive ? IPane{ *this } : nullptr;
|
||||
}
|
||||
|
||||
IPane LeafPane::FindFirstLeaf()
|
||||
{
|
||||
return IPane{ *this };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the TermControl of this pane
|
||||
// Return Value:
|
||||
// - The TermControl of this LeafPane
|
||||
TermControl LeafPane::TerminalControl()
|
||||
{
|
||||
return _control;
|
||||
}
|
||||
|
||||
GUID LeafPane::Profile()
|
||||
{
|
||||
return _profile;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the root UIElement of this pane, which in our case just contains a border
|
||||
// with a Terminal Control in it
|
||||
// Return Value:
|
||||
// - the Grid acting as the root of this pane.
|
||||
Controls::Grid LeafPane::GetRootElement()
|
||||
{
|
||||
return Root();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns true if this pane was the last pane to be focused in a tree of panes.
|
||||
// Return Value:
|
||||
// - true iff we were the last pane focused in this tree of panes.
|
||||
bool LeafPane::WasLastFocused() const noexcept
|
||||
{
|
||||
return _lastActive;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update the focus state of this pane. We'll make sure to colorize our
|
||||
// borders depending on if we are the active pane or not.
|
||||
void LeafPane::UpdateVisuals()
|
||||
{
|
||||
GridBorder().BorderBrush(_lastActive ? s_focusedBorderBrush : s_unfocusedBorderBrush);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Remove the "Active" state from this Pane
|
||||
// - Updates our visuals to match our new state, including highlighting our borders
|
||||
void LeafPane::ClearActive()
|
||||
{
|
||||
_lastActive = false;
|
||||
UpdateVisuals();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the "Active" state on this Pane. Only one Pane in a tree of Panes
|
||||
// should be "active"
|
||||
// - Updates our visuals to match our new state, including highlighting our borders.
|
||||
void LeafPane::SetActive()
|
||||
{
|
||||
_lastActive = true;
|
||||
UpdateVisuals();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the settings of this pane if our profile guid matches the parameter
|
||||
// Arguments:
|
||||
// - settings: The new TerminalSettings to apply to any matching controls
|
||||
// - profile: The GUID of the profile these settings should apply to.
|
||||
void LeafPane::UpdateSettings(const TerminalSettingsCreateResult& settings, const GUID& profile)
|
||||
{
|
||||
if (profile == _profile)
|
||||
{
|
||||
auto controlSettings = _control.Settings().as<TerminalSettings>();
|
||||
// Update the parent of the control's settings object (and not the object itself) so
|
||||
// that any overrides made by the control don't get affected by the reload
|
||||
controlSettings.SetParent(settings.DefaultSettings());
|
||||
auto unfocusedSettings{ settings.UnfocusedSettings() };
|
||||
if (unfocusedSettings)
|
||||
{
|
||||
// Note: the unfocused settings needs to be entirely unchanged _except_ we need to
|
||||
// set its parent to the settings object that lives in the control. This is because
|
||||
// the overrides made by the control live in that settings object, so we want to make
|
||||
// sure the unfocused settings inherit from that.
|
||||
unfocusedSettings.SetParent(controlSettings);
|
||||
}
|
||||
_control.UnfocusedAppearance(unfocusedSettings);
|
||||
_control.UpdateSettings();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Focuses this pane if the given id matches ours
|
||||
// Arguments:
|
||||
// - The ID of the pane we want to focus
|
||||
void LeafPane::FocusPane(uint32_t id)
|
||||
{
|
||||
if (_Id == id)
|
||||
{
|
||||
_control.Focus(FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Focuses this control
|
||||
void LeafPane::FocusFirstChild()
|
||||
{
|
||||
if (Root().ActualWidth() == 0 && Root().ActualHeight() == 0)
|
||||
{
|
||||
// When these sizes are 0, then the pane might still be in startup,
|
||||
// and doesn't yet have a real size. In that case, the control.Focus
|
||||
// event won't be handled until _after_ the startup events are all
|
||||
// processed. This will lead to the Tab not being notified that the
|
||||
// focus moved to a different Pane.
|
||||
//
|
||||
// In that scenario, trigger the event manually here, to correctly
|
||||
// inform the Tab that we're now focused.
|
||||
_GotFocusHandlers(*this);
|
||||
}
|
||||
|
||||
_control.Focus(FocusState::Programmatic);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns true if this pane is currently focused
|
||||
// Return Value:
|
||||
// - true if the currently focused pane is this pane
|
||||
bool LeafPane::HasFocusedChild()
|
||||
{
|
||||
return _control && _lastActive;
|
||||
}
|
||||
|
||||
bool LeafPane::ContainsReadOnly()
|
||||
{
|
||||
return _control.ReadOnly();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Splits this pane, creating a new leaf pane and a parent pane
|
||||
// - The parent pane holds this pane and the newly created neighbour
|
||||
// - Emits an event with the new parent, so that whoever is listening
|
||||
// will replace us with our parent
|
||||
// Arguments:
|
||||
// - splitType: what type of split we want to create.
|
||||
// - profile: The profile GUID to associate with the newly created pane.
|
||||
// - control: A TermControl to use in the new pane.
|
||||
// Return Value:
|
||||
// - The newly created pane
|
||||
TerminalApp::LeafPane LeafPane::Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control)
|
||||
{
|
||||
splitType = _convertAutomaticSplitState(splitType);
|
||||
auto newNeighbour{ make<LeafPane>(profile, control, false) };
|
||||
|
||||
// Update the border of this pane and set appropriate border for the new leaf pane.
|
||||
if (splitType == SplitState::Vertical)
|
||||
{
|
||||
newNeighbour.Borders(_Borders | BordersEnum::Left);
|
||||
_Borders = _Borders | BordersEnum::Right;
|
||||
}
|
||||
else
|
||||
{
|
||||
newNeighbour.Borders(_Borders | BordersEnum::Top);
|
||||
_Borders = _Borders | BordersEnum::Bottom;
|
||||
}
|
||||
|
||||
UpdateBorders();
|
||||
newNeighbour.UpdateBorders();
|
||||
|
||||
if (WasLastFocused())
|
||||
{
|
||||
ClearActive();
|
||||
newNeighbour.SetActive();
|
||||
}
|
||||
|
||||
const auto newParent{ make<ParentPane>(*this, newNeighbour, splitType, 1.0f - splitSize) };
|
||||
|
||||
_PaneTypeChangedHandlers(nullptr, newParent);
|
||||
|
||||
newParent.InitializeChildren();
|
||||
|
||||
return newNeighbour;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Adjusts given dimension (width or height) so that we align with our character grid
|
||||
// as close as possible. Snaps to closes match (either upward or downward). Also makes
|
||||
// sure to fit in minimal sizes of the panes.
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true operates on width, otherwise on height
|
||||
// - dimension: a dimension (width or height) to snap
|
||||
// Return Value:
|
||||
// - A value corresponding to the next closest snap size for this Pane, either upward or downward
|
||||
float LeafPane::CalcSnappedDimensionSingle(const bool widthOrHeight, const float dimension) const
|
||||
{
|
||||
const auto [lower, higher] = CalcSnappedDimension(widthOrHeight, dimension);
|
||||
return dimension - lower < higher - dimension ? lower : higher;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Closes our attached control, preparing us to be removed from the UI tree
|
||||
void LeafPane::Shutdown()
|
||||
{
|
||||
_control.Close();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Fire our Closed event to tell our parent that we should be removed.
|
||||
void LeafPane::Close()
|
||||
{
|
||||
_ClosedHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
uint32_t LeafPane::GetLeafPaneCount() const noexcept
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - If this is the pane the caller wishes to zoom, we set our zoomed flag
|
||||
// and update our borders
|
||||
// Arguments:
|
||||
// - zoomedPane: This is the pane which we're attempting to zoom on.
|
||||
void LeafPane::Maximize(IPane paneToZoom)
|
||||
{
|
||||
_zoomed = (paneToZoom == *this);
|
||||
UpdateBorders();
|
||||
}
|
||||
|
||||
void LeafPane::Restore(IPane /*paneToUnzoom*/)
|
||||
{
|
||||
_zoomed = false;
|
||||
UpdateBorders();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the absolute minimum size that this pane can be resized to and still
|
||||
// have 1x1 character visible. Since we're a leaf, we'll
|
||||
// include the space needed for borders _within_ us.
|
||||
// Return Value:
|
||||
// - The minimum size that this pane can be resized to and still have a visible
|
||||
// character.
|
||||
Size LeafPane::GetMinSize() const
|
||||
{
|
||||
auto controlSize = _control.MinimumSize();
|
||||
auto newWidth = controlSize.Width;
|
||||
auto newHeight = controlSize.Height;
|
||||
|
||||
newWidth += WI_IsFlagSet(_Borders, BordersEnum::Left) ? PaneBorderSize : 0;
|
||||
newWidth += WI_IsFlagSet(_Borders, BordersEnum::Right) ? PaneBorderSize : 0;
|
||||
newHeight += WI_IsFlagSet(_Borders, BordersEnum::Top) ? PaneBorderSize : 0;
|
||||
newHeight += WI_IsFlagSet(_Borders, BordersEnum::Bottom) ? PaneBorderSize : 0;
|
||||
|
||||
return { newWidth, newHeight };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is a helper to determine which direction an "Automatic" split should
|
||||
// happen in for a given pane, but without using the ActualWidth() and
|
||||
// ActualHeight() methods. This is used during the initialization of the
|
||||
// Terminal, when we could be processing many "split-pane" commands _before_
|
||||
// we've ever laid out the Terminal for the first time. When this happens, the
|
||||
// Pane's don't have an actual size yet. However, we'd still like to figure
|
||||
// out how to do an "auto" split when these Panes are all laid out.
|
||||
// - This method assumes that the Pane we're attempting to split is `target`,
|
||||
// and this method should be called on the root of a tree of Panes.
|
||||
// - We'll walk down the tree attempting to find `target`. As we traverse the
|
||||
// tree, we'll reduce the size passed to each subsequent recursive call. The
|
||||
// size passed to this method represents how much space this Pane _will_ have
|
||||
// to use.
|
||||
// * If this pane is the pane we're looking for, use the
|
||||
// available space to calculate which direction to split in.
|
||||
// * If this pane is _any other leaf_, then just return nullopt, to indicate
|
||||
// that the `target` Pane is not down this branch.
|
||||
// Arguments:
|
||||
// - target: The Pane we're attempting to split.
|
||||
// - availableSpace: The theoretical space that's available for this pane to be able to split.
|
||||
// Return Value:
|
||||
// - nullopt if `target` is not this pane, otherwise the
|
||||
// SplitState that `target` would use for an `Automatic` split given
|
||||
// `availableSpace`
|
||||
IReference<SplitState> LeafPane::PreCalculateAutoSplit(const IPane target,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
if (winrt::get_self<implementation::LeafPane>(target) == this)
|
||||
{
|
||||
// Use the available space to calculate which direction to split in.
|
||||
return availableSpace.Width > availableSpace.Height ? SplitState::Vertical : SplitState::Horizontal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this pane is _any other leaf_, then just return nullptr, to
|
||||
// indicate that the `target` Pane is not down this branch.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is a helper to determine if a given Pane can be split, but without
|
||||
// using the ActualWidth() and ActualHeight() methods. This is used during
|
||||
// processing of many "split-pane" commands, which could happen _before_ we've
|
||||
// laid out a Pane for the first time. When this happens, the Pane's don't
|
||||
// have an actual size yet. However, we'd still like to figure out if the pane
|
||||
// could be split, once they're all laid out.
|
||||
// - This method assumes that the Pane we're attempting to split is `target`,
|
||||
// and this method should be called on the root of a tree of Panes.
|
||||
// - We'll walk down the tree attempting to find `target`. As we traverse the
|
||||
// tree, we'll reduce the size passed to each subsequent recursive call. The
|
||||
// size passed to this method represents how much space this Pane _will_ have
|
||||
// to use.
|
||||
// - If this pane is the pane we're looking for, use the
|
||||
// available space to calculate which direction to split in.
|
||||
// - If this pane is _any other leaf_, then just return nullopt, to indicate
|
||||
// that the `target` Pane is not down this branch.
|
||||
// Arguments:
|
||||
// - target: The Pane we're attempting to split.
|
||||
// - splitType: The direction we're attempting to split in.
|
||||
// - availableSpace: The theoretical space that's available for this pane to be able to split.
|
||||
// Return Value:
|
||||
// - nullopt if `target` is not this pane, otherwise
|
||||
// true iff we could split this pane, given `availableSpace`
|
||||
// Note:
|
||||
// - This method is highly similar to Pane::PreCalculateAutoSplit
|
||||
IReference<bool> LeafPane::PreCalculateCanSplit(const IPane target,
|
||||
SplitState splitType,
|
||||
const float splitSize,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
if (winrt::get_self<implementation::LeafPane>(target) == this)
|
||||
{
|
||||
const auto firstPrecent = 1.0f - splitSize;
|
||||
const auto secondPercent = splitSize;
|
||||
// If this pane is a leaf, and it's the pane we're looking for, use
|
||||
// the available space to calculate which direction to split in.
|
||||
const Size minSize = GetMinSize();
|
||||
|
||||
if (splitType == SplitState::None)
|
||||
{
|
||||
return { false };
|
||||
}
|
||||
else if (splitType == SplitState::Vertical)
|
||||
{
|
||||
const auto widthMinusSeparator = availableSpace.Width - CombinedPaneBorderSize;
|
||||
const auto newFirstWidth = widthMinusSeparator * firstPrecent;
|
||||
const auto newSecondWidth = widthMinusSeparator * secondPercent;
|
||||
|
||||
return { newFirstWidth > minSize.Width && newSecondWidth > minSize.Width };
|
||||
}
|
||||
else if (splitType == SplitState::Horizontal)
|
||||
{
|
||||
const auto heightMinusSeparator = availableSpace.Height - CombinedPaneBorderSize;
|
||||
const auto newFirstHeight = heightMinusSeparator * firstPrecent;
|
||||
const auto newSecondHeight = heightMinusSeparator * secondPercent;
|
||||
|
||||
return { newFirstHeight > minSize.Height && newSecondHeight > minSize.Height };
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this pane is _any other leaf_, then just return nullptr, to
|
||||
// indicate that the `target` Pane is not down this branch.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LeafPane::UpdateBorderWithClosedNeighbor(TerminalApp::LeafPane closedNeighbor, const ResizeDirection& neighborDirection)
|
||||
{
|
||||
// Set the border on the side we shared to the same state that the neighbour had.
|
||||
switch (neighborDirection)
|
||||
{
|
||||
case ResizeDirection::Up:
|
||||
WI_UpdateFlag(_Borders, BordersEnum::Top, WI_IsFlagSet(closedNeighbor.Borders(), BordersEnum::Top));
|
||||
break;
|
||||
case ResizeDirection::Down:
|
||||
WI_UpdateFlag(_Borders, BordersEnum::Bottom, WI_IsFlagSet(closedNeighbor.Borders(), BordersEnum::Bottom));
|
||||
break;
|
||||
case ResizeDirection::Left:
|
||||
WI_UpdateFlag(_Borders, BordersEnum::Left, WI_IsFlagSet(closedNeighbor.Borders(), BordersEnum::Left));
|
||||
break;
|
||||
case ResizeDirection::Right:
|
||||
WI_UpdateFlag(_Borders, BordersEnum::Right, WI_IsFlagSet(closedNeighbor.Borders(), BordersEnum::Right));
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateBorders();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when our attached control is closed. Triggers listeners to our close event
|
||||
void LeafPane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
{
|
||||
const auto newConnectionState = _control.ConnectionState();
|
||||
const auto previousConnectionState = std::exchange(_connectionState, newConnectionState);
|
||||
|
||||
if (newConnectionState < ConnectionState::Closed)
|
||||
{
|
||||
// Pane doesn't care if the connection isn't entering a terminal state.
|
||||
return;
|
||||
}
|
||||
|
||||
if (previousConnectionState < ConnectionState::Connected && newConnectionState >= ConnectionState::Failed)
|
||||
{
|
||||
// A failure to complete the connection (before it has _connected_) is not covered by "closeOnExit".
|
||||
// This is to prevent a misconfiguration (closeOnExit: always, startingDirectory: garbage) resulting
|
||||
// in Terminal flashing open and immediately closed.
|
||||
return;
|
||||
}
|
||||
|
||||
const auto settings{ winrt::TerminalApp::implementation::AppLogic::CurrentAppSettings() };
|
||||
auto paneProfile = settings.FindProfile(_profile);
|
||||
if (paneProfile)
|
||||
{
|
||||
auto mode = paneProfile.CloseOnExit();
|
||||
if ((mode == CloseOnExitMode::Always) ||
|
||||
(mode == CloseOnExitMode::Graceful && newConnectionState == ConnectionState::Closed))
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Plays a warning note when triggered by the BEL control character,
|
||||
// using the sound configured for the "Critical Stop" system event.`
|
||||
// This matches the behavior of the Windows Console host.
|
||||
// - Will also flash the taskbar if the bellStyle setting for this profile
|
||||
// has the 'visual' flag set
|
||||
void LeafPane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
const auto settings{ winrt::TerminalApp::implementation::AppLogic::CurrentAppSettings() };
|
||||
auto paneProfile = settings.FindProfile(_profile);
|
||||
if (paneProfile)
|
||||
{
|
||||
if (WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
|
||||
{
|
||||
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
|
||||
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
|
||||
}
|
||||
if (WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
|
||||
{
|
||||
_control.BellLightOn();
|
||||
}
|
||||
// Bubble this event up to app host, starting with bubbling to the hosting tab
|
||||
_PaneRaiseBellHandlers(nullptr, WI_IsFlagSet(paneProfile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Taskbar));
|
||||
}
|
||||
}
|
||||
|
||||
// Event Description:
|
||||
// - Called when our control gains focus. We'll use this to trigger our GotFocus
|
||||
// callback. The tab that's hosting us should have registered a callback which
|
||||
// can be used to mark us as active.
|
||||
void LeafPane::_ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable const& /* sender */,
|
||||
RoutedEventArgs const& /* args */)
|
||||
{
|
||||
_GotFocusHandlers(*this);
|
||||
}
|
||||
|
||||
void LeafPane::_ControlLostFocusHandler(winrt::Windows::Foundation::IInspectable const& /* sender */,
|
||||
RoutedEventArgs const& /* args */)
|
||||
{
|
||||
_LostFocusHandlers(*this);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the thickness of each side of our borders to match our _borders state.
|
||||
void LeafPane::UpdateBorders()
|
||||
{
|
||||
double top = 0, bottom = 0, left = 0, right = 0;
|
||||
|
||||
Thickness newBorders{ 0 };
|
||||
if (_zoomed)
|
||||
{
|
||||
// When the pane is zoomed, manually show all the borders around the window.
|
||||
top = bottom = right = left = PaneBorderSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WI_IsFlagSet(_Borders, BordersEnum::Top))
|
||||
{
|
||||
top = PaneBorderSize;
|
||||
}
|
||||
if (WI_IsFlagSet(_Borders, BordersEnum::Bottom))
|
||||
{
|
||||
bottom = PaneBorderSize;
|
||||
}
|
||||
if (WI_IsFlagSet(_Borders, BordersEnum::Left))
|
||||
{
|
||||
left = PaneBorderSize;
|
||||
}
|
||||
if (WI_IsFlagSet(_Borders, BordersEnum::Right))
|
||||
{
|
||||
right = PaneBorderSize;
|
||||
}
|
||||
}
|
||||
GridBorder().BorderThickness(ThicknessHelper::FromLengths(left, top, right, bottom));
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Attempts to load some XAML resources that the Pane will need. This includes:
|
||||
// * The Color we'll use for active Panes's borders - SystemAccentColor
|
||||
// * The Brush we'll use for inactive Panes - TabViewBackground (to match the
|
||||
// color of the titlebar)
|
||||
void LeafPane::_SetupResources()
|
||||
{
|
||||
const auto res = Application::Current().Resources();
|
||||
const auto accentColorKey = winrt::box_value(L"SystemAccentColor");
|
||||
if (res.HasKey(accentColorKey))
|
||||
{
|
||||
const auto colorFromResources = res.Lookup(accentColorKey);
|
||||
// If SystemAccentColor is _not_ a Color for some reason, use
|
||||
// Transparent as the color, so we don't do this process again on
|
||||
// the next pane (by leaving s_focusedBorderBrush nullptr)
|
||||
auto actualColor = winrt::unbox_value_or<Color>(colorFromResources, Colors::Black());
|
||||
s_focusedBorderBrush = SolidColorBrush(actualColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
s_focusedBorderBrush = SolidColorBrush{ Colors::Black() };
|
||||
}
|
||||
|
||||
const auto tabViewBackgroundKey = winrt::box_value(L"TabViewBackground");
|
||||
if (res.HasKey(tabViewBackgroundKey))
|
||||
{
|
||||
winrt::Windows::Foundation::IInspectable obj = res.Lookup(tabViewBackgroundKey);
|
||||
s_unfocusedBorderBrush = obj.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
s_unfocusedBorderBrush = SolidColorBrush{ Colors::Black() };
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Adjusts given dimension (width or height) so that we align with our character grid
|
||||
// as close as possible. Also makes sure to fit in minimal sizes of the pane
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true operates on width, otherwise on height
|
||||
// - dimension: a dimension (width or height) to be snapped
|
||||
// Return Value:
|
||||
// - pair of floats, where first value is the size snapped downward (not greater then
|
||||
// requested size) and second is the size snapped upward (not lower than requested size).
|
||||
// If requested size is already snapped, then both returned values equal this value.
|
||||
SnapSizeResult LeafPane::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
|
||||
{
|
||||
const auto minSize = GetMinSize();
|
||||
const auto minDimension = widthOrHeight ? minSize.Width : minSize.Height;
|
||||
|
||||
if (dimension <= minDimension)
|
||||
{
|
||||
return { minDimension, minDimension };
|
||||
}
|
||||
|
||||
float lower = _control.SnapDimensionToGrid(widthOrHeight, dimension);
|
||||
if (widthOrHeight)
|
||||
{
|
||||
lower += WI_IsFlagSet(_Borders, BordersEnum::Left) ? PaneBorderSize : 0;
|
||||
lower += WI_IsFlagSet(_Borders, BordersEnum::Right) ? PaneBorderSize : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lower += WI_IsFlagSet(_Borders, BordersEnum::Top) ? PaneBorderSize : 0;
|
||||
lower += WI_IsFlagSet(_Borders, BordersEnum::Bottom) ? PaneBorderSize : 0;
|
||||
}
|
||||
|
||||
if (lower == dimension)
|
||||
{
|
||||
// If we happen to be already snapped, then just return this size
|
||||
// as both lower and higher values.
|
||||
return { lower, lower };
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto cellSize = _control.CharacterDimensions();
|
||||
const auto higher = lower + (widthOrHeight ? cellSize.Width : cellSize.Height);
|
||||
return { lower, higher };
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Converts an "automatic" split type into either Vertical or Horizontal,
|
||||
// based upon the current dimensions of the Pane.
|
||||
// - If any of the other SplitState values are passed in, they're returned
|
||||
// unmodified.
|
||||
// Arguments:
|
||||
// - splitType: The SplitState to attempt to convert
|
||||
// Return Value:
|
||||
// - None if splitType was None, otherwise one of Horizontal or Vertical
|
||||
SplitState LeafPane::_convertAutomaticSplitState(const SplitState& splitType)
|
||||
{
|
||||
// Careful here! If the pane doesn't yet have a size, these dimensions will
|
||||
// be 0, and we'll always return Vertical.
|
||||
|
||||
if (splitType == SplitState::Automatic)
|
||||
{
|
||||
// If the requested split type was "auto", determine which direction to
|
||||
// split based on our current dimensions
|
||||
const Size actualSize{ gsl::narrow_cast<float>(Root().ActualWidth()),
|
||||
gsl::narrow_cast<float>(Root().ActualHeight()) };
|
||||
return actualSize.Width >= actualSize.Height ? SplitState::Vertical : SplitState::Horizontal;
|
||||
}
|
||||
return splitType;
|
||||
}
|
||||
|
||||
DEFINE_EVENT(LeafPane, GotFocus, _GotFocusHandlers, winrt::delegate<LeafPane>);
|
||||
DEFINE_EVENT(LeafPane, LostFocus, _LostFocusHandlers, winrt::delegate<LeafPane>);
|
||||
DEFINE_EVENT(LeafPane, PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);
|
||||
}
|
137
src/cascadia/TerminalApp/LeafPane.h
Normal file
137
src/cascadia/TerminalApp/LeafPane.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
// Module Name:
|
||||
// - LeafPane.h
|
||||
//
|
||||
// Abstract:
|
||||
// - Panes are an abstraction by which the terminal can display multiple terminal
|
||||
// instances simultaneously in a single terminal window. While tabs allow for
|
||||
// a single terminal window to have many terminal sessions running
|
||||
// simultaneously within a single window, only one tab can be visible at a
|
||||
// time. Panes, on the other hand, allow a user to have many different
|
||||
// terminal sessions visible to the user within the context of a single window
|
||||
// at the same time. This can enable greater productivity from the user, as
|
||||
// they can see the output of one terminal window while working in another.
|
||||
// - See doc/cascadia/Panes.md for a detailed description.
|
||||
// - Panes can be one of 2 types, parent or leaf. A parent pane contains 2 other panes
|
||||
// (each of which could itself be a parent or could be a leaf). A leaf pane contains
|
||||
// a terminal control.
|
||||
//
|
||||
// Author(s):
|
||||
// - Mike Griese (zadjii-msft) 16-May-2019
|
||||
// - Pankaj Bhojwani February-2021
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||
|
||||
#include "LeafPane.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
DEFINE_ENUM_FLAG_OPERATORS(BordersEnum);
|
||||
|
||||
struct LeafPane : LeafPaneT<LeafPane>
|
||||
{
|
||||
public:
|
||||
LeafPane();
|
||||
LeafPane(const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control,
|
||||
const bool lastFocused = false);
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::Grid GetRootElement();
|
||||
|
||||
IPane GetActivePane();
|
||||
IPane FindFirstLeaf();
|
||||
winrt::Microsoft::Terminal::Control::TermControl TerminalControl();
|
||||
GUID Profile();
|
||||
void FocusPane(uint32_t id);
|
||||
void FocusFirstChild();
|
||||
bool HasFocusedChild();
|
||||
|
||||
bool ContainsReadOnly();
|
||||
|
||||
bool WasLastFocused() const noexcept;
|
||||
void UpdateVisuals();
|
||||
void ClearActive();
|
||||
void SetActive();
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
||||
const GUID& profile);
|
||||
void ResizeContent(const winrt::Windows::Foundation::Size& /*newSize*/){};
|
||||
|
||||
TerminalApp::LeafPane Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
|
||||
float CalcSnappedDimensionSingle(const bool widthOrHeight, const float dimension) const;
|
||||
void Shutdown();
|
||||
void Close();
|
||||
uint32_t GetLeafPaneCount() const noexcept;
|
||||
|
||||
void Maximize(IPane paneToZoom);
|
||||
void Restore(IPane paneToUnZoom);
|
||||
|
||||
winrt::Windows::Foundation::Size GetMinSize() const;
|
||||
|
||||
winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Settings::Model::SplitState> PreCalculateAutoSplit(const IPane target,
|
||||
const winrt::Windows::Foundation::Size parentSize) const;
|
||||
winrt::Windows::Foundation::IReference<bool> PreCalculateCanSplit(const IPane target,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const;
|
||||
|
||||
void UpdateBorderWithClosedNeighbor(TerminalApp::LeafPane closedNeighbor, const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& neighborDirection);
|
||||
|
||||
SnapSizeResult CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
|
||||
void BorderTappedHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs const& e);
|
||||
|
||||
void UpdateBorders();
|
||||
|
||||
DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate<LeafPane>);
|
||||
DECLARE_EVENT(LostFocus, _LostFocusHandlers, winrt::delegate<LeafPane>);
|
||||
DECLARE_EVENT(PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);
|
||||
TYPED_EVENT(Closed, IPane, IPane);
|
||||
TYPED_EVENT(PaneTypeChanged, IPane, IPane);
|
||||
|
||||
WINRT_PROPERTY(uint32_t, Id);
|
||||
WINRT_PROPERTY(BordersEnum, Borders, BordersEnum::None);
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
|
||||
GUID _profile;
|
||||
bool _lastActive{ false };
|
||||
bool _zoomed{ false };
|
||||
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_unfocusedBorderBrush;
|
||||
|
||||
winrt::event_token _connectionStateChangedToken{ 0 };
|
||||
winrt::event_token _warningBellToken{ 0 };
|
||||
|
||||
winrt::Windows::UI::Xaml::UIElement::GotFocus_revoker _gotFocusRevoker;
|
||||
winrt::Windows::UI::Xaml::UIElement::LostFocus_revoker _lostFocusRevoker;
|
||||
|
||||
void _ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
|
||||
void _ControlWarningBellHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::Foundation::IInspectable const& e);
|
||||
void _ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void _ControlLostFocusHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
|
||||
static void _SetupResources();
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState _convertAutomaticSplitState(const winrt::Microsoft::Terminal::Settings::Model::SplitState& splitType);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(LeafPane);
|
||||
}
|
33
src/cascadia/TerminalApp/LeafPane.idl
Normal file
33
src/cascadia/TerminalApp/LeafPane.idl
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "IPane.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
enum BordersEnum
|
||||
{
|
||||
None = 0,
|
||||
Top = 1,
|
||||
Bottom = 2,
|
||||
Left = 4,
|
||||
Right = 8
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass LeafPane : Windows.UI.Xaml.Controls.UserControl, IPane
|
||||
{
|
||||
LeafPane(Guid profile, Microsoft.Terminal.Control.TermControl con, Boolean active);
|
||||
|
||||
UInt32 Id;
|
||||
BordersEnum Borders;
|
||||
Microsoft.Terminal.Control.TermControl TerminalControl { get; };
|
||||
Guid Profile { get; };
|
||||
|
||||
Boolean WasLastFocused();
|
||||
void SetActive();
|
||||
void Close();
|
||||
void UpdateBorders();
|
||||
void UpdateBorderWithClosedNeighbor(LeafPane closedNeighbor, Microsoft.Terminal.Settings.Model.ResizeDirection neighborDirection);
|
||||
LeafPane Split(Microsoft.Terminal.Settings.Model.SplitState splitType, Single splitSize, Guid profile, Microsoft.Terminal.Control.TermControl con);
|
||||
}
|
||||
}
|
21
src/cascadia/TerminalApp/LeafPane.xaml
Normal file
21
src/cascadia/TerminalApp/LeafPane.xaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
|
||||
<UserControl x:Class="TerminalApp.LeafPane"
|
||||
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:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
MinHeight="16"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid x:Name="Root">
|
||||
<Border x:Name="GridBorder"
|
||||
Tapped="BorderTappedHandler" />
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
|
@ -2,9 +2,11 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Pane.h"
|
||||
#include "ParentPane.h"
|
||||
|
||||
Pane::LayoutSizeNode::LayoutSizeNode(const float minSize) :
|
||||
using namespace winrt::TerminalApp::implementation;
|
||||
|
||||
ParentPane::LayoutSizeNode::LayoutSizeNode(const float minSize) :
|
||||
size{ minSize },
|
||||
isMinimumSize{ true },
|
||||
firstChild{ nullptr },
|
||||
|
@ -14,7 +16,7 @@ Pane::LayoutSizeNode::LayoutSizeNode(const float minSize) :
|
|||
{
|
||||
}
|
||||
|
||||
Pane::LayoutSizeNode::LayoutSizeNode(const LayoutSizeNode& other) :
|
||||
ParentPane::LayoutSizeNode::LayoutSizeNode(const LayoutSizeNode& other) :
|
||||
size{ other.size },
|
||||
isMinimumSize{ other.isMinimumSize },
|
||||
firstChild{ other.firstChild ? std::make_unique<LayoutSizeNode>(*other.firstChild) : nullptr },
|
||||
|
@ -32,7 +34,7 @@ Pane::LayoutSizeNode::LayoutSizeNode(const LayoutSizeNode& other) :
|
|||
// - other: Node to take the values from.
|
||||
// Return Value:
|
||||
// - itself
|
||||
Pane::LayoutSizeNode& Pane::LayoutSizeNode::operator=(const LayoutSizeNode& other)
|
||||
ParentPane::LayoutSizeNode& ParentPane::LayoutSizeNode::operator=(const LayoutSizeNode& other)
|
||||
{
|
||||
size = other.size;
|
||||
isMinimumSize = other.isMinimumSize;
|
||||
|
@ -53,7 +55,7 @@ Pane::LayoutSizeNode& Pane::LayoutSizeNode::operator=(const LayoutSizeNode& othe
|
|||
// - other: Node to take the values from.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Pane::LayoutSizeNode::_AssignChildNode(std::unique_ptr<LayoutSizeNode>& nodeField, const LayoutSizeNode* const newNode)
|
||||
void ParentPane::LayoutSizeNode::_AssignChildNode(std::unique_ptr<LayoutSizeNode>& nodeField, const LayoutSizeNode* const newNode)
|
||||
{
|
||||
if (newNode)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,239 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
// Module Name:
|
||||
// - Pane.h
|
||||
//
|
||||
// Abstract:
|
||||
// - Panes are an abstraction by which the terminal can display multiple terminal
|
||||
// instances simultaneously in a single terminal window. While tabs allow for
|
||||
// a single terminal window to have many terminal sessions running
|
||||
// simultaneously within a single window, only one tab can be visible at a
|
||||
// time. Panes, on the other hand, allow a user to have many different
|
||||
// terminal sessions visible to the user within the context of a single window
|
||||
// at the same time. This can enable greater productivity from the user, as
|
||||
// they can see the output of one terminal window while working in another.
|
||||
// - See doc/cascadia/Panes.md for a detailed description.
|
||||
//
|
||||
// Author:
|
||||
// - Mike Griese (zadjii-msft) 16-May-2019
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||
|
||||
enum class Borders : int
|
||||
{
|
||||
None = 0x0,
|
||||
Top = 0x1,
|
||||
Bottom = 0x2,
|
||||
Left = 0x4,
|
||||
Right = 0x8
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(Borders);
|
||||
|
||||
class Pane : public std::enable_shared_from_this<Pane>
|
||||
{
|
||||
public:
|
||||
Pane(const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control,
|
||||
const bool lastFocused = false);
|
||||
|
||||
std::shared_ptr<Pane> GetActivePane();
|
||||
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
|
||||
std::optional<GUID> GetFocusedProfile();
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::Grid GetRootElement();
|
||||
|
||||
bool WasLastFocused() const noexcept;
|
||||
void UpdateVisuals();
|
||||
void ClearActive();
|
||||
void SetActive();
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
||||
const GUID& profile);
|
||||
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
||||
void Relayout();
|
||||
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
bool NavigateFocus(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction);
|
||||
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitState> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
const winrt::Windows::Foundation::Size parentSize) const;
|
||||
std::optional<bool> PreCalculateCanSplit(const std::shared_ptr<Pane> target,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const;
|
||||
void Shutdown();
|
||||
void Close();
|
||||
|
||||
int GetLeafPaneCount() const noexcept;
|
||||
|
||||
void Maximize(std::shared_ptr<Pane> zoomedPane);
|
||||
void Restore(std::shared_ptr<Pane> zoomedPane);
|
||||
|
||||
std::optional<uint32_t> Id() noexcept;
|
||||
void Id(uint32_t id) noexcept;
|
||||
bool FocusPane(const uint32_t id);
|
||||
|
||||
bool ContainsReadOnly() const;
|
||||
|
||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
DECLARE_EVENT(LostFocus, _LostFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
DECLARE_EVENT(PaneRaiseBell, _PaneRaiseBellHandlers, winrt::Windows::Foundation::EventHandler<bool>);
|
||||
|
||||
private:
|
||||
struct SnapSizeResult;
|
||||
struct SnapChildrenSizeResult;
|
||||
struct LayoutSizeNode;
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::Grid _root{};
|
||||
winrt::Windows::UI::Xaml::Controls::Border _border{};
|
||||
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_unfocusedBorderBrush;
|
||||
|
||||
std::shared_ptr<Pane> _firstChild{ nullptr };
|
||||
std::shared_ptr<Pane> _secondChild{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState _splitState{ winrt::Microsoft::Terminal::Settings::Model::SplitState::None };
|
||||
float _desiredSplitPosition;
|
||||
|
||||
std::optional<uint32_t> _id;
|
||||
|
||||
bool _lastActive{ false };
|
||||
std::optional<GUID> _profile{ std::nullopt };
|
||||
winrt::event_token _connectionStateChangedToken{ 0 };
|
||||
winrt::event_token _firstClosedToken{ 0 };
|
||||
winrt::event_token _secondClosedToken{ 0 };
|
||||
winrt::event_token _warningBellToken{ 0 };
|
||||
|
||||
winrt::Windows::UI::Xaml::UIElement::GotFocus_revoker _gotFocusRevoker;
|
||||
winrt::Windows::UI::Xaml::UIElement::LostFocus_revoker _lostFocusRevoker;
|
||||
|
||||
std::shared_mutex _createCloseLock{};
|
||||
|
||||
Borders _borders{ Borders::None };
|
||||
|
||||
bool _zoomed{ false };
|
||||
|
||||
bool _IsLeaf() const noexcept;
|
||||
bool _HasFocusedChild() const noexcept;
|
||||
void _SetupChildCloseHandlers();
|
||||
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> _Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
|
||||
void _CreateRowColDefinitions();
|
||||
void _ApplySplitDefinitions();
|
||||
void _SetupEntranceAnimation();
|
||||
void _UpdateBorders();
|
||||
|
||||
bool _Resize(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
bool _NavigateFocus(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction);
|
||||
|
||||
void _CloseChild(const bool closeFirst);
|
||||
winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst);
|
||||
|
||||
void _FocusFirstChild();
|
||||
void _ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
|
||||
void _ControlWarningBellHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::Foundation::IInspectable const& e);
|
||||
void _ControlGotFocusHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void _ControlLostFocusHandler(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
|
||||
std::pair<float, float> _CalcChildrenSizes(const float fullSize) const;
|
||||
SnapChildrenSizeResult _CalcSnappedChildrenSizes(const bool widthOrHeight, const float fullSize) const;
|
||||
SnapSizeResult _CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
void _AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& sizeNode) const;
|
||||
|
||||
winrt::Windows::Foundation::Size _GetMinSize() const;
|
||||
LayoutSizeNode _CreateMinSizeTree(const bool widthOrHeight) const;
|
||||
float _ClampSplitPosition(const bool widthOrHeight, const float requestedValue, const float totalSize) const;
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState _convertAutomaticSplitState(const winrt::Microsoft::Terminal::Settings::Model::SplitState& splitType) const;
|
||||
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitState> _preCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const;
|
||||
|
||||
// Function Description:
|
||||
// - Returns true if the given direction can be used with the given split
|
||||
// type.
|
||||
// - This is used for pane resizing (which will need a pane separator
|
||||
// that's perpendicular to the direction to be able to move the separator
|
||||
// in that direction).
|
||||
// - Also used for moving focus between panes, which again happens _across_ a separator.
|
||||
// Arguments:
|
||||
// - direction: The Direction to compare
|
||||
// - splitType: The winrt::TerminalApp::SplitState to compare
|
||||
// Return Value:
|
||||
// - true iff the direction is perpendicular to the splitType. False for
|
||||
// winrt::TerminalApp::SplitState::None.
|
||||
template<typename T>
|
||||
static constexpr bool DirectionMatchesSplit(const T& direction,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::SplitState& splitType)
|
||||
{
|
||||
if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::Horizontal)
|
||||
{
|
||||
return direction == T::Up ||
|
||||
direction == T::Down;
|
||||
}
|
||||
else if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::Vertical)
|
||||
{
|
||||
return direction == T::Left ||
|
||||
direction == T::Right;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _SetupResources();
|
||||
|
||||
struct SnapSizeResult
|
||||
{
|
||||
float lower;
|
||||
float higher;
|
||||
};
|
||||
|
||||
struct SnapChildrenSizeResult
|
||||
{
|
||||
std::pair<float, float> lower;
|
||||
std::pair<float, float> higher;
|
||||
};
|
||||
|
||||
// Helper structure that builds a (roughly) binary tree corresponding
|
||||
// to the pane tree. Used for laying out panes with snapped sizes.
|
||||
struct LayoutSizeNode
|
||||
{
|
||||
float size;
|
||||
bool isMinimumSize;
|
||||
std::unique_ptr<LayoutSizeNode> firstChild;
|
||||
std::unique_ptr<LayoutSizeNode> secondChild;
|
||||
|
||||
// These two fields hold next possible snapped values of firstChild and
|
||||
// secondChild. Although that could be calculated from these fields themselves,
|
||||
// it would be wasteful as we have to know these values more often than for
|
||||
// simple increment. Hence we cache that here.
|
||||
std::unique_ptr<LayoutSizeNode> nextFirstChild;
|
||||
std::unique_ptr<LayoutSizeNode> nextSecondChild;
|
||||
|
||||
explicit LayoutSizeNode(const float minSize);
|
||||
LayoutSizeNode(const LayoutSizeNode& other);
|
||||
|
||||
LayoutSizeNode& operator=(const LayoutSizeNode& other);
|
||||
|
||||
private:
|
||||
void _AssignChildNode(std::unique_ptr<LayoutSizeNode>& nodeField, const LayoutSizeNode* const newNode);
|
||||
};
|
||||
};
|
1450
src/cascadia/TerminalApp/ParentPane.cpp
Normal file
1450
src/cascadia/TerminalApp/ParentPane.cpp
Normal file
File diff suppressed because it is too large
Load diff
191
src/cascadia/TerminalApp/ParentPane.h
Normal file
191
src/cascadia/TerminalApp/ParentPane.h
Normal file
|
@ -0,0 +1,191 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
// Module Name:
|
||||
// - ParentPane.h
|
||||
//
|
||||
// Abstract:
|
||||
// - Panes are an abstraction by which the terminal can display multiple terminal
|
||||
// instances simultaneously in a single terminal window. While tabs allow for
|
||||
// a single terminal window to have many terminal sessions running
|
||||
// simultaneously within a single window, only one tab can be visible at a
|
||||
// time. Panes, on the other hand, allow a user to have many different
|
||||
// terminal sessions visible to the user within the context of a single window
|
||||
// at the same time. This can enable greater productivity from the user, as
|
||||
// they can see the output of one terminal window while working in another.
|
||||
// - See doc/cascadia/Panes.md for a detailed description.
|
||||
// - Panes can be one of 2 types, parent or leaf. A parent pane contains 2 other panes
|
||||
// (each of which could itself be a parent or could be a leaf). A leaf pane contains
|
||||
// a terminal control.
|
||||
//
|
||||
// Author(s):
|
||||
// - Mike Griese (zadjii-msft) 16-May-2019
|
||||
// - Pankaj Bhojwani February-2021
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "inc/cppwinrt_utils.h"
|
||||
#include "LeafPane.h"
|
||||
|
||||
#include "ParentPane.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct ParentPane : ParentPaneT<ParentPane>
|
||||
{
|
||||
public:
|
||||
ParentPane(TerminalApp::LeafPane firstChild, TerminalApp::LeafPane secondChild, winrt::Microsoft::Terminal::Settings::Model::SplitState splitState, float splitPosition);
|
||||
winrt::Windows::UI::Xaml::Controls::Grid GetRootElement();
|
||||
void FocusPane(uint32_t id);
|
||||
void FocusFirstChild();
|
||||
bool HasFocusedChild();
|
||||
|
||||
bool ContainsReadOnly();
|
||||
|
||||
void InitializeChildren();
|
||||
|
||||
void Shutdown();
|
||||
void ClearActive();
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
|
||||
const GUID& profile);
|
||||
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
||||
void Relayout();
|
||||
IPane GetActivePane() const;
|
||||
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
bool NavigateFocus(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction);
|
||||
float CalcSnappedDimensionSingle(const bool widthOrHeight, const float dimension) const;
|
||||
uint32_t GetLeafPaneCount() const noexcept;
|
||||
winrt::Windows::Foundation::Size GetMinSize() const;
|
||||
|
||||
void Maximize(IPane paneToZoom);
|
||||
void Restore(IPane paneToUnzoom);
|
||||
|
||||
winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Settings::Model::SplitState> PreCalculateAutoSplit(const IPane target,
|
||||
const winrt::Windows::Foundation::Size parentSize) const;
|
||||
winrt::Windows::Foundation::IReference<bool> PreCalculateCanSplit(const IPane target,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const winrt::Windows::Foundation::Size availableSpace) const;
|
||||
|
||||
IPane FindFirstLeaf();
|
||||
|
||||
void PropagateToLeavesOnEdge(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& edge, std::function<void(TerminalApp::LeafPane)> action);
|
||||
SnapSizeResult CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
|
||||
TYPED_EVENT(PaneTypeChanged, IPane, IPane);
|
||||
|
||||
private:
|
||||
struct SnapChildrenSizeResult;
|
||||
struct LayoutSizeNode;
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_unfocusedBorderBrush;
|
||||
|
||||
IPane _firstChild;
|
||||
IPane _secondChild;
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState _splitState{ winrt::Microsoft::Terminal::Settings::Model::SplitState::None };
|
||||
float _desiredSplitPosition;
|
||||
winrt::event_token _firstClosedToken{ 0 };
|
||||
winrt::event_token _secondClosedToken{ 0 };
|
||||
winrt::event_token _firstTypeChangedToken{ 0 };
|
||||
winrt::event_token _secondTypeChangedToken{ 0 };
|
||||
|
||||
bool _firstLayoutUpdated{ false };
|
||||
bool _secondLayoutUpdated{ false };
|
||||
winrt::Microsoft::Terminal::Control::TermControl::LayoutUpdated_revoker _firstLayoutRevoker;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::LayoutUpdated_revoker _secondLayoutRevoker;
|
||||
|
||||
void _CreateRowColDefinitions();
|
||||
bool _Resize(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
bool _NavigateFocus(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction);
|
||||
|
||||
void _ChildrenLayoutUpdatedHelper(const bool isFirstChild);
|
||||
void _SetupEntranceAnimation();
|
||||
void _CloseChild(const bool closeFirst);
|
||||
winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst);
|
||||
|
||||
void _SetupChildEventHandlers(const bool isFirstChild);
|
||||
void _RemoveAllChildEventHandlers(const bool isFirstChild);
|
||||
|
||||
void _OnChildSplitOrCollapse(const bool isFirstChild, IPane newChild);
|
||||
|
||||
void _GridLayoutHelper() const noexcept;
|
||||
|
||||
std::pair<float, float> _CalcChildrenSizes(const float fullSize) const;
|
||||
SnapChildrenSizeResult _CalcSnappedChildrenSizes(const bool widthOrHeight, const float fullSize) const;
|
||||
LayoutSizeNode _CreateMinSizeTree(const bool widthOrHeight) const;
|
||||
float _ClampSplitPosition(const bool widthOrHeight, const float requestedValue, const float totalSize) const;
|
||||
void _AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& sizeNode) const;
|
||||
|
||||
void _SetupResources();
|
||||
|
||||
struct SnapChildrenSizeResult
|
||||
{
|
||||
std::pair<float, float> lower;
|
||||
std::pair<float, float> higher;
|
||||
};
|
||||
|
||||
// Helper structure that builds a (roughly) binary tree corresponding
|
||||
// to the pane tree. Used for laying out panes with snapped sizes.
|
||||
struct LayoutSizeNode
|
||||
{
|
||||
float size;
|
||||
bool isMinimumSize;
|
||||
std::unique_ptr<LayoutSizeNode> firstChild;
|
||||
std::unique_ptr<LayoutSizeNode> secondChild;
|
||||
|
||||
// These two fields hold next possible snapped values of firstChild and
|
||||
// secondChild. Although that could be calculated from these fields themselves,
|
||||
// it would be wasteful as we have to know these values more often than for
|
||||
// simple increment. Hence we cache that here.
|
||||
std::unique_ptr<LayoutSizeNode> nextFirstChild;
|
||||
std::unique_ptr<LayoutSizeNode> nextSecondChild;
|
||||
|
||||
explicit LayoutSizeNode(const float minSize);
|
||||
LayoutSizeNode(const LayoutSizeNode& other);
|
||||
|
||||
LayoutSizeNode& operator=(const LayoutSizeNode& other);
|
||||
|
||||
private:
|
||||
void _AssignChildNode(std::unique_ptr<LayoutSizeNode>& nodeField, const LayoutSizeNode* const newNode);
|
||||
};
|
||||
|
||||
// Function Description:
|
||||
// - Returns true if the given direction can be used with the given split
|
||||
// type.
|
||||
// - This is used for pane resizing (which will need a pane separator
|
||||
// that's perpendicular to the direction to be able to move the separator
|
||||
// in that direction).
|
||||
// - Also used for moving focus between panes, which again happens _across_ a separator.
|
||||
// Arguments:
|
||||
// - direction: The Direction to compare
|
||||
// - splitType: The winrt::TerminalApp::SplitState to compare
|
||||
// Return Value:
|
||||
// - true iff the direction is perpendicular to the splitType. False for
|
||||
// winrt::TerminalApp::SplitState::None.
|
||||
template<typename T>
|
||||
static constexpr bool DirectionMatchesSplit(const T& direction,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::SplitState& splitType)
|
||||
{
|
||||
if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::Horizontal)
|
||||
{
|
||||
return direction == T::Up ||
|
||||
direction == T::Down;
|
||||
}
|
||||
else if (splitType == winrt::Microsoft::Terminal::Settings::Model::SplitState::Vertical)
|
||||
{
|
||||
return direction == T::Left ||
|
||||
direction == T::Right;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(ParentPane);
|
||||
}
|
17
src/cascadia/TerminalApp/ParentPane.idl
Normal file
17
src/cascadia/TerminalApp/ParentPane.idl
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "IPane.idl";
|
||||
import "LeafPane.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass ParentPane : Windows.UI.Xaml.Controls.UserControl, IPane
|
||||
{
|
||||
ParentPane(LeafPane firstChild, LeafPane secondChild, Microsoft.Terminal.Settings.Model.SplitState splitState, Single splitPosition);
|
||||
void InitializeChildren();
|
||||
Boolean ResizePane(Microsoft.Terminal.Settings.Model.ResizeDirection direction);
|
||||
Boolean NavigateFocus(Microsoft.Terminal.Settings.Model.FocusDirection direction);
|
||||
void Relayout();
|
||||
}
|
||||
}
|
18
src/cascadia/TerminalApp/ParentPane.xaml
Normal file
18
src/cascadia/TerminalApp/ParentPane.xaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
|
||||
<UserControl x:Class="TerminalApp.ParentPane"
|
||||
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:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
MinHeight="16"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid x:Name="Root" />
|
||||
|
||||
</UserControl>
|
|
@ -638,11 +638,9 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
_UnZoomIfNeeded();
|
||||
|
||||
auto pane = terminalTab->GetActivePane();
|
||||
|
||||
if (const auto pane{ terminalTab->GetActivePane() })
|
||||
{
|
||||
if (const auto control{ pane->GetTerminalControl() })
|
||||
if (const auto control{ pane.TerminalControl() })
|
||||
{
|
||||
if (control.ReadOnly())
|
||||
{
|
||||
|
@ -661,7 +659,7 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
pane->Close();
|
||||
pane.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,12 @@
|
|||
<Page Include="CommandPalette.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="LeafPane.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="ParentPane.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
|
@ -123,7 +129,12 @@
|
|||
<ClInclude Include="EmptyStringVisibilityConverter.h">
|
||||
<DependentUpon>EmptyStringVisibilityConverter.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Pane.h" />
|
||||
<ClInclude Include="LeafPane.h">
|
||||
<DependentUpon>LeafPane.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ParentPane.h">
|
||||
<DependentUpon>ParentPane.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ColorHelper.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="ShortcutActionDispatch.h">
|
||||
|
@ -206,7 +217,12 @@
|
|||
<ClCompile Include="EmptyStringVisibilityConverter.cpp">
|
||||
<DependentUpon>EmptyStringVisibilityConverter.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Pane.cpp" />
|
||||
<ClCompile Include="LeafPane.cpp">
|
||||
<DependentUpon>LeafPane.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ParentPane.cpp">
|
||||
<DependentUpon>ParentPane.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Pane.LayoutSizeNode.cpp" />
|
||||
<ClCompile Include="ColorHelper.cpp" />
|
||||
<ClCompile Include="DebugTapConnection.cpp" />
|
||||
|
@ -250,6 +266,7 @@
|
|||
<Midl Include="ShortcutActionDispatch.idl" />
|
||||
<Midl Include="AppKeyBindings.idl" />
|
||||
<Midl Include="AppLogic.idl" />
|
||||
<Midl Include="IPane.idl" />
|
||||
<Midl Include="MinMaxCloseControl.idl">
|
||||
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
@ -289,6 +306,14 @@
|
|||
<DependentUpon>CommandPalette.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="LeafPane.idl">
|
||||
<DependentUpon>LeafPane.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="ParentPane.idl">
|
||||
<DependentUpon>ParentPane.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="FilteredCommand.idl" />
|
||||
<Midl Include="EmptyStringVisibilityConverter.idl" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -10,7 +10,10 @@
|
|||
<ClCompile Include="init.cpp" />
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Pane.cpp">
|
||||
<ClCompile Include="LeafPane.cpp">
|
||||
<Filter>pane</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ParentPane.cpp">
|
||||
<Filter>pane</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Tab.cpp">
|
||||
|
@ -60,6 +63,12 @@
|
|||
<ClInclude Include="Pane.h">
|
||||
<Filter>pane</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LeafPane.h">
|
||||
<Filter>pane</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ParentPane.h">
|
||||
<Filter>pane</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Tab.h">
|
||||
<Filter>tab</Filter>
|
||||
</ClInclude>
|
||||
|
@ -116,6 +125,15 @@
|
|||
<Midl Include="TerminalTab.idl">
|
||||
<Filter>tab</Filter>
|
||||
</Midl>
|
||||
<Midl Include="IPane.idl">
|
||||
<Filter>pane</Filter>
|
||||
</Midl>
|
||||
<Midl Include="LeafPane.idl">
|
||||
<Filter>pane</Filter>
|
||||
</Midl>
|
||||
<Midl Include="ParentPane.idl">
|
||||
<Filter>pane</Filter>
|
||||
</Midl>
|
||||
<Midl Include="FilteredCommand.idl">
|
||||
<Filter>commandPalette</Filter>
|
||||
</Midl>
|
||||
|
@ -139,6 +157,12 @@
|
|||
<Page Include="TabHeaderControl.xaml">
|
||||
<Filter>controls</Filter>
|
||||
</Page>
|
||||
<Page Include="LeafPane.xaml">
|
||||
<Filter>pane</Filter>
|
||||
</Page>
|
||||
<Page Include="ParentPane.xaml">
|
||||
<Filter>pane</Filter>
|
||||
</Page>
|
||||
<Page Include="TerminalPage.xaml">
|
||||
<Filter>controls</Filter>
|
||||
</Page>
|
||||
|
|
|
@ -1002,7 +1002,7 @@ namespace winrt::TerminalApp::implementation
|
|||
term.RestorePointerCursor({ get_weak(), &TerminalPage::_RestorePointerCursorHandler });
|
||||
|
||||
// Bind Tab events to the TermControl and the Tab's Pane
|
||||
hostingTab.Initialize(term);
|
||||
hostingTab.Initialize();
|
||||
|
||||
auto weakTab{ hostingTab.get_weak() };
|
||||
auto weakThis{ get_weak() };
|
||||
|
|
|
@ -25,20 +25,17 @@ namespace winrt
|
|||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TerminalTab::TerminalTab(const GUID& profile, const TermControl& control)
|
||||
TerminalTab::TerminalTab(const GUID& profile, const TermControl& control) :
|
||||
_zoomedPane(nullptr)
|
||||
{
|
||||
_rootPane = std::make_shared<Pane>(profile, control, true);
|
||||
_rootPane = make<LeafPane>(profile, control, true);
|
||||
const auto rootPaneAsLeaf = _rootPane.try_as<TerminalApp::LeafPane>();
|
||||
|
||||
_rootPane->Id(_nextPaneId);
|
||||
rootPaneAsLeaf.Id(_nextPaneId);
|
||||
_mruPanes.insert(_mruPanes.begin(), _nextPaneId);
|
||||
++_nextPaneId;
|
||||
|
||||
_rootPane->Closed([=](auto&& /*s*/, auto&& /*e*/) {
|
||||
_ClosedHandlers(nullptr, nullptr);
|
||||
});
|
||||
|
||||
_activePane = _rootPane;
|
||||
Content(_rootPane->GetRootElement());
|
||||
Content(rootPaneAsLeaf);
|
||||
|
||||
_MakeTabViewItem();
|
||||
_CreateContextMenu();
|
||||
|
@ -144,7 +141,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// that was last focused.
|
||||
TermControl TerminalTab::GetActiveTerminalControl() const
|
||||
{
|
||||
return _activePane->GetTerminalControl();
|
||||
return _rootPane.GetActivePane().try_as<TerminalApp::LeafPane>().TerminalControl();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -154,9 +151,9 @@ namespace winrt::TerminalApp::implementation
|
|||
// - control: reference to the TermControl object to bind event to
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::Initialize(const TermControl& control)
|
||||
void TerminalTab::Initialize()
|
||||
{
|
||||
_BindEventHandlers(control);
|
||||
_BindEventHandlers();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -201,7 +198,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// focused, else the GUID of the profile of the last control to be focused
|
||||
std::optional<GUID> TerminalTab::GetFocusedProfile() const noexcept
|
||||
{
|
||||
return _activePane->GetFocusedProfile();
|
||||
return _rootPane.GetActivePane().try_as<TerminalApp::LeafPane>().Profile();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -211,10 +208,13 @@ namespace winrt::TerminalApp::implementation
|
|||
// - control: reference to the TermControl object to bind event to
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_BindEventHandlers(const TermControl& control) noexcept
|
||||
void TerminalTab::_BindEventHandlers() noexcept
|
||||
{
|
||||
_AttachEventHandlersToPane(_rootPane);
|
||||
_AttachEventHandlersToControl(control);
|
||||
// This function gets called even when SplitPane is invoked (so potentially much after the initial construction
|
||||
// of the tab), so just in case remove the root pane event handlers before attaching them again so we don't have the
|
||||
// tab reacting to the same event twice
|
||||
_RemoveRootPaneEventHandlers();
|
||||
_SetupRootPaneEventHandlers();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -226,7 +226,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalTab::UpdateSettings(const TerminalSettingsCreateResult& settings, const GUID& profile)
|
||||
{
|
||||
_rootPane->UpdateSettings(settings, profile);
|
||||
_rootPane.UpdateSettings(settings, profile);
|
||||
|
||||
// The tabWidthMode may have changed, update the header control accordingly
|
||||
_UpdateHeaderControlMaxWidth();
|
||||
|
@ -409,42 +409,26 @@ namespace winrt::TerminalApp::implementation
|
|||
const GUID& profile,
|
||||
TermControl& control)
|
||||
{
|
||||
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
||||
const auto activePaneId = _activePane->Id();
|
||||
auto [first, second] = _activePane->Split(splitType, splitSize, profile, control);
|
||||
if (activePaneId)
|
||||
{
|
||||
first->Id(activePaneId.value());
|
||||
second->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
}
|
||||
else
|
||||
{
|
||||
first->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
second->Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
}
|
||||
_activePane = first;
|
||||
_AttachEventHandlersToControl(control);
|
||||
const auto newLeafPane = _rootPane.GetActivePane().try_as<TerminalApp::LeafPane>().Split(splitType, splitSize, profile, control);
|
||||
newLeafPane.Id(_nextPaneId);
|
||||
++_nextPaneId;
|
||||
|
||||
// Add a event handlers to the new panes' GotFocus event. When the pane
|
||||
// gains focus, we'll mark it as the new active pane.
|
||||
_AttachEventHandlersToPane(first);
|
||||
_AttachEventHandlersToPane(second);
|
||||
// Add the event handlers we need
|
||||
_AttachEventHandlersToControl(control);
|
||||
_AttachEventHandlersToLeafPane(newLeafPane);
|
||||
|
||||
// Immediately update our tracker of the focused pane now. If we're
|
||||
// splitting panes during startup (from a commandline), then it's
|
||||
// possible that the focus events won't propagate immediately. Updating
|
||||
// the focus here will give the same effect though.
|
||||
_UpdateActivePane(second);
|
||||
_UpdateActivePane(newLeafPane);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - See Pane::CalcSnappedDimension
|
||||
float TerminalTab::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
|
||||
{
|
||||
return _rootPane->CalcSnappedDimension(widthOrHeight, dimension);
|
||||
return _rootPane.CalcSnappedDimensionSingle(widthOrHeight, dimension);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -458,7 +442,7 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
// NOTE: This _must_ be called on the root pane, so that it can propagate
|
||||
// throughout the entire tree.
|
||||
_rootPane->ResizeContent(newSize);
|
||||
_rootPane.ResizeContent(newSize);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -472,7 +456,10 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
// NOTE: This _must_ be called on the root pane, so that it can propagate
|
||||
// throughout the entire tree.
|
||||
_rootPane->ResizePane(direction);
|
||||
if (const auto rootPaneAsParent = _rootPane.try_as<TerminalApp::ParentPane>())
|
||||
{
|
||||
rootPaneAsParent.ResizePane(direction);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -487,26 +474,27 @@ namespace winrt::TerminalApp::implementation
|
|||
if (direction == FocusDirection::Previous)
|
||||
{
|
||||
// To get to the previous pane, get the id of the previous pane and focus to that
|
||||
_rootPane->FocusPane(_mruPanes.at(1));
|
||||
_rootPane.FocusPane(_mruPanes.at(1));
|
||||
}
|
||||
else
|
||||
else if (const auto rootPaneAsParent = _rootPane.try_as<TerminalApp::ParentPane>())
|
||||
{
|
||||
// NOTE: This _must_ be called on the root pane, so that it can propagate
|
||||
// throughout the entire tree.
|
||||
_rootPane->NavigateFocus(direction);
|
||||
rootPaneAsParent.NavigateFocus(direction);
|
||||
}
|
||||
}
|
||||
|
||||
bool TerminalTab::FocusPane(const uint32_t id)
|
||||
{
|
||||
return _rootPane->FocusPane(id);
|
||||
_rootPane.FocusPane(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Prepares this tab for being removed from the UI hierarchy by shutting down all active connections.
|
||||
void TerminalTab::Shutdown()
|
||||
{
|
||||
_rootPane->Shutdown();
|
||||
_rootPane.Shutdown();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -519,7 +507,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - <none>
|
||||
void TerminalTab::ClosePane()
|
||||
{
|
||||
_activePane->Close();
|
||||
_rootPane.GetActivePane().try_as<TerminalApp::LeafPane>().Close();
|
||||
}
|
||||
|
||||
void TerminalTab::SetTabText(winrt::hstring title)
|
||||
|
@ -586,7 +574,10 @@ namespace winrt::TerminalApp::implementation
|
|||
const bool isInitialChange) {
|
||||
if (isInitialChange)
|
||||
{
|
||||
_rootPane->Relayout();
|
||||
if (const auto rootPaneAsParent = _rootPane.try_as<TerminalApp::ParentPane>())
|
||||
{
|
||||
rootPaneAsParent.Relayout();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -686,12 +677,11 @@ namespace winrt::TerminalApp::implementation
|
|||
// - pane: a Pane to mark as active.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_UpdateActivePane(std::shared_ptr<Pane> pane)
|
||||
void TerminalTab::_UpdateActivePane(TerminalApp::LeafPane pane)
|
||||
{
|
||||
// Clear the active state of the entire tree, and mark only the pane as active.
|
||||
_rootPane->ClearActive();
|
||||
_activePane = pane;
|
||||
_activePane->SetActive();
|
||||
_rootPane.ClearActive();
|
||||
pane.SetActive();
|
||||
|
||||
// Update our own title text to match the newly-active pane.
|
||||
UpdateTitle();
|
||||
|
@ -699,18 +689,16 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
// We need to move the pane to the top of our mru list
|
||||
// If its already somewhere in the list, remove it first
|
||||
if (const auto paneId = pane->Id())
|
||||
const auto paneId = pane.Id();
|
||||
for (auto i = _mruPanes.begin(); i != _mruPanes.end(); ++i)
|
||||
{
|
||||
for (auto i = _mruPanes.begin(); i != _mruPanes.end(); ++i)
|
||||
if (*i == paneId)
|
||||
{
|
||||
if (*i == paneId.value())
|
||||
{
|
||||
_mruPanes.erase(i);
|
||||
break;
|
||||
}
|
||||
_mruPanes.erase(i);
|
||||
break;
|
||||
}
|
||||
_mruPanes.insert(_mruPanes.begin(), paneId.value());
|
||||
}
|
||||
_mruPanes.insert(_mruPanes.begin(), paneId);
|
||||
|
||||
_RecalculateAndApplyReadOnly();
|
||||
|
||||
|
@ -723,26 +711,25 @@ namespace winrt::TerminalApp::implementation
|
|||
// focus, we'll mark it as the new active pane. We'll also query the title of
|
||||
// that pane when it's focused to set our own text, and finally, we'll trigger
|
||||
// our own ActivePaneChanged event.
|
||||
// - Also add an event handler for the pane's raise visual bell event
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::_AttachEventHandlersToPane(std::shared_ptr<Pane> pane)
|
||||
void TerminalTab::_AttachEventHandlersToLeafPane(TerminalApp::LeafPane pane)
|
||||
{
|
||||
auto weakThis{ get_weak() };
|
||||
std::weak_ptr<Pane> weakPane{ pane };
|
||||
|
||||
pane->GotFocus([weakThis](std::shared_ptr<Pane> sender) {
|
||||
const auto paneImpl = winrt::get_self<implementation::LeafPane>(pane);
|
||||
paneImpl->GotFocus([weakThis](TerminalApp::LeafPane sender) {
|
||||
// Do nothing if the Tab's lifetime is expired or pane isn't new.
|
||||
auto tab{ weakThis.get() };
|
||||
|
||||
if (tab)
|
||||
{
|
||||
if (sender != tab->_activePane)
|
||||
{
|
||||
tab->_UpdateActivePane(sender);
|
||||
tab->_RecalculateAndApplyTabColor();
|
||||
}
|
||||
tab->_UpdateActivePane(sender);
|
||||
tab->_RecalculateAndApplyTabColor();
|
||||
|
||||
tab->_focusState = WUX::FocusState::Programmatic;
|
||||
// This tab has gained focus, remove the bell indicator if it is active
|
||||
if (tab->_tabStatus.BellIndicator())
|
||||
|
@ -752,7 +739,7 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
});
|
||||
|
||||
pane->LostFocus([weakThis](std::shared_ptr<Pane> /*sender*/) {
|
||||
paneImpl->LostFocus([weakThis](TerminalApp::LeafPane /*sender*/) {
|
||||
// Do nothing if the Tab's lifetime is expired or pane isn't new.
|
||||
auto tab{ weakThis.get() };
|
||||
|
||||
|
@ -763,35 +750,8 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
});
|
||||
|
||||
// Add a Closed event handler to the Pane. If the pane closes out from
|
||||
// underneath us, and it's zoomed, we want to be able to make sure to
|
||||
// update our state accordingly to un-zoom that pane. See GH#7252.
|
||||
pane->Closed([weakThis, weakPane](auto&& /*s*/, auto && /*e*/) -> winrt::fire_and_forget {
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
if (tab->_zoomedPane)
|
||||
{
|
||||
co_await winrt::resume_foreground(tab->Content().Dispatcher());
|
||||
|
||||
tab->Content(tab->_rootPane->GetRootElement());
|
||||
tab->ExitZoom();
|
||||
}
|
||||
if (auto pane = weakPane.lock())
|
||||
{
|
||||
for (auto i = tab->_mruPanes.begin(); i != tab->_mruPanes.end(); ++i)
|
||||
{
|
||||
if (*i == pane->Id())
|
||||
{
|
||||
tab->_mruPanes.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add a PaneRaiseBell event handler to the Pane
|
||||
pane->PaneRaiseBell([weakThis](auto&& /*s*/, auto&& visual) {
|
||||
paneImpl->PaneRaiseBell([weakThis](auto&& /*s*/, auto&& visual) {
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
if (visual)
|
||||
|
@ -813,6 +773,73 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
paneImpl->Closed([weakThis](TerminalApp::IPane sender, auto&& /*a*/) {
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
if (const auto senderAsLeaf = sender.try_as<TerminalApp::LeafPane>())
|
||||
{
|
||||
// Update our mru list
|
||||
const auto senderId = senderAsLeaf.Id();
|
||||
for (auto i = tab->_mruPanes.begin(); i != tab->_mruPanes.end(); ++i)
|
||||
{
|
||||
if (*i == senderId)
|
||||
{
|
||||
tab->_mruPanes.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If that was the last leaf, close the tab
|
||||
if (tab->_mruPanes.empty())
|
||||
{
|
||||
tab->_RemoveRootPaneEventHandlers();
|
||||
tab->_ClosedHandlers(nullptr, nullptr);
|
||||
}
|
||||
else if (!senderAsLeaf.WasLastFocused())
|
||||
{
|
||||
// If the closed child was not focused, then there is a
|
||||
// good chance that the last focused pane no longer has focus
|
||||
// due to the changes made to the UI tree from the close event
|
||||
// So, focus the most recently used pane just in case
|
||||
tab->_rootPane.FocusPane(tab->_mruPanes.at(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TerminalTab::_SetupRootPaneEventHandlers()
|
||||
{
|
||||
if (const auto rootPaneAsLeaf = _rootPane.try_as<TerminalApp::LeafPane>())
|
||||
{
|
||||
// Root pane also belongs to the pane tree, so attach the usual events, as for
|
||||
// every other pane.
|
||||
_AttachEventHandlersToLeafPane(rootPaneAsLeaf);
|
||||
_AttachEventHandlersToControl(rootPaneAsLeaf.TerminalControl());
|
||||
}
|
||||
|
||||
// When the root pane is a leaf and gets split, it produces a new parent pane that contains
|
||||
// both itself and its new leaf neighbor. We then replace the root pane with the new parent pane.
|
||||
|
||||
// When root pane is a parent and one of its children got closed (and so the parent collapses),
|
||||
// we take in its remaining, orphaned child as our own.
|
||||
|
||||
// Either way, the event handling is the same - update the event handlers and set the tab's content to the new pane
|
||||
_rootPaneTypeChangedToken = _rootPane.PaneTypeChanged([weakThis = get_weak()](auto&& /*s*/, TerminalApp::IPane newPane) {
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
tab->_RemoveRootPaneEventHandlers();
|
||||
tab->_rootPane = newPane;
|
||||
tab->_SetupRootPaneEventHandlers();
|
||||
tab->Content(newPane.try_as<winrt::Windows::UI::Xaml::FrameworkElement>());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TerminalTab::_RemoveRootPaneEventHandlers()
|
||||
{
|
||||
_rootPane.PaneTypeChanged(_rootPaneTypeChangedToken);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1142,7 +1169,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - The total number of leaf panes hosted by this tab.
|
||||
int TerminalTab::GetLeafPaneCount() const noexcept
|
||||
{
|
||||
return _rootPane->GetLeafPaneCount();
|
||||
return _rootPane.GetLeafPaneCount();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1157,14 +1184,23 @@ namespace winrt::TerminalApp::implementation
|
|||
// `availableSpace`
|
||||
SplitState TerminalTab::PreCalculateAutoSplit(winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
return _rootPane->PreCalculateAutoSplit(_activePane, availableSpace).value_or(SplitState::Vertical);
|
||||
const auto res = _rootPane.PreCalculateAutoSplit(_rootPane.GetActivePane(), availableSpace);
|
||||
return res ? res.Value() : SplitState::Vertical;
|
||||
}
|
||||
|
||||
bool TerminalTab::PreCalculateCanSplit(SplitState splitType,
|
||||
const float splitSize,
|
||||
winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
return _rootPane->PreCalculateCanSplit(_activePane, splitType, splitSize, availableSpace).value_or(false);
|
||||
const auto res = _rootPane.PreCalculateCanSplit(_rootPane.GetActivePane(), splitType, splitSize, availableSpace);
|
||||
if (res)
|
||||
{
|
||||
return res.Value();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1190,19 +1226,27 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
void TerminalTab::EnterZoom()
|
||||
{
|
||||
_zoomedPane = _activePane;
|
||||
_rootPane->Maximize(_zoomedPane);
|
||||
_zoomedPane = _rootPane.GetActivePane().try_as<TerminalApp::LeafPane>();
|
||||
_rootPane.Maximize(_zoomedPane);
|
||||
|
||||
// Update the tab header to show the magnifying glass
|
||||
_tabStatus.IsPaneZoomed(true);
|
||||
Content(_zoomedPane->GetRootElement());
|
||||
Content(_zoomedPane);
|
||||
}
|
||||
void TerminalTab::ExitZoom()
|
||||
{
|
||||
_rootPane->Restore(_zoomedPane);
|
||||
_rootPane.Restore(_zoomedPane);
|
||||
_zoomedPane = nullptr;
|
||||
// Update the tab header to hide the magnifying glass
|
||||
_tabStatus.IsPaneZoomed(false);
|
||||
Content(_rootPane->GetRootElement());
|
||||
if (const auto rootAsLeaf = _rootPane.try_as<TerminalApp::LeafPane>())
|
||||
{
|
||||
Content(rootAsLeaf);
|
||||
}
|
||||
else
|
||||
{
|
||||
Content(_rootPane.try_as<TerminalApp::ParentPane>());
|
||||
}
|
||||
}
|
||||
|
||||
bool TerminalTab::IsZoomed()
|
||||
|
@ -1234,13 +1278,13 @@ namespace winrt::TerminalApp::implementation
|
|||
_tabStatus.IsReadOnlyActive(isReadOnlyActive);
|
||||
}
|
||||
|
||||
ReadOnly(_rootPane->ContainsReadOnly());
|
||||
ReadOnly(_rootPane.ContainsReadOnly());
|
||||
TabViewItem().IsClosable(!ReadOnly());
|
||||
}
|
||||
|
||||
std::shared_ptr<Pane> TerminalTab::GetActivePane() const
|
||||
TerminalApp::LeafPane TerminalTab::GetActivePane() const
|
||||
{
|
||||
return _activePane;
|
||||
return _rootPane.GetActivePane().try_as<TerminalApp::LeafPane>();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
#include "Pane.h"
|
||||
#include "ColorPickupFlyout.h"
|
||||
#include "TabBase.h"
|
||||
#include "LeafPane.h"
|
||||
#include "ParentPane.h"
|
||||
#include "TerminalTab.g.h"
|
||||
|
||||
static constexpr double HeaderRenameBoxWidthDefault{ 165 };
|
||||
|
@ -24,7 +25,7 @@ namespace winrt::TerminalApp::implementation
|
|||
TerminalTab(const GUID& profile, const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
|
||||
// Called after construction to perform the necessary setup, which relies on weak_ptr
|
||||
void Initialize(const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
void Initialize();
|
||||
|
||||
winrt::Microsoft::Terminal::Control::TermControl GetActiveTerminalControl() const;
|
||||
std::optional<GUID> GetFocusedProfile() const noexcept;
|
||||
|
@ -80,7 +81,7 @@ namespace winrt::TerminalApp::implementation
|
|||
int GetLeafPaneCount() const noexcept;
|
||||
|
||||
void TogglePaneReadOnly();
|
||||
std::shared_ptr<Pane> GetActivePane() const;
|
||||
TerminalApp::LeafPane GetActivePane() const;
|
||||
|
||||
winrt::TerminalApp::TerminalTabStatus TabStatus()
|
||||
{
|
||||
|
@ -95,9 +96,8 @@ namespace winrt::TerminalApp::implementation
|
|||
TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Pane> _rootPane{ nullptr };
|
||||
std::shared_ptr<Pane> _activePane{ nullptr };
|
||||
std::shared_ptr<Pane> _zoomedPane{ nullptr };
|
||||
IPane _rootPane;
|
||||
TerminalApp::LeafPane _zoomedPane;
|
||||
winrt::hstring _lastIconPath{};
|
||||
winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{};
|
||||
std::optional<winrt::Windows::UI::Color> _themeTabColor{};
|
||||
|
@ -105,6 +105,8 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::TerminalApp::TabHeaderControl _headerControl{};
|
||||
winrt::TerminalApp::TerminalTabStatus _tabStatus{};
|
||||
|
||||
winrt::event_token _rootPaneTypeChangedToken{ 0 };
|
||||
|
||||
std::vector<uint32_t> _mruPanes;
|
||||
uint32_t _nextPaneId{ 0 };
|
||||
|
||||
|
@ -129,12 +131,14 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
void _RefreshVisualState();
|
||||
|
||||
void _BindEventHandlers(const winrt::Microsoft::Terminal::Control::TermControl& control) noexcept;
|
||||
void _BindEventHandlers() noexcept;
|
||||
|
||||
void _AttachEventHandlersToControl(const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
void _AttachEventHandlersToPane(std::shared_ptr<Pane> pane);
|
||||
void _AttachEventHandlersToLeafPane(TerminalApp::LeafPane pane);
|
||||
void _SetupRootPaneEventHandlers();
|
||||
void _RemoveRootPaneEventHandlers();
|
||||
|
||||
void _UpdateActivePane(std::shared_ptr<Pane> pane);
|
||||
void _UpdateActivePane(TerminalApp::LeafPane pane);
|
||||
|
||||
winrt::hstring _GetActiveTitle() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue