Compare commits

...

73 commits

Author SHA1 Message Date
Dustin L. Howett eec8228924 Migrate spelling-0.0.19 changes from main 2021-06-07 08:51:23 -07:00
Pankaj Bhojwani 1067d24986 spelling 2021-06-07 08:51:23 -07:00
Pankaj Bhojwani ee358fad7f remove dictionary 2021-06-07 08:39:02 -07:00
Pankaj Bhojwani 392be7bf37 delete 2021-06-07 08:37:34 -07:00
Pankaj Bhojwani f9fc1b0221 Merge branch 'main' of https://github.com/microsoft/terminal into dev/pabhoj/pane_refactor 2021-06-07 08:22:05 -07:00
Pankaj Bhojwani e2ec41fb9f connection state changed event changes 2021-06-02 10:22:23 -07:00
Pankaj Bhojwani ee6515bee1 conflict 2021-06-02 09:37:17 -07:00
Pankaj Bhojwani f09e8cbafd cleanup old todos 2021-04-15 13:57:59 -07:00
Pankaj Bhojwani 6026c0e440 settings changes 2021-04-14 15:38:29 -07:00
Pankaj Bhojwani a1040b498c fix close event, tab focuses mru pane upon pane close 2021-04-12 16:23:17 -07:00
Pankaj Bhojwani fab614cbfc format 2021-04-08 11:11:17 -07:00
Pankaj Bhojwani e5d5669b30 conflict 2021-04-07 11:37:06 -07:00
Pankaj Bhojwani 840004f252 gah 2021-04-01 15:50:19 -07:00
Pankaj Bhojwani d7c5e7c13f more 2021-04-01 15:49:26 -07:00
Pankaj Bhojwani 44de0aa2d3 undo debug changes 2021-04-01 15:47:43 -07:00
Pankaj Bhojwani 52c406d85c switch to grid to solve focus problem 2021-04-01 15:19:44 -07:00
Pankaj Bhojwani 87e1ff0855 debug changes 2021-03-31 10:38:39 -07:00
Pankaj Bhojwani 1335753337 remove pane.h 2021-03-15 16:39:14 -07:00
Pankaj Bhojwani 7c57e627bf unfocused brush for parent 2021-03-15 16:36:39 -07:00
Pankaj Bhojwani 4254c62155 delete most of pane.h 2021-03-09 11:47:00 -08:00
Pankaj Bhojwani d8112e977d yet another focus attempt 2021-03-09 10:39:21 -08:00
Pankaj Bhojwani 62131c02f7 remove unnecessary includes 2021-03-02 11:56:40 -08:00
Pankaj Bhojwani 74f600b0d2 abstracts 2021-03-02 11:33:18 -08:00
Pankaj Bhojwani 1752f44af3 borders name 2021-03-02 11:29:13 -08:00
Pankaj Bhojwani 85f51adb9a address more comments 2021-03-02 11:19:57 -08:00
Pankaj Bhojwani f7c8a9acae address some comments 2021-03-01 16:58:32 -08:00
Pankaj Bhojwani 1d37b71a61 remove 2s 2021-02-16 15:49:31 -08:00
Pankaj Bhojwani 3ecd86fefa format 2021-02-16 15:06:51 -08:00
Pankaj Bhojwani 730eafe33d update some comments 2021-02-16 15:02:31 -08:00
Pankaj Bhojwani b9451359b9 delete pane again 2021-02-16 15:00:22 -08:00
Pankaj Bhojwani 486642c52d merge main, fix conflicts, readonly in new impl 2021-02-16 11:19:29 -08:00
Pankaj Bhojwani a7d506b849 remove a todo 2021-02-11 16:21:01 -08:00
Pankaj Bhojwani 3a78622dc9 use nullptr to empty content 2021-02-11 14:42:15 -08:00
Pankaj Bhojwani 856486ec45 focus transfer is still buggy 2021-02-11 14:33:53 -08:00
Pankaj Bhojwani d2208fac43 entrance animation seems to work.. 2021-02-11 10:50:34 -08:00
Pankaj Bhojwani 3d75680f77 entrance animation works now 2021-02-10 14:15:53 -08:00
Pankaj Bhojwani c6de9d5977 small cleanup 2021-02-10 11:46:43 -08:00
Pankaj Bhojwani b028a04633 update parent's child type changed handler 2021-02-10 11:17:58 -08:00
Pankaj Bhojwani 7fdef8789e hopefully this is the last border fix 2021-02-10 10:11:38 -08:00
Pankaj Bhojwani 051e0b0456 add pane type changed event, remove got split and child closed events 2021-02-09 12:16:02 -08:00
Pankaj Bhojwani 3eda960a8d tab listens to every leaf's close 2021-02-08 16:46:52 -08:00
Pankaj Bhojwani 9da26627ea don't need this 2021-02-05 15:15:59 -08:00
Pankaj Bhojwani bb66ec8292 the old pane did not go gently into that good night 2021-02-05 14:53:47 -08:00
Pankaj Bhojwani f664608388 transfer comments 2021-02-05 11:12:24 -08:00
Pankaj Bhojwani 884c3f2e9d update active pane in terminal tab 2021-02-04 14:28:08 -08:00
Pankaj Bhojwani a91427a829 spelling 2021-02-04 12:04:22 -08:00
Pankaj Bhojwani 11772a05c9 okay now the borders update properly 2021-02-04 11:54:39 -08:00
Pankaj Bhojwani 8ac4140ad5 update borders properly 2021-02-04 11:46:15 -08:00
Pankaj Bhojwani 5cdd8610a0 maximize/restore 2021-02-03 16:13:30 -08:00
Pankaj Bhojwani 89db208d76 animations partly in 2021-02-03 15:22:07 -08:00
Pankaj Bhojwani a35c45cb9c opening/closing panes works now 2021-02-03 10:56:50 -08:00
Pankaj Bhojwani 4728a60718 errors 2021-02-02 14:43:22 -08:00
Pankaj Bhojwani e5df4d3e85 more event handling 2021-02-01 16:43:56 -08:00
Pankaj Bhojwani 2bcbc45a5e started changing tab 2021-02-01 15:59:33 -08:00
Pankaj Bhojwani b21255dbad some event handlers 2021-02-01 15:17:52 -08:00
Pankaj Bhojwani 758064c324 border stuff 2021-02-01 14:37:16 -08:00
Pankaj Bhojwani 56d8e6a04c moar moving 2021-02-01 11:34:31 -08:00
Pankaj Bhojwani a4541a3d54 i am a cow 2021-01-29 16:00:20 -08:00
Pankaj Bhojwani 0c1d7365c4 moooooooo 2021-01-28 16:51:47 -08:00
Pankaj Bhojwani 5f822afb3b mooooooooooooooooooooooooooove 2021-01-28 14:48:58 -08:00
Pankaj Bhojwani 76efe47fac more 2021-01-27 16:45:58 -08:00
Pankaj Bhojwani 961f27ed42 moooooooove 2021-01-27 13:54:20 -08:00
Pankaj Bhojwani 6f5b499c62 more moving 2021-01-27 13:21:32 -08:00
Pankaj Bhojwani f3dc0a230b moving the code 2021-01-27 10:42:32 -08:00
Pankaj Bhojwani d7a4c04099 sloooowly 2021-01-26 17:00:19 -08:00
Pankaj Bhojwani b0959f10b6 still builds 2021-01-26 16:46:49 -08:00
Pankaj Bhojwani 74087d659a builds I guess 2021-01-26 16:26:18 -08:00
Pankaj Bhojwani 504c5c2110 most of skeleton in 2021-01-26 12:33:23 -08:00
Pankaj Bhojwani e622876ab0 more baby steps 2021-01-26 10:52:59 -08:00
Pankaj Bhojwani 194f849448 initial xaml 2021-01-25 15:22:53 -08:00
Pankaj Bhojwani bcf1720452 ascribe to IPane 2021-01-25 11:29:44 -08:00
Pankaj Bhojwani 4a8d4b5396 IPane interface 2021-01-25 10:56:12 -08:00
Pankaj Bhojwani ed00e4011b files in place 2021-01-22 13:51:06 -08:00
28 changed files with 3002 additions and 2529 deletions

