From 3e47d800bddacd3c89dac8d6dc6f126a8898a1a2 Mon Sep 17 00:00:00 2001 From: "Jon Thysell (JAUNTY)" Date: Tue, 28 Sep 2021 10:14:57 -0700 Subject: [PATCH 1/6] Switch to MUX:CommandBarFlyout in XAML Islands proofing menu This fixes the broken keyboard navigation in an islands app, however it can cause a crash when using WinUI 2.6 (but is fixed in WinUI 2.7). Closes #8306 --- vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp | 4 ++-- vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp index 04bfd094667..949be872605 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp @@ -30,9 +30,9 @@ struct CustomAppBarButton : xaml::Controls::AppBarButtonT { } }; -void FixProofingMenuCrashForXamlIsland(xaml::Controls::TextCommandBarFlyout const &flyout) { +void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase const &flyout) { flyout.Opening([](winrt::IInspectable const &sender, auto &&) { - const auto &flyout = sender.as(); + const auto &flyout = sender.as(); if (const auto &textBox = flyout.Target().try_as()) { const auto &commands = flyout.SecondaryCommands(); for (uint32_t i = 0; i < commands.Size(); ++i) { diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h index d00d4f1ed95..87c8c728df8 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h @@ -8,9 +8,11 @@ #include #include +#include + namespace Microsoft::ReactNative { -void FixProofingMenuCrashForXamlIsland(xaml::Controls::TextCommandBarFlyout const &flyout); +void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase const &flyout); template inline void EnsureUniqueTextFlyoutForXamlIsland(T const &textView) { @@ -19,7 +21,7 @@ inline void EnsureUniqueTextFlyoutForXamlIsland(T const &textView) { // to show the flyout on other windows cause the first window to get focus. // https://github.com/microsoft/microsoft-ui-xaml/issues/5341 if (IsXamlIsland()) { - xaml::Controls::TextCommandBarFlyout flyout; + winrt::Microsoft::UI::Xaml::Controls::TextCommandBarFlyout flyout; flyout.Placement(xaml::Controls::Primitives::FlyoutPlacementMode::BottomEdgeAlignedLeft); // This works around a XAML Islands bug where the Proofing sub-menu for From b568ada877b421adc25b3ed315dbe9dc1a12f0e1 Mon Sep 17 00:00:00 2001 From: "Jon Thysell (JAUNTY)" Date: Tue, 28 Sep 2021 10:21:32 -0700 Subject: [PATCH 2/6] Change files --- ...ative-windows-77e0d25a-8269-4693-8568-96ba49675a87.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-77e0d25a-8269-4693-8568-96ba49675a87.json diff --git a/change/react-native-windows-77e0d25a-8269-4693-8568-96ba49675a87.json b/change/react-native-windows-77e0d25a-8269-4693-8568-96ba49675a87.json new file mode 100644 index 00000000000..27812246d03 --- /dev/null +++ b/change/react-native-windows-77e0d25a-8269-4693-8568-96ba49675a87.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Switch to MUX:CommandBarFlyout in XAML Islands proofing menu", + "packageName": "react-native-windows", + "email": "jthysell@microsoft.com", + "dependentChangeType": "patch" +} From ba00bb2710a2c2f68aab9d124773eb7268a750f0 Mon Sep 17 00:00:00 2001 From: "Jon Thysell (JAUNTY)" Date: Tue, 28 Sep 2021 11:04:37 -0700 Subject: [PATCH 3/6] Added focus workaround --- vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp index 949be872605..eab3146ad6c 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp @@ -37,7 +37,16 @@ void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase co const auto &commands = flyout.SecondaryCommands(); for (uint32_t i = 0; i < commands.Size(); ++i) { if (const auto &appBarButton = commands.GetAt(i).try_as()) { - if (appBarButton.Flyout() == textBox.ProofingMenuFlyout()) { + if (!appBarButton.Flyout()) { + // This works around a loss of focus on the Proofing sub-menu when clicking on + // on the menu items. + // https://github.com/microsoft/microsoft-ui-xaml/issues/5818 + appBarButton.Click([weakCommandBarFlyout = winrt::make_weak(cbf)](auto &&...) { + if (auto flyout = weakCommandBarFlyout.get()) { + Xaml::Input::FocusManager::TryFocusAsync(flyout.Target(), FocusState::Programmatic); + } + }); + } else if (appBarButton.Flyout() == textBox.ProofingMenuFlyout()) { // Replace the AppBarButton for the proofing menu with one that doesn't crash const auto customAppBarButton = winrt::make(); customAppBarButton.Label(appBarButton.Label()); From 31784f0701c0668e8ee5ea6d2825d1af175a3169 Mon Sep 17 00:00:00 2001 From: "Jon Thysell (JAUNTY)" Date: Tue, 28 Sep 2021 12:00:53 -0700 Subject: [PATCH 4/6] fix build --- vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp index eab3146ad6c..aaebd48157c 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp @@ -41,7 +41,7 @@ void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase co // This works around a loss of focus on the Proofing sub-menu when clicking on // on the menu items. // https://github.com/microsoft/microsoft-ui-xaml/issues/5818 - appBarButton.Click([weakCommandBarFlyout = winrt::make_weak(cbf)](auto &&...) { + appBarButton.Click([weakCommandBarFlyout = winrt::make_weak(flyout)](auto &&...) { if (auto flyout = weakCommandBarFlyout.get()) { Xaml::Input::FocusManager::TryFocusAsync(flyout.Target(), FocusState::Programmatic); } From e04dfc58832d4f2e518ecfc4005719e4fe764cd5 Mon Sep 17 00:00:00 2001 From: Jon Thysell Date: Tue, 28 Sep 2021 12:19:37 -0700 Subject: [PATCH 5/6] Update vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp Co-authored-by: Liron Yahdav --- vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp index aaebd48157c..67527b5f518 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp @@ -38,7 +38,7 @@ void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase co for (uint32_t i = 0; i < commands.Size(); ++i) { if (const auto &appBarButton = commands.GetAt(i).try_as()) { if (!appBarButton.Flyout()) { - // This works around a loss of focus on the Proofing sub-menu when clicking on + // This works around a loss of focus from the target element when clicking on // on the menu items. // https://github.com/microsoft/microsoft-ui-xaml/issues/5818 appBarButton.Click([weakCommandBarFlyout = winrt::make_weak(flyout)](auto &&...) { From 5746fdb78845f0c255cf3608c311864916528810 Mon Sep 17 00:00:00 2001 From: "Jon Thysell (JAUNTY)" Date: Tue, 28 Sep 2021 12:47:22 -0700 Subject: [PATCH 6/6] fix build --- vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp index aaebd48157c..64635608951 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp @@ -43,7 +43,7 @@ void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase co // https://github.com/microsoft/microsoft-ui-xaml/issues/5818 appBarButton.Click([weakCommandBarFlyout = winrt::make_weak(flyout)](auto &&...) { if (auto flyout = weakCommandBarFlyout.get()) { - Xaml::Input::FocusManager::TryFocusAsync(flyout.Target(), FocusState::Programmatic); + xaml::Input::FocusManager::TryFocusAsync(flyout.Target(), xaml::FocusState::Programmatic); } }); } else if (appBarButton.Flyout() == textBox.ProofingMenuFlyout()) {