@@ -34,16 +34,20 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi
34
34
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
35
35
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
36
36
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) :
38
38
_control{ control },
39
39
_lastActive{ lastFocused },
40
40
_profile{ profile }
41
41
{
42
42
_root.Children ().Append (_borderFirst);
43
43
_borderFirst.Child (_control);
44
44
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
+ }
47
51
48
52
// On the first Pane's creation, lookup resources we'll use to theme the
49
53
// Pane, including the brushed to use for the focused/unfocused border
@@ -1079,8 +1083,12 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
1079
1083
{
1080
1084
return ;
1081
1085
}
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 ();
1084
1092
const auto previousConnectionState = std::exchange (_connectionState, newConnectionState);
1085
1093
1086
1094
if (newConnectionState < ConnectionState::Closed)
@@ -1123,7 +1131,9 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
1123
1131
{
1124
1132
return ;
1125
1133
}
1126
- if (_profile)
1134
+
1135
+ const auto & termControl{ _control.try_as <TermControl>() };
1136
+ if (_profile && termControl)
1127
1137
{
1128
1138
// We don't want to do anything if nothing is set, so check for that first
1129
1139
if (static_cast <int >(_profile.BellStyle ()) != 0 )
@@ -1137,7 +1147,7 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
1137
1147
1138
1148
if (WI_IsFlagSet (_profile.BellStyle (), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
1139
1149
{
1140
- _control .BellLightOn ();
1150
+ termControl .BellLightOn ();
1141
1151
}
1142
1152
1143
1153
// raise the event with the bool value corresponding to the taskbar flag
@@ -1197,7 +1207,11 @@ void Pane::Shutdown()
1197
1207
std::unique_lock lock{ _createCloseLock };
1198
1208
if (_IsLeaf ())
1199
1209
{
1200
- _control.Close ();
1210
+ const auto & termControl{ _control.try_as <TermControl>() };
1211
+ if (termControl)
1212
+ {
1213
+ termControl.Close ();
1214
+ }
1201
1215
}
1202
1216
else
1203
1217
{
@@ -1207,7 +1221,7 @@ void Pane::Shutdown()
1207
1221
}
1208
1222
1209
1223
// 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
1211
1225
// child, or an entire tree of grids and panes as children of this element.
1212
1226
// Arguments:
1213
1227
// - <none>
@@ -1283,10 +1297,11 @@ TermControl Pane::GetLastFocusedTerminalControl()
1283
1297
// Arguments:
1284
1298
// - <none>
1285
1299
// 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
1288
1303
{
1289
- return _IsLeaf () ? _control : nullptr ;
1304
+ return _IsLeaf () ? _control. try_as <TermControl>() : nullptr ;
1290
1305
}
1291
1306
1292
1307
// Method Description:
@@ -1457,9 +1472,13 @@ void Pane::_FocusFirstChild()
1457
1472
void Pane::UpdateSettings (const TerminalSettingsCreateResult& settings, const Profile& profile)
1458
1473
{
1459
1474
assert (_IsLeaf ());
1460
-
1475
+ const auto & termControl{ _control.try_as <TermControl>() };
1476
+ if (!termControl)
1477
+ {
1478
+ return ;
1479
+ }
1461
1480
_profile = profile;
1462
- auto controlSettings = _control .Settings ().as <TerminalSettings>();
1481
+ auto controlSettings = termControl .Settings ().as <TerminalSettings>();
1463
1482
// Update the parent of the control's settings object (and not the object itself) so
1464
1483
// that any overrides made by the control don't get affected by the reload
1465
1484
controlSettings.SetParent (settings.DefaultSettings ());
@@ -1472,8 +1491,8 @@ void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Pr
1472
1491
// sure the unfocused settings inherit from that.
1473
1492
unfocusedSettings.SetParent (controlSettings);
1474
1493
}
1475
- _control .UnfocusedAppearance (unfocusedSettings);
1476
- _control .UpdateSettings ();
1494
+ termControl .UnfocusedAppearance (unfocusedSettings);
1495
+ termControl .UpdateSettings ();
1477
1496
}
1478
1497
1479
1498
// Method Description:
@@ -1614,8 +1633,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
1614
1633
_id = remainingChild->Id ();
1615
1634
1616
1635
// 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
+ }
1619
1642
1620
1643
// Revoke the old event handlers. Remove both the handlers for the panes
1621
1644
// themselves closing, and remove their handlers for their controls
@@ -1629,24 +1652,33 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
1629
1652
closedChild->WalkTree ([](auto p) {
1630
1653
if (p->_IsLeaf ())
1631
1654
{
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
+ }
1634
1661
}
1635
1662
return false ;
1636
1663
});
1637
1664
}
1638
1665
1639
1666
closedChild->Closed (closedChildClosedToken);
1640
1667
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
+ }
1643
1675
1644
1676
// If we or either of our children was focused, we want to take that
1645
1677
// focus from them.
1646
1678
_lastActive = _lastActive || _firstChild->_lastActive || _secondChild->_lastActive ;
1647
1679
1648
1680
// 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.
1650
1682
remainingChild->_root .Children ().Clear ();
1651
1683
remainingChild->_borderFirst .Child (nullptr );
1652
1684
@@ -1657,7 +1689,7 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
1657
1689
_root.ColumnDefinitions ().Clear ();
1658
1690
_root.RowDefinitions ().Clear ();
1659
1691
1660
- // Reattach the TermControl to our grid.
1692
+ // Reattach the UserControl to our grid.
1661
1693
_root.Children ().Append (_borderFirst);
1662
1694
_borderFirst.Child (_control);
1663
1695
@@ -1719,8 +1751,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
1719
1751
closedChild->WalkTree ([](auto p) {
1720
1752
if (p->_IsLeaf ())
1721
1753
{
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
+ }
1724
1760
}
1725
1761
return false ;
1726
1762
});
@@ -2352,18 +2388,18 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
2352
2388
2353
2389
// Method Description:
2354
2390
// - 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
2356
2392
// we'll create two new children, and place them side-by-side in our Grid.
2357
2393
// Arguments:
2358
2394
// - splitType: what type of split we want to create.
2359
2395
// - 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.
2361
2397
// Return Value:
2362
2398
// - The two newly created Panes, with the original pane first
2363
2399
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split (SplitDirection splitType,
2364
2400
const float splitSize,
2365
2401
const Profile& profile,
2366
- const TermControl & control)
2402
+ const Controls::UserControl & control)
2367
2403
{
2368
2404
if (!_lastActive)
2369
2405
{
@@ -2471,11 +2507,14 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
2471
2507
2472
2508
if (_IsLeaf ())
2473
2509
{
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
+ }
2479
2518
2480
2519
// Remove our old GotFocus handler from the control. We don't want the
2481
2520
// 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
2485
2524
}
2486
2525
2487
2526
// 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.
2489
2528
_root.Children ().Clear ();
2490
2529
_borderFirst.Child (nullptr );
2491
2530
_borderSecond.Child (nullptr );
@@ -2863,8 +2902,13 @@ float Pane::CalcSnappedDimension(const bool widthOrHeight, const float dimension
2863
2902
// If requested size is already snapped, then both returned values equal this value.
2864
2903
Pane::SnapSizeResult Pane::_CalcSnappedDimension (const bool widthOrHeight, const float dimension) const
2865
2904
{
2905
+ const auto & termControl{ _control.try_as <TermControl>() };
2866
2906
if (_IsLeaf ())
2867
2907
{
2908
+ if (!termControl)
2909
+ {
2910
+ return { dimension, dimension };
2911
+ }
2868
2912
// If we're a leaf pane, align to the grid of controlling terminal
2869
2913
2870
2914
const auto minSize = _GetMinSize ();
@@ -2875,7 +2919,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
2875
2919
return { minDimension, minDimension };
2876
2920
}
2877
2921
2878
- float lower = _control .SnapDimensionToGrid (widthOrHeight, dimension);
2922
+ float lower = termControl .SnapDimensionToGrid (widthOrHeight, dimension);
2879
2923
if (widthOrHeight)
2880
2924
{
2881
2925
lower += WI_IsFlagSet (_borders, Borders::Left) ? PaneBorderSize : 0 ;
@@ -2895,7 +2939,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
2895
2939
}
2896
2940
else
2897
2941
{
2898
- const auto cellSize = _control .CharacterDimensions ();
2942
+ const auto cellSize = termControl .CharacterDimensions ();
2899
2943
const auto higher = lower + (widthOrHeight ? cellSize.Width : cellSize.Height );
2900
2944
return { lower, higher };
2901
2945
}
@@ -2940,7 +2984,8 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
2940
2984
// - <none>
2941
2985
void Pane::_AdvanceSnappedDimension (const bool widthOrHeight, LayoutSizeNode& sizeNode) const
2942
2986
{
2943
- if (_IsLeaf ())
2987
+ const auto & termControl{ _control.try_as <TermControl>() };
2988
+ if (_IsLeaf () && termControl)
2944
2989
{
2945
2990
// We're a leaf pane, so just add one more row or column (unless isMinimumSize
2946
2991
// is true, see below).
@@ -2955,11 +3000,11 @@ void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& si
2955
3000
}
2956
3001
else
2957
3002
{
2958
- const auto cellSize = _control .CharacterDimensions ();
3003
+ const auto cellSize = termControl .CharacterDimensions ();
2959
3004
sizeNode.size += widthOrHeight ? cellSize.Width : cellSize.Height ;
2960
3005
}
2961
3006
}
2962
- else
3007
+ else if (! _IsLeaf ())
2963
3008
{
2964
3009
// We're a parent pane, so we have to advance dimension of our children panes. In
2965
3010
// fact, we advance only one child (chosen later) to keep the growth fine-grained.
@@ -3061,7 +3106,8 @@ Size Pane::_GetMinSize() const
3061
3106
{
3062
3107
if (_IsLeaf ())
3063
3108
{
3064
- auto controlSize = _control.MinimumSize ();
3109
+ const auto & termControl{ _control.try_as <TermControl>() };
3110
+ auto controlSize = termControl ? termControl.MinimumSize () : Size{ 1 , 1 };
3065
3111
auto newWidth = controlSize.Width ;
3066
3112
auto newHeight = controlSize.Height ;
3067
3113
@@ -3247,7 +3293,8 @@ std::optional<SplitDirection> Pane::PreCalculateAutoSplit(const std::shared_ptr<
3247
3293
// - Returns true if the pane or one of its descendants is read-only
3248
3294
bool Pane::ContainsReadOnly () const
3249
3295
{
3250
- return _IsLeaf () ? _control.ReadOnly () : (_firstChild->ContainsReadOnly () || _secondChild->ContainsReadOnly ());
3296
+ const auto & termControl{ GetTerminalControl () };
3297
+ return termControl ? termControl.ReadOnly () : (_firstChild->ContainsReadOnly () || _secondChild->ContainsReadOnly ());
3251
3298
}
3252
3299
3253
3300
// Method Description:
@@ -3260,13 +3307,14 @@ bool Pane::ContainsReadOnly() const
3260
3307
// - <none>
3261
3308
void Pane::CollectTaskbarStates (std::vector<winrt::TerminalApp::TaskbarState>& states)
3262
3309
{
3263
- if (_IsLeaf ())
3310
+ const auto & termControl{ GetTerminalControl () };
3311
+ if (termControl)
3264
3312
{
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 ()) };
3267
3315
states.push_back (tbState);
3268
3316
}
3269
- else
3317
+ else if (! _IsLeaf ())
3270
3318
{
3271
3319
_firstChild->CollectTaskbarStates (states);
3272
3320
_secondChild->CollectTaskbarStates (states);
0 commit comments