Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "[Fabric] Handle scalefactor changes",
"packageName": "react-native-windows",
"email": "30809111+acoates-ms@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ void ParagraphComponentView::updateState(
m_textLayout = nullptr;
}

void ParagraphComponentView::updateLayoutMetrics(
facebook::react::LayoutMetrics const &layoutMetrics,
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
Super::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);

if (layoutMetrics.pointScaleFactor != oldLayoutMetrics.pointScaleFactor) {
m_textLayout = nullptr;
}
}

void ParagraphComponentView::FinalizeUpdates(
winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept {
ensureVisual();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept
override;
void updateEventEmitter(facebook::react::EventEmitter::Shared const &eventEmitter) noexcept override;
void updateLayoutMetrics(
facebook::react::LayoutMetrics const &layoutMetrics,
facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
void updateState(facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept
override;
void FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ inline Mso::Future<void> CompositionReactViewInstance::PostInUIQueue(TAction &&a
return promise.AsFuture();
}

void ApplyConstraints(
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraintsIn,
facebook::react::LayoutConstraints &layoutConstraintsOut) noexcept {
layoutConstraintsOut.minimumSize = {layoutConstraintsIn.MinimumSize.Width, layoutConstraintsIn.MinimumSize.Height};
layoutConstraintsOut.maximumSize = {layoutConstraintsIn.MaximumSize.Width, layoutConstraintsIn.MaximumSize.Height};
layoutConstraintsOut.layoutDirection =
static_cast<facebook::react::LayoutDirection>(layoutConstraintsIn.LayoutDirection);
}

ReactNativeIsland::ReactNativeIsland() noexcept {}

#ifdef USE_WINUI3
Expand All @@ -136,6 +145,7 @@ ReactNativeIsland::~ReactNativeIsland() noexcept {
#ifdef USE_WINUI3
if (m_island && m_island.IsConnected()) {
m_island.AutomationProviderRequested(m_islandAutomationProviderRequestedToken);
m_island.StateChanged(m_islandStateChangedToken);
}
#endif

Expand Down Expand Up @@ -251,6 +261,7 @@ void ReactNativeIsland::ScaleFactor(float value) noexcept {
rootView.Scale({invScale, invScale, invScale});
}
UpdateRootVisualSize();
Arrange(m_layoutConstraints, m_viewportOffset);
}
}

Expand Down Expand Up @@ -480,10 +491,14 @@ void ReactNativeIsland::ShowInstanceLoaded() noexcept {
initProps = folly::dynamic::object();
}
initProps["concurrentRoot"] = true;

facebook::react::LayoutConstraints fbLayoutConstraints;
ApplyConstraints(m_layoutConstraints, fbLayoutConstraints);

uiManager->startSurface(
*this,
static_cast<facebook::react::SurfaceId>(m_rootTag),
m_layoutConstraints,
fbLayoutConstraints,
to_string(m_reactViewOptions.ComponentName()),
initProps);

Expand All @@ -500,16 +515,21 @@ facebook::react::AttributedStringBox CreateLoadingAttributedString() noexcept {
return facebook::react::AttributedStringBox{attributedString};
}

facebook::react::Size MeasureLoading(const facebook::react::LayoutConstraints &layoutConstraints, float scaleFactor) {
facebook::react::Size MeasureLoading(
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
float scaleFactor) {
facebook::react::LayoutConstraints fbLayoutConstraints;
ApplyConstraints(layoutConstraints, fbLayoutConstraints);

auto attributedStringBox = CreateLoadingAttributedString();
winrt::com_ptr<::IDWriteTextLayout> textLayout;
facebook::react::TextLayoutManager::GetTextLayout(
attributedStringBox, {} /*paragraphAttributes*/, layoutConstraints, textLayout);
attributedStringBox, {} /*paragraphAttributes*/, fbLayoutConstraints, textLayout);

DWRITE_TEXT_METRICS tm;
winrt::check_hresult(textLayout->GetMetrics(&tm));

return layoutConstraints.clamp(
return fbLayoutConstraints.clamp(
{loadingActivityHorizontalOffset * scaleFactor + tm.width, loadingBarHeight * scaleFactor});
}

Expand Down Expand Up @@ -634,15 +654,6 @@ void ReactNativeIsland::ShowInstanceLoading() noexcept {
InternalRootVisual().InsertAt(m_loadingVisual, m_hasRenderedVisual ? 1 : 0);
}

void ApplyConstraints(
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraintsIn,
facebook::react::LayoutConstraints &layoutConstraintsOut) noexcept {
layoutConstraintsOut.minimumSize = {layoutConstraintsIn.MinimumSize.Width, layoutConstraintsIn.MinimumSize.Height};
layoutConstraintsOut.maximumSize = {layoutConstraintsIn.MaximumSize.Width, layoutConstraintsIn.MaximumSize.Height};
layoutConstraintsOut.layoutDirection =
static_cast<facebook::react::LayoutDirection>(layoutConstraintsIn.LayoutDirection);
}

winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
const winrt::Windows::Foundation::Point &viewportOffset) const noexcept {
Expand All @@ -663,7 +674,7 @@ winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
size = fabricuiManager->measureSurface(static_cast<facebook::react::SurfaceId>(m_rootTag), constraints, context);
}
} else if (m_loadingVisual) {
size = MeasureLoading(constraints, m_scaleFactor);
size = MeasureLoading(layoutConstraints, m_scaleFactor);
}

auto clampedSize = constraints.clamp(size);
Expand All @@ -673,7 +684,10 @@ winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
void ReactNativeIsland::Arrange(
const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
const winrt::Windows::Foundation::Point &viewportOffset) noexcept {
ApplyConstraints(layoutConstraints, m_layoutConstraints);
m_layoutConstraints = layoutConstraints;
m_viewportOffset = viewportOffset;
facebook::react::LayoutConstraints fbLayoutConstraints;
ApplyConstraints(layoutConstraints, fbLayoutConstraints);

if (m_isInitialized && m_rootTag != -1) {
if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
Expand All @@ -684,11 +698,11 @@ void ReactNativeIsland::Arrange(
context.viewportOffset = {viewportOffset.X, viewportOffset.Y};

fabricuiManager->constraintSurfaceLayout(
static_cast<facebook::react::SurfaceId>(m_rootTag), m_layoutConstraints, context);
static_cast<facebook::react::SurfaceId>(m_rootTag), fbLayoutConstraints, context);
}
} else if (m_loadingVisual) {
// TODO: Resize to align loading
auto s = m_layoutConstraints.clamp(MeasureLoading(m_layoutConstraints, m_scaleFactor));
auto s = fbLayoutConstraints.clamp(MeasureLoading(layoutConstraints, m_scaleFactor));
NotifySizeChanged();
}
}
Expand Down Expand Up @@ -738,6 +752,17 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
pThis->m_island = nullptr;
}
});

