@@ -34,16 +34,20 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi
3434winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
3535winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
3636
37- Pane::Pane (const Profile& profile, const TermControl & control, const bool lastFocused) :
37+ Pane::Pane (const Profile& profile, const Controls::UserControl & control, const bool lastFocused) :
3838 _control{ control },
3939 _lastActive{ lastFocused },
4040 _profile{ profile }
4141{
4242 _root.Children ().Append (_borderFirst);
4343 _borderFirst.Child (_control);
4444
45- _connectionStateChangedToken = _control.ConnectionStateChanged ({ this , &Pane::_ControlConnectionStateChangedHandler });
46- _warningBellToken = _control.WarningBell ({ this , &Pane::_ControlWarningBellHandler });
45+ const auto & termControl{ _control.try_as <TermControl>() };
46+ if (termControl)
47+ {
48+ _connectionStateChangedToken = termControl.ConnectionStateChanged ({ this , &Pane::_ControlConnectionStateChangedHandler });
49+ _warningBellToken = termControl.WarningBell ({ this , &Pane::_ControlWarningBellHandler });
50+ }
4751
4852 // On the first Pane's creation, lookup resources we'll use to theme the
4953 // Pane, including the brushed to use for the focused/unfocused border
@@ -1079,8 +1083,12 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
10791083 {
10801084 return ;
10811085 }
1082-
1083- const auto newConnectionState = _control.ConnectionState ();
1086+ const auto & termControl{ _control.try_as <TermControl>() };
1087+ if (!termControl)
1088+ {
1089+ return ;
1090+ }
1091+ const auto newConnectionState = termControl.ConnectionState ();
10841092 const auto previousConnectionState = std::exchange (_connectionState, newConnectionState);
10851093
10861094 if (newConnectionState < ConnectionState::Closed)
@@ -1123,7 +1131,9 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
11231131 {
11241132 return ;
11251133 }
1126- if (_profile)
1134+
1135+ const auto & termControl{ _control.try_as <TermControl>() };
1136+ if (_profile && termControl)
11271137 {
11281138 // We don't want to do anything if nothing is set, so check for that first
11291139 if (static_cast <int >(_profile.BellStyle ()) != 0 )
@@ -1137,7 +1147,7 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
11371147
11381148 if (WI_IsFlagSet (_profile.BellStyle (), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
11391149 {
1140- _control .BellLightOn ();
1150+ termControl .BellLightOn ();
11411151 }
11421152
11431153 // raise the event with the bool value corresponding to the taskbar flag
@@ -1197,7 +1207,11 @@ void Pane::Shutdown()
11971207 std::unique_lock lock{ _createCloseLock };
11981208 if (_IsLeaf ())
11991209 {
1200- _control.Close ();
1210+ const auto & termControl{ _control.try_as <TermControl>() };
1211+ if (termControl)
1212+ {
1213+ termControl.Close ();
1214+ }
12011215 }
12021216 else
12031217 {
@@ -1207,7 +1221,7 @@ void Pane::Shutdown()
12071221}
12081222
12091223// Method Description:
1210- // - Get the root UIElement of this pane. There may be a single TermControl as a
1224+ // - Get the root UIElement of this pane. There may be a single UserControl as a
12111225// child, or an entire tree of grids and panes as children of this element.
12121226// Arguments:
12131227// - <none>
@@ -1283,10 +1297,11 @@ TermControl Pane::GetLastFocusedTerminalControl()
12831297// Arguments:
12841298// - <none>
12851299// Return Value:
1286- // - nullptr if this Pane is a parent, otherwise the TermControl of this Pane.
1287- TermControl Pane::GetTerminalControl ()
1300+ // - nullptr if this Pane is a parent or isn't hosting a Terminal, otherwise the
1301+ // TermControl of this Pane.
1302+ TermControl Pane::GetTerminalControl () const
12881303{
1289- return _IsLeaf () ? _control : nullptr ;
1304+ return _IsLeaf () ? _control. try_as <TermControl>() : nullptr ;
12901305}
12911306
12921307// Method Description:
@@ -1457,9 +1472,13 @@ void Pane::_FocusFirstChild()
14571472void Pane::UpdateSettings (const TerminalSettingsCreateResult& settings, const Profile& profile)
14581473{
14591474 assert (_IsLeaf ());
1460-
1475+ const auto & termControl{ _control.try_as <TermControl>() };
1476+ if (!termControl)
1477+ {
1478+ return ;
1479+ }
14611480 _profile = profile;
1462- auto controlSettings = _control .Settings ().as <TerminalSettings>();
1481+ auto controlSettings = termControl .Settings ().as <TerminalSettings>();
14631482 // Update the parent of the control's settings object (and not the object itself) so
14641483 // that any overrides made by the control don't get affected by the reload
14651484 controlSettings.SetParent (settings.DefaultSettings ());
@@ -1472,8 +1491,8 @@ void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Pr
14721491 // sure the unfocused settings inherit from that.
14731492 unfocusedSettings.SetParent (controlSettings);
14741493 }
1475- _control .UnfocusedAppearance (unfocusedSettings);
1476- _control .UpdateSettings ();
1494+ termControl .UnfocusedAppearance (unfocusedSettings);
1495+ termControl .UpdateSettings ();
14771496}
14781497
14791498// Method Description:
@@ -1614,8 +1633,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
16141633 _id = remainingChild->Id ();
16151634
16161635 // Add our new event handler before revoking the old one.
1617- _connectionStateChangedToken = _control.ConnectionStateChanged ({ this , &Pane::_ControlConnectionStateChangedHandler });
1618- _warningBellToken = _control.WarningBell ({ this , &Pane::_ControlWarningBellHandler });
1636+ const auto & termControl{ _control.try_as <TermControl>() };
1637+ if (termControl)
1638+ {
1639+ _connectionStateChangedToken = termControl.ConnectionStateChanged ({ this , &Pane::_ControlConnectionStateChangedHandler });
1640+ _warningBellToken = termControl.WarningBell ({ this , &Pane::_ControlWarningBellHandler });
1641+ }
16191642
16201643 // Revoke the old event handlers. Remove both the handlers for the panes
16211644 // themselves closing, and remove their handlers for their controls
@@ -1629,24 +1652,33 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
16291652 closedChild->WalkTree ([](auto p) {
16301653 if (p->_IsLeaf ())
16311654 {
1632- p->_control .ConnectionStateChanged (p->_connectionStateChangedToken );
1633- p->_control .WarningBell (p->_warningBellToken );
1655+ const auto & closedControl{ p->_control .try_as <TermControl>() };
1656+ if (closedControl)
1657+ {
1658+ closedControl.ConnectionStateChanged (closedChild->_connectionStateChangedToken );
1659+ closedControl.WarningBell (closedChild->_warningBellToken );
1660+ }
16341661 }
16351662 return false ;
16361663 });
16371664 }
16381665
16391666 closedChild->Closed (closedChildClosedToken);
16401667 remainingChild->Closed (remainingChildClosedToken);
1641- remainingChild->_control .ConnectionStateChanged (remainingChild->_connectionStateChangedToken );
1642- remainingChild->_control .WarningBell (remainingChild->_warningBellToken );
1668+
1669+ const auto & remainingControl{ remainingChild->_control .try_as <TermControl>() };
1670+ if (remainingControl)
1671+ {
1672+ remainingControl.ConnectionStateChanged (remainingChild->_connectionStateChangedToken );
1673+ remainingControl.WarningBell (remainingChild->_warningBellToken );
1674+ }
16431675
16441676 // If we or either of our children was focused, we want to take that
16451677 // focus from them.
16461678 _lastActive = _lastActive || _firstChild->_lastActive || _secondChild->_lastActive ;
16471679
16481680 // Remove all the ui elements of the remaining child. This'll make sure
1649- // we can re-attach the TermControl to our Grid.
1681+ // we can re-attach the UserControl to our Grid.
16501682 remainingChild->_root .Children ().Clear ();
16511683 remainingChild->_borderFirst .Child (nullptr );
16521684
@@ -1657,7 +1689,7 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
16571689 _root.ColumnDefinitions ().Clear ();
16581690 _root.RowDefinitions ().Clear ();
16591691
1660- // Reattach the TermControl to our grid.
1692+ // Reattach the UserControl to our grid.
16611693 _root.Children ().Append (_borderFirst);
16621694 _borderFirst.Child (_control);
16631695
@@ -1719,8 +1751,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
17191751 closedChild->WalkTree ([](auto p) {
17201752 if (p->_IsLeaf ())
17211753 {
1722- p->_control .ConnectionStateChanged (p->_connectionStateChangedToken );
1723- p->_control .WarningBell (p->_warningBellToken );
1754+ const auto & closedControl{ p->_control .try_as <TermControl>() };
1755+ if (closedControl)
1756+ {
1757+ closedControl.ConnectionStateChanged (closedChild->_connectionStateChangedToken );
1758+ closedControl.WarningBell (closedChild->_warningBellToken );
1759+ }
17241760 }
17251761 return false ;
17261762 });
@@ -2352,18 +2388,18 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
23522388
23532389// Method Description:
23542390// - Split the focused pane in our tree of panes, and place the given
2355- // TermControl into the newly created pane. If we're the focused pane, then
2391+ // UserControl into the newly created pane. If we're the focused pane, then
23562392// we'll create two new children, and place them side-by-side in our Grid.
23572393// Arguments:
23582394// - splitType: what type of split we want to create.
23592395// - profile: The profile to associate with the newly created pane.
2360- // - control: A TermControl to use in the new pane.
2396+ // - control: A UserControl to use in the new pane.
23612397// Return Value:
23622398// - The two newly created Panes, with the original pane first
23632399std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split (SplitDirection splitType,
23642400 const float splitSize,
23652401 const Profile& profile,
2366- const TermControl & control)
2402+ const Controls::UserControl & control)
23672403{
23682404 if (!_lastActive)
23692405 {
@@ -2471,11 +2507,14 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
24712507
24722508 if (_IsLeaf ())
24732509 {
2474- // revoke our handler - the child will take care of the control now.
2475- _control.ConnectionStateChanged (_connectionStateChangedToken);
2476- _connectionStateChangedToken.value = 0 ;
2477- _control.WarningBell (_warningBellToken);
2478- _warningBellToken.value = 0 ;
2510+ if (const auto & termControl{ _control.try_as <TermControl>() })
2511+ {
2512+ // revoke our handler - the child will take care of the control now.
2513+ termControl.ConnectionStateChanged (_connectionStateChangedToken);
2514+ _connectionStateChangedToken.value = 0 ;
2515+ termControl.WarningBell (_warningBellToken);
2516+ _warningBellToken.value = 0 ;
2517+ }
24792518
24802519 // Remove our old GotFocus handler from the control. We don't want the
24812520 // control telling us that it's now focused, we want it telling its new
@@ -2485,7 +2524,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
24852524 }
24862525
24872526 // Remove any children we currently have. We can't add the existing
2488- // TermControl to a new grid until we do this.
2527+ // UserControl to a new grid until we do this.
24892528 _root.Children ().Clear ();
24902529 _borderFirst.Child (nullptr );
24912530 _borderSecond.Child (nullptr );
@@ -2863,8 +2902,13 @@ float Pane::CalcSnappedDimension(const bool widthOrHeight, const float dimension
28632902// If requested size is already snapped, then both returned values equal this value.
28642903Pane::SnapSizeResult Pane::_CalcSnappedDimension (const bool widthOrHeight, const float dimension) const
28652904{
2905+ const auto & termControl{ _control.try_as <TermControl>() };
28662906 if (_IsLeaf ())
28672907 {
2908+ if (!termControl)
2909+ {
2910+ return { dimension, dimension };
2911+ }
28682912 // If we're a leaf pane, align to the grid of controlling terminal
28692913
28702914 const auto minSize = _GetMinSize ();
@@ -2875,7 +2919,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
28752919 return { minDimension, minDimension };
28762920 }
28772921
2878- float lower = _control .SnapDimensionToGrid (widthOrHeight, dimension);
2922+ float lower = termControl .SnapDimensionToGrid (widthOrHeight, dimension);
28792923 if (widthOrHeight)
28802924 {
28812925 lower += WI_IsFlagSet (_borders, Borders::Left) ? PaneBorderSize : 0 ;
@@ -2895,7 +2939,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
28952939 }
28962940 else
28972941 {
2898- const auto cellSize = _control .CharacterDimensions ();
2942+ const auto cellSize = termControl .CharacterDimensions ();
28992943 const auto higher = lower + (widthOrHeight ? cellSize.Width : cellSize.Height );
29002944 return { lower, higher };
29012945 }
@@ -2940,7 +2984,8 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
29402984// - <none>
29412985void Pane::_AdvanceSnappedDimension (const bool widthOrHeight, LayoutSizeNode& sizeNode) const
29422986{
2943- if (_IsLeaf ())
2987+ const auto & termControl{ _control.try_as <TermControl>() };
2988+ if (_IsLeaf () && termControl)
29442989 {
29452990 // We're a leaf pane, so just add one more row or column (unless isMinimumSize
29462991 // is true, see below).
@@ -2955,11 +3000,11 @@ void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& si
29553000 }
29563001 else
29573002 {
2958- const auto cellSize = _control .CharacterDimensions ();
3003+ const auto cellSize = termControl .CharacterDimensions ();
29593004 sizeNode.size += widthOrHeight ? cellSize.Width : cellSize.Height ;
29603005 }
29613006 }
2962- else
3007+ else if (! _IsLeaf ())
29633008 {
29643009 // We're a parent pane, so we have to advance dimension of our children panes. In
29653010 // fact, we advance only one child (chosen later) to keep the growth fine-grained.
@@ -3061,7 +3106,8 @@ Size Pane::_GetMinSize() const
30613106{
30623107 if (_IsLeaf ())
30633108 {
3064- auto controlSize = _control.MinimumSize ();
3109+ const auto & termControl{ _control.try_as <TermControl>() };
3110+ auto controlSize = termControl ? termControl.MinimumSize () : Size{ 1 , 1 };
30653111 auto newWidth = controlSize.Width ;
30663112 auto newHeight = controlSize.Height ;
30673113
@@ -3247,7 +3293,8 @@ std::optional<SplitDirection> Pane::PreCalculateAutoSplit(const std::shared_ptr<
32473293// - Returns true if the pane or one of its descendants is read-only
32483294bool Pane::ContainsReadOnly () const
32493295{
3250- return _IsLeaf () ? _control.ReadOnly () : (_firstChild->ContainsReadOnly () || _secondChild->ContainsReadOnly ());
3296+ const auto & termControl{ GetTerminalControl () };
3297+ return termControl ? termControl.ReadOnly () : (_firstChild->ContainsReadOnly () || _secondChild->ContainsReadOnly ());
32513298}
32523299
32533300// Method Description:
@@ -3260,13 +3307,14 @@ bool Pane::ContainsReadOnly() const
32603307// - <none>
32613308void Pane::CollectTaskbarStates (std::vector<winrt::TerminalApp::TaskbarState>& states)
32623309{
3263- if (_IsLeaf ())
3310+ const auto & termControl{ GetTerminalControl () };
3311+ if (termControl)
32643312 {
3265- auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_control .TaskbarState (),
3266- _control .TaskbarProgress ()) };
3313+ auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(termControl .TaskbarState (),
3314+ termControl .TaskbarProgress ()) };
32673315 states.push_back (tbState);
32683316 }
3269- else
3317+ else if (! _IsLeaf ())
32703318 {
32713319 _firstChild->CollectTaskbarStates (states);
32723320 _secondChild->CollectTaskbarStates (states);
0 commit comments