Make sure we keep event handlers on the control when detaching a pane (#11039)
When moving a pane to a new tab previously we removed the event handlers on it as if we were closing it, but we are just moving it so we need to keep them. I tried really hard to make sure all of the events were hooked up correctly, but I guess I missed these originally since they are normally created in the Pane constructor. Closes #11035 ## Validation Steps Performed created panes, moved them to new tabs, confirmed that they close and ding appropriately.
This commit is contained in:
parent
ea58e4036b
commit
2c5a35f1be
|
@ -58,8 +58,8 @@ Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFo
|
||||||
_root.Background(s_unfocusedBorderBrush);
|
_root.Background(s_unfocusedBorderBrush);
|
||||||
|
|
||||||
// Register an event with the control to have it inform us when it gains focus.
|
// Register an event with the control to have it inform us when it gains focus.
|
||||||
_gotFocusRevoker = control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
|
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
|
||||||
_lostFocusRevoker = control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
|
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
|
||||||
|
|
||||||
// When our border is tapped, make sure to transfer focus to our control.
|
// When our border is tapped, make sure to transfer focus to our control.
|
||||||
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
|
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
|
||||||
|
@ -1202,7 +1202,7 @@ std::shared_ptr<Pane> Pane::DetachPane(std::shared_ptr<Pane> pane)
|
||||||
auto detached = isFirstChild ? _firstChild : _secondChild;
|
auto detached = isFirstChild ? _firstChild : _secondChild;
|
||||||
// Remove the child from the tree, replace the current node with the
|
// Remove the child from the tree, replace the current node with the
|
||||||
// other child.
|
// other child.
|
||||||
_CloseChild(isFirstChild);
|
_CloseChild(isFirstChild, true);
|
||||||
|
|
||||||
detached->_borders = Borders::None;
|
detached->_borders = Borders::None;
|
||||||
detached->_UpdateBorders();
|
detached->_UpdateBorders();
|
||||||
|
@ -1230,9 +1230,12 @@ std::shared_ptr<Pane> Pane::DetachPane(std::shared_ptr<Pane> pane)
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - closeFirst: if true, the first child should be closed, and the second
|
// - closeFirst: if true, the first child should be closed, and the second
|
||||||
// should be preserved, and vice-versa for false.
|
// should be preserved, and vice-versa for false.
|
||||||
|
// - isDetaching: if true, then the pane event handlers for the closed child
|
||||||
|
// should be kept, this way they don't have to be recreated when it is later
|
||||||
|
// reattached to a tree somewhere as the control moves with the pane.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
void Pane::_CloseChild(const bool closeFirst)
|
void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
|
||||||
{
|
{
|
||||||
// Lock the create/close lock so that another operation won't concurrently
|
// Lock the create/close lock so that another operation won't concurrently
|
||||||
// modify our tree
|
// modify our tree
|
||||||
|
@ -1250,6 +1253,8 @@ void Pane::_CloseChild(const bool closeFirst)
|
||||||
|
|
||||||
auto closedChild = closeFirst ? _firstChild : _secondChild;
|
auto closedChild = closeFirst ? _firstChild : _secondChild;
|
||||||
auto remainingChild = closeFirst ? _secondChild : _firstChild;
|
auto remainingChild = closeFirst ? _secondChild : _firstChild;
|
||||||
|
auto closedChildClosedToken = closeFirst ? _firstClosedToken : _secondClosedToken;
|
||||||
|
auto remainingChildClosedToken = closeFirst ? _secondClosedToken : _firstClosedToken;
|
||||||
|
|
||||||
// If the only child left is a leaf, that means we're a leaf now.
|
// If the only child left is a leaf, that means we're a leaf now.
|
||||||
if (remainingChild->_IsLeaf())
|
if (remainingChild->_IsLeaf())
|
||||||
|
@ -1275,11 +1280,18 @@ void Pane::_CloseChild(const bool closeFirst)
|
||||||
// themselves closing, and remove their handlers for their controls
|
// themselves closing, and remove their handlers for their controls
|
||||||
// closing. At this point, if the remaining child's control is closed,
|
// closing. At this point, if the remaining child's control is closed,
|
||||||
// they'll trigger only our event handler for the control's close.
|
// they'll trigger only our event handler for the control's close.
|
||||||
_firstChild->Closed(_firstClosedToken);
|
|
||||||
_secondChild->Closed(_secondClosedToken);
|
// However, if we are detaching the pane we want to keep its control
|
||||||
closedChild->_control.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
// handlers since it is just getting moved.
|
||||||
|
if (!isDetaching)
|
||||||
|
{
|
||||||
|
closedChild->_control.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
||||||
|
closedChild->_control.WarningBell(closedChild->_warningBellToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedChild->Closed(closedChildClosedToken);
|
||||||
|
remainingChild->Closed(remainingChildClosedToken);
|
||||||
remainingChild->_control.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
|
remainingChild->_control.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
|
||||||
closedChild->_control.WarningBell(closedChild->_warningBellToken);
|
|
||||||
remainingChild->_control.WarningBell(remainingChild->_warningBellToken);
|
remainingChild->_control.WarningBell(remainingChild->_warningBellToken);
|
||||||
|
|
||||||
// If either of our children was focused, we want to take that focus from
|
// If either of our children was focused, we want to take that focus from
|
||||||
|
@ -1339,12 +1351,6 @@ void Pane::_CloseChild(const bool closeFirst)
|
||||||
// Find what borders need to persist after we close the child
|
// Find what borders need to persist after we close the child
|
||||||
auto remainingBorders = _GetCommonBorders();
|
auto remainingBorders = _GetCommonBorders();
|
||||||
|
|
||||||
// First stash away references to the old panes and their tokens
|
|
||||||
const auto oldFirstToken = _firstClosedToken;
|
|
||||||
const auto oldSecondToken = _secondClosedToken;
|
|
||||||
const auto oldFirst = _firstChild;
|
|
||||||
const auto oldSecond = _secondChild;
|
|
||||||
|
|
||||||
// Steal all the state from our child
|
// Steal all the state from our child
|
||||||
_splitState = remainingChild->_splitState;
|
_splitState = remainingChild->_splitState;
|
||||||
_firstChild = remainingChild->_firstChild;
|
_firstChild = remainingChild->_firstChild;
|
||||||
|
@ -1357,11 +1363,14 @@ void Pane::_CloseChild(const bool closeFirst)
|
||||||
_firstChild->Closed(remainingChild->_firstClosedToken);
|
_firstChild->Closed(remainingChild->_firstClosedToken);
|
||||||
_secondChild->Closed(remainingChild->_secondClosedToken);
|
_secondChild->Closed(remainingChild->_secondClosedToken);
|
||||||
|
|
||||||
// Revoke event handlers on old panes and controls
|
// Remove the event handlers on the old children
|
||||||
oldFirst->Closed(oldFirstToken);
|
remainingChild->Closed(remainingChildClosedToken);
|
||||||
oldSecond->Closed(oldSecondToken);
|
closedChild->Closed(closedChildClosedToken);
|
||||||
closedChild->_control.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
if (!isDetaching)
|
||||||
closedChild->_control.WarningBell(closedChild->_warningBellToken);
|
{
|
||||||
|
closedChild->_control.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
||||||
|
closedChild->_control.WarningBell(closedChild->_warningBellToken);
|
||||||
|
}
|
||||||
|
|
||||||
// Reset our UI:
|
// Reset our UI:
|
||||||
_root.Children().Clear();
|
_root.Children().Clear();
|
||||||
|
@ -1432,7 +1441,7 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst)
|
||||||
// this one doesn't seem to.
|
// this one doesn't seem to.
|
||||||
if (!animationsEnabledInOS || !animationsEnabledInApp || eitherChildZoomed)
|
if (!animationsEnabledInOS || !animationsEnabledInApp || eitherChildZoomed)
|
||||||
{
|
{
|
||||||
pane->_CloseChild(closeFirst);
|
pane->_CloseChild(closeFirst, false);
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1539,7 +1548,7 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst)
|
||||||
{
|
{
|
||||||
// We don't need to manually undo any of the above trickiness.
|
// We don't need to manually undo any of the above trickiness.
|
||||||
// We're going to re-parent the child's content into us anyways
|
// We're going to re-parent the child's content into us anyways
|
||||||
pane->_CloseChild(closeFirst);
|
pane->_CloseChild(closeFirst, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,7 +210,7 @@ private:
|
||||||
const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction,
|
const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction,
|
||||||
const PanePoint offset);
|
const PanePoint offset);
|
||||||
|
|
||||||
void _CloseChild(const bool closeFirst);
|
void _CloseChild(const bool closeFirst, const bool isDetaching);
|
||||||
winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst);
|
winrt::fire_and_forget _CloseChildRoutine(const bool closeFirst);
|
||||||
|
|
||||||
void _FocusFirstChild();
|
void _FocusFirstChild();
|
||||||
|
|
Loading…
Reference in a new issue