m_islandStateChangedToken =
m_island.StateChanged([weakThis = get_weak()](
winrt::Microsoft::UI::Content::ContentIsland const &island,
winrt::Microsoft::UI::Content::ContentIslandStateChangedEventArgs const &args) {
if (auto pThis = weakThis.get()) {
if (args.DidRasterizationScaleChange()) {
pThis->ScaleFactor(island.RasterizationScale());
}
}
});
}
return m_island;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ struct ReactNativeIsland
winrt::Microsoft::UI::Content::ContentIsland m_island{nullptr};
winrt::event_token m_islandFrameworkClosedToken;
winrt::event_token m_islandAutomationProviderRequestedToken;
winrt::event_token m_islandStateChangedToken;
#endif

HWND m_hwnd{0};
Expand All @@ -147,7 +148,8 @@ struct ReactNativeIsland
winrt::Microsoft::ReactNative::Composition::ICustomResourceLoader m_resources{nullptr};
winrt::Microsoft::ReactNative::Composition::Theme m_theme{nullptr};
winrt::Microsoft::ReactNative::Composition::Theme::ThemeChanged_revoker m_themeChangedRevoker;
facebook::react::LayoutConstraints m_layoutConstraints;
winrt::Microsoft::ReactNative::LayoutConstraints m_layoutConstraints;
winrt::Windows::Foundation::Point m_viewportOffset{0, 0};
winrt::event<winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs>>
m_sizeChangedEvent;

Expand Down
5 changes: 5 additions & 0 deletions vnext/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ WindowsImageManager::GetImageRandomAccessStreamAsync(ReactImageSource source) co
}

winrt::Windows::Storage::StorageFile file(co_await getFileSync);

if (!file) {
co_return winrt::Microsoft::ReactNative::Composition::ImageFailedResponse(L"Failed to get file.");
}

co_return winrt::Microsoft::ReactNative::Composition::StreamImageResponse(co_await file.OpenReadAsync());
}

Expand Down