mirror of
https://github.com/microsoft/terminal.git
synced 2026-07-08 18:16:28 +00:00
Fixes xbox controller crashing the Terminal (#20234)
## Summary of the Pull Request Fixes a denial of service by a toddler with an Xbox controller wanting to play Forza. They can impatiently press up and down and close out the terminal window. Issue is upstream in WinUI, but I think this gathers things into a state where Terminal can at least recover by adding a `GettingFocus` handler on the `TabViewItem` that cancels that gamepad focus move before it reaches the framework handler. ## References and Relevant Issues Issue #19671 and #20089 ## Validation Steps Performed Handed a controller to my toddler while working in terminal. I also banged on the keys myself. ## PR Checklist Closes #19671 Closes #20089
This commit is contained in:
1
.github/actions/spelling/allow/microsoft.txt
vendored
1
.github/actions/spelling/allow/microsoft.txt
vendored
@@ -78,4 +78,5 @@ wtl
|
||||
wtt
|
||||
wttlog
|
||||
Xamarin
|
||||
XBOX
|
||||
xfgcheck
|
||||
|
||||
@@ -162,6 +162,40 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
// BODGY: Work around a fail-fast crash in WinUI 2's TabView. When a
|
||||
// game controller (e.g. an XBOX controller's d-pad/stick) moves focus
|
||||
// Up or Down between two TabViewItems, MUX's TabView::OnListViewGettingFocus
|
||||
// runs a GameController-only code path that calls
|
||||
// DispatcherQueue.TryEnqueue, which fails with E_INVALIDARG. That
|
||||
// unhandled error inside a GettingFocus callback makes XAML fail-fast,
|
||||
// and the whole window vanishes. See
|
||||
// microsoft-ui-xaml/blob/840c6cd4ac9d16d9aa99b24f0bd43997fe21bef8/dev/TabView/TabView.cpp#L246
|
||||
//
|
||||
// This GettingFocus handler is on the TabViewItem, which is closer to
|
||||
// the focus source than the TabViewListView that MUX's handler lives
|
||||
// on, so it runs first. Marking the event Handled - and cancelling the
|
||||
// focus move, which is exactly what MUX itself does for the keyboard
|
||||
// case - preempts MUX's broken handler. Keyboard navigation is left
|
||||
// untouched; MUX handles that path safely.
|
||||
TabViewItem().GettingFocus([](auto&&, const winrt::WUX::Input::GettingFocusEventArgs& args) {
|
||||
const auto direction{ args.Direction() };
|
||||
if (direction != winrt::WUX::Input::FocusNavigationDirection::Up &&
|
||||
direction != winrt::WUX::Input::FocusNavigationDirection::Down)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (args.InputDevice() != winrt::WUX::Input::FocusInputDeviceKind::GameController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (args.OldFocusedElement().try_as<winrt::MUX::Controls::TabViewItem>() &&
|
||||
args.NewFocusedElement().try_as<winrt::MUX::Controls::TabViewItem>())
|
||||
{
|
||||
args.Cancel(true);
|
||||
args.Handled(true);
|
||||
}
|
||||
});
|
||||
|
||||
UpdateTitle();
|
||||
_RecalculateAndApplyTabColor();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user