Skip to content

Commit b2d8d70

Browse files
committed
Work around XAML Islands issue with TextCommandBarFlyout
As reported in microsoft/microsoft-ui-xaml#5341, the singleton TextCommandBarFlyout for the XAML TextBox and TextBlock components are limited to one window. When the flyout opens on a different window after already being opened on another, the first window the flyout was opened on gets focus, and the flyout is immediately closed. This change creates a TextCommandBarFlyout per TextInput native view and per selection TextBlock native view.
1 parent 4ba8f26 commit b2d8d70

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

vnext/Microsoft.ReactNative/Views/TextInputViewManager.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "TextInputViewManager.h"
77

88
#include "Unicode.h"
9+
#include "Utils/Helpers.h"
910

1011
#include <UI.Xaml.Controls.h>
1112
#include <UI.Xaml.Input.h>
@@ -804,6 +805,18 @@ ShadowNode *TextInputViewManager::createShadow() const {
804805

805806
XamlView TextInputViewManager::CreateViewCore(int64_t /*tag*/, const winrt::Microsoft::ReactNative::JSValueObject &) {
806807
xaml::Controls::TextBox textBox;
808+
// This works around a XAML Islands bug where the XamlRoot of the first
809+
// window the flyout is shown on takes ownership of the flyout and attempts
810+
// to show the flyout on other windows cause the first window to get focus.
811+
// https://github.com/microsoft/microsoft-ui-xaml/issues/5341
812+
if (IsXamlIsland() &&
813+
winrt::Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(
814+
L"Windows.Foundation.UniversalApiContract", 7)) {
815+
xaml::Controls::TextCommandBarFlyout flyout;
816+
flyout.Placement(xaml::Controls::Primitives::FlyoutPlacementMode::BottomEdgeAlignedLeft);
817+
textBox.ContextFlyout(flyout);
818+
textBox.SelectionFlyout(flyout);
819+
}
807820
return textBox;
808821
}
809822

vnext/Microsoft.ReactNative/Views/TextViewManager.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
#include "pch.h"
55

66
#include "TextViewManager.h"
7+
#include "Utils/Helpers.h"
78

89
#include <Views/RawTextViewManager.h>
910
#include <Views/ShadowNodeBase.h>
1011
#include <Views/VirtualTextViewManager.h>
1112

1213
#include <UI.Xaml.Automation.Peers.h>
1314
#include <UI.Xaml.Automation.h>
15+
#include <UI.Xaml.Controls.Primitives.h>
1416
#include <UI.Xaml.Controls.h>
1517
#include <UI.Xaml.Documents.h>
1618
#include <Utils/PropertyUtils.h>
@@ -211,10 +213,24 @@ bool TextViewManager::UpdateProperty(
211213
textBlock.ClearValue(xaml::Controls::TextBlock::LineStackingStrategyProperty());
212214
}
213215
} else if (propertyName == "selectable") {
214-
if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Boolean)
215-
textBlock.IsTextSelectionEnabled(propertyValue.AsBoolean());
216-
else if (propertyValue.IsNull())
216+
if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Boolean) {
217+
const auto selectable = propertyValue.AsBoolean();
218+
textBlock.IsTextSelectionEnabled(selectable);
219+
// This works around a XAML Islands bug where the XamlRoot of the first
220+
// window the flyout is shown on takes ownership of the flyout and attempts
221+
// to show the flyout on other windows cause the first window to get focus.
222+
// https://github.com/microsoft/microsoft-ui-xaml/issues/5341
223+
if (selectable && IsXamlIsland() &&
224+
winrt::Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(
225+
L"Windows.Foundation.UniversalApiContract", 7)) {
226+
xaml::Controls::TextCommandBarFlyout flyout;
227+
flyout.Placement(xaml::Controls::Primitives::FlyoutPlacementMode::BottomEdgeAlignedLeft);
228+
textBlock.ContextFlyout(flyout);
229+
textBlock.SelectionFlyout(flyout);
230+
}
231+
} else if (propertyValue.IsNull()) {
217232
textBlock.ClearValue(xaml::Controls::TextBlock::IsTextSelectionEnabledProperty());
233+
}
218234
} else if (propertyName == "allowFontScaling") {
219235
if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Boolean) {
220236
textBlock.IsTextScaleFactorEnabled(propertyValue.AsBoolean());

0 commit comments

Comments
 (0)