View file

@ -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

View file

@ -2,15 +2,20 @@ ACCEPTFILES
ACCESSDENIED
alignas
alignof
APPLYTOSUBMENUS
bitfield
bitfields
BUILDBRANCH
BUILDMSG
BUILDNUMBER
BYPOSITION
charconv
CLASSNOTAVAILABLE
cmdletbinding
COLORPROPERTY
colspan
COMDLG
comparand
cstdint
CXICON
CYICON
@ -20,9 +25,11 @@ DERR
dlldata
DONTADDTORECENT
DWORDLONG
enumset
environstrings
EXPCMDFLAGS
EXPCMDSTATE
filetime
FILTERSPEC
FORCEFILESYSTEM
FORCEMINIMIZE
@ -45,6 +52,7 @@ IBind
IBox
IClass
IComparable
IComparer
IConnection
ICustom
IDialog
@ -58,6 +66,8 @@ IObject
iosfwd
IPackage
IPeasant
isspace
ISetup
IStorage
istream
IStringable
@ -65,26 +75,40 @@ ITab
ITaskbar
IUri
IVirtual
KEYSELECT
LCID
llabs
llu
localtime
lround
LSHIFT
MENUCOMMAND
MENUDATA
MENUINFO
memicmp
mptt
mov
msappx
MULTIPLEUSE
NCHITTEST
NCLBUTTONDBLCLK
NCRBUTTONDBLCLK
NIF
NIN
NOAGGREGATION
NOASYNC
NOCHANGEDIR
NOPROGRESS
NOREDIRECTIONBITMAP
NOREPEAT
NOTIFYBYPOS
NOTIFYICON
NOTIFYICONDATA
ntprivapi
oaidl
ocidl
ODR
offsetof
osver
OSVERSIONINFOEXW
otms
@ -93,6 +117,7 @@ overridable
PAGESCROLL
PICKFOLDERS
pmr
rcx
REGCLS
RETURNCMD
rfind
@ -101,41 +126,54 @@ RSHIFT
schandle
semver
serializer
SETVERSION
SHELLEXECUTEINFOW
shobjidl
SHOWMINIMIZED
SHOWTIP
SINGLEUSE
SIZENS
smoothstep
snprintf
spsc
sregex
SRWLOC
SRWLOCK
STDCPP
STDMETHOD
strchr
strcpy
streambuf
strtoul
Stubless
Subheader
Subpage
syscall
TASKBARCREATED
TBPF
THEMECHANGED
tlg
tmp
tolower
toupper
TTask
TVal
UChar
UPDATEINIFILE
userenv
wcsstr
wcstoui
winmain
wmemcmp
wpc
wsregex
wwinmain
xchg
XDocument
XElement
xfacet
xhash
XIcon
xiosbase
xlocale
xlocbuf
@ -144,9 +182,13 @@ xlocmes
xlocmon
xlocnum
xloctime
XMax
xmemory
XParse
xpath
xstddef
xstring
xtree
xutility
YIcon
YMax

View file

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

View file

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

View file

@ -1,5 +1,6 @@
ACLs
ADMINS
advapi
altform
altforms
appendwttlogging
@ -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

View file

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

View file

@ -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

View file

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

View file

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

View file

@ -1,19 +1,20 @@
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
name: Spell checking
on:
pull_request_target:
push:
jobs:
build:
spelling:
name: Spell checking
runs-on: ubuntu-latest
steps:
- name: checkout-merge
if: "contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2.0.0
uses: actions/checkout@v2
with:
ref: refs/pull/${{github.event.pull_request.number}}/merge
- name: checkout
if: "!contains(github.event_name, 'pull_request')"
uses: actions/checkout@v2.0.0
- uses: check-spelling/check-spelling@v0.0.18
uses: actions/checkout@v2
- uses: check-spelling/check-spelling@v0.0.19

View 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;
}
}

View 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>);
}

View 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);
}

View 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);
}
}

View 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>

View file

@ -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

View file

@ -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);
};
};

File diff suppressed because it is too large Load diff

View 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);
}

View 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();
}
}

View 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>

View file

@ -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();
}
}
}

View file

@ -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>

View file

@ -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>

View file

@ -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() };

View file

@ -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:

View file

@ -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;