diff --git a/.github/actions/spelling/allow/microsoft.txt b/.github/actions/spelling/allow/microsoft.txt index f43408388b..782754a012 100644 --- a/.github/actions/spelling/allow/microsoft.txt +++ b/.github/actions/spelling/allow/microsoft.txt @@ -78,4 +78,5 @@ wtl wtt wttlog Xamarin +XBOX xfgcheck diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index da4d0896ae..2ca1bb1d77 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -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() && + args.NewFocusedElement().try_as()) + { + args.Cancel(true); + args.Handled(true); + } + }); + UpdateTitle(); _RecalculateAndApplyTabColor(); }