react-native-windows 0.82.0-preview.10 → 0.82.0-preview.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Microsoft.ReactNative/CompositionComponentView.idl +3 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +84 -17
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +4 -0
- package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +50 -15
- package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +7 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +33 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +17 -0
- package/PropertySheets/Generated/PackageVersion.g.props +2 -2
- package/PropertySheets/WinUI.props +1 -1
- package/Scripts/NuGetRestoreForceEvaluateAllSolutions.ps1 +5 -11
- package/package.json +1 -1
|
@@ -154,6 +154,9 @@ namespace Microsoft.ReactNative.Composition
|
|
|
154
154
|
[webhosthidden]
|
|
155
155
|
[default_interface]
|
|
156
156
|
runtimeclass ScrollViewComponentView : ViewComponentView {
|
|
157
|
+
// Issue #15557: Event fired when scroll position changes.
|
|
158
|
+
// ContentIslandComponentView uses this to update LocalToParentTransformMatrix.
|
|
159
|
+
event Windows.Foundation.EventHandler<IInspectable> ViewChanged;
|
|
157
160
|
};
|
|
158
161
|
|
|
159
162
|
[experimental]
|
|
@@ -36,10 +36,11 @@ constexpr float FOCUS_VISUAL_RADIUS = 3.0f;
|
|
|
36
36
|
|
|
37
37
|
// m_outerVisual
|
|
38
38
|
// |
|
|
39
|
-
// |
|
|
40
39
|
// ----- m_visual <-- Background / clip - Can be a custom visual depending on Component type
|
|
41
40
|
// |
|
|
42
41
|
// ----- Border Visuals x N (BorderPrimitive attached to m_visual)
|
|
42
|
+
// ----- <children> (default: directly in m_visual after border visuals)
|
|
43
|
+
// ----- m_childrenContainer (created on demand when overflow:hidden, children moved here)
|
|
43
44
|
// ------Focus Visual Container (created when hosting focus visuals)
|
|
44
45
|
// |
|
|
45
46
|
// |------Inner Focus Visual
|
|
@@ -708,7 +709,9 @@ void ComponentView::applyShadowProps(const facebook::react::ViewProps &viewProps
|
|
|
708
709
|
shadow.Color(theme()->Color(*viewProps.shadowColor));
|
|
709
710
|
}
|
|
710
711
|
|
|
711
|
-
Visual
|
|
712
|
+
// Apply shadow to OuterVisual (not Visual) because Visual may have a rounded-corner clip
|
|
713
|
+
// from updateClippingPath, which would clip the shadow. OuterVisual is not clipped.
|
|
714
|
+
OuterVisual().as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Shadow(shadow);
|
|
712
715
|
}
|
|
713
716
|
|
|
714
717
|
void ComponentView::updateTransformProps(
|
|
@@ -892,23 +895,26 @@ void ComponentView::updateClippingPath(
|
|
|
892
895
|
const facebook::react::ViewProps &viewProps) noexcept {
|
|
893
896
|
auto borderMetrics = BorderPrimitive::resolveAndAlignBorderMetrics(layoutMetrics, viewProps);
|
|
894
897
|
|
|
895
|
-
|
|
896
|
-
borderMetrics.borderRadii.
|
|
897
|
-
borderMetrics.borderRadii.
|
|
898
|
-
borderMetrics.borderRadii.
|
|
899
|
-
|
|
900
|
-
|
|
898
|
+
bool hasRoundedCorners = borderMetrics.borderRadii.topLeft.horizontal != 0 ||
|
|
899
|
+
borderMetrics.borderRadii.topRight.horizontal != 0 || borderMetrics.borderRadii.bottomLeft.horizontal != 0 ||
|
|
900
|
+
borderMetrics.borderRadii.bottomRight.horizontal != 0 || borderMetrics.borderRadii.topLeft.vertical != 0 ||
|
|
901
|
+
borderMetrics.borderRadii.topRight.vertical != 0 || borderMetrics.borderRadii.bottomLeft.vertical != 0 ||
|
|
902
|
+
borderMetrics.borderRadii.bottomRight.vertical != 0;
|
|
903
|
+
|
|
904
|
+
const float scale = layoutMetrics.pointScaleFactor;
|
|
905
|
+
const float viewWidth = layoutMetrics.frame.size.width * scale;
|
|
906
|
+
const float viewHeight = layoutMetrics.frame.size.height * scale;
|
|
907
|
+
|
|
908
|
+
// Apply clipping to m_visual only for rounded corners
|
|
909
|
+
// overflow:hidden clipping is handled separately via m_childrenContainer in ViewComponentView
|
|
910
|
+
if (hasRoundedCorners) {
|
|
901
911
|
winrt::com_ptr<ID2D1PathGeometry> pathGeometry = BorderPrimitive::GenerateRoundedRectPathGeometry(
|
|
902
|
-
m_compContext,
|
|
903
|
-
borderMetrics.borderRadii,
|
|
904
|
-
{0, 0, 0, 0},
|
|
905
|
-
{0,
|
|
906
|
-
0,
|
|
907
|
-
layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
|
|
908
|
-
layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
|
|
912
|
+
m_compContext, borderMetrics.borderRadii, {0, 0, 0, 0}, {0, 0, viewWidth, viewHeight});
|
|
909
913
|
|
|
910
914
|
Visual().as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(
|
|
911
915
|
pathGeometry.get());
|
|
916
|
+
} else {
|
|
917
|
+
Visual().as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(nullptr);
|
|
912
918
|
}
|
|
913
919
|
}
|
|
914
920
|
|
|
@@ -1083,6 +1089,11 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
|
|
|
1083
1089
|
ViewComponentView::VisualToMountChildrenInto() noexcept {
|
|
1084
1090
|
if (m_builder && m_builder->VisualToMountChildrenIntoHandler())
|
|
1085
1091
|
return m_builder->VisualToMountChildrenIntoHandler()(*this);
|
|
1092
|
+
// When overflow:hidden, children are hosted in m_childrenContainer (child of m_visual)
|
|
1093
|
+
// so we can apply clipping without affecting borders/background.
|
|
1094
|
+
// Otherwise children go directly into Visual() (the original behavior).
|
|
1095
|
+
if (m_childrenContainer)
|
|
1096
|
+
return m_childrenContainer;
|
|
1086
1097
|
return Visual();
|
|
1087
1098
|
}
|
|
1088
1099
|
|
|
@@ -1091,9 +1102,14 @@ void ViewComponentView::MountChildComponentView(
|
|
|
1091
1102
|
uint32_t index) noexcept {
|
|
1092
1103
|
base_type::MountChildComponentView(childComponentView, index);
|
|
1093
1104
|
|
|
1094
|
-
indexOffsetForBorder(index);
|
|
1095
1105
|
ensureVisual();
|
|
1096
1106
|
|
|
1107
|
+
// When children are in Visual() directly, offset past border visuals.
|
|
1108
|
+
// When children are in m_childrenContainer, no offset needed.
|
|
1109
|
+
if (!m_childrenContainer) {
|
|
1110
|
+
indexOffsetForBorder(index);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1097
1113
|
if (auto compositionChild = childComponentView.try_as<ComponentView>()) {
|
|
1098
1114
|
auto visualIndex = index;
|
|
1099
1115
|
// Most of the time child index will align with visual index.
|
|
@@ -1105,6 +1121,7 @@ void ViewComponentView::MountChildComponentView(
|
|
|
1105
1121
|
}
|
|
1106
1122
|
}
|
|
1107
1123
|
}
|
|
1124
|
+
|
|
1108
1125
|
VisualToMountChildrenInto().InsertAt(compositionChild->OuterVisual(), visualIndex);
|
|
1109
1126
|
} else {
|
|
1110
1127
|
m_hasNonVisualChildren = true;
|
|
@@ -1116,7 +1133,6 @@ void ViewComponentView::UnmountChildComponentView(
|
|
|
1116
1133
|
uint32_t index) noexcept {
|
|
1117
1134
|
base_type::UnmountChildComponentView(childComponentView, index);
|
|
1118
1135
|
|
|
1119
|
-
indexOffsetForBorder(index);
|
|
1120
1136
|
if (auto compositionChild = childComponentView.try_as<ComponentView>()) {
|
|
1121
1137
|
VisualToMountChildrenInto().Remove(compositionChild->OuterVisual());
|
|
1122
1138
|
}
|
|
@@ -1316,6 +1332,57 @@ void ViewComponentView::updateLayoutMetrics(
|
|
|
1316
1332
|
Visual().Size(
|
|
1317
1333
|
{layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
|
|
1318
1334
|
layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
|
|
1335
|
+
|
|
1336
|
+
// Update children container clipping for overflow:hidden
|
|
1337
|
+
updateChildrenClippingPath(layoutMetrics, *viewProps());
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
void ViewComponentView::updateChildrenClippingPath(
|
|
1341
|
+
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
1342
|
+
const facebook::react::ViewProps &viewProps) noexcept {
|
|
1343
|
+
const float scale = layoutMetrics.pointScaleFactor;
|
|
1344
|
+
const float viewWidth = layoutMetrics.frame.size.width * scale;
|
|
1345
|
+
const float viewHeight = layoutMetrics.frame.size.height * scale;
|
|
1346
|
+
|
|
1347
|
+
if (viewProps.getClipsContentToBounds()) {
|
|
1348
|
+
// Create m_childrenContainer on demand (like iOS _containerView pattern)
|
|
1349
|
+
// m_childrenContainer is a child of m_visual, placed after border visuals.
|
|
1350
|
+
if (!m_childrenContainer) {
|
|
1351
|
+
m_childrenContainer = m_compContext.CreateSpriteVisual();
|
|
1352
|
+
|
|
1353
|
+
// Insert at the end of m_visual's children (after border visuals + existing children)
|
|
1354
|
+
// Then move existing children from m_visual into m_childrenContainer
|
|
1355
|
+
uint32_t borderCount = 0;
|
|
1356
|
+
indexOffsetForBorder(borderCount);
|
|
1357
|
+
|
|
1358
|
+
// Move existing child visuals from m_visual to m_childrenContainer
|
|
1359
|
+
uint32_t childVisualIndex = 0;
|
|
1360
|
+
for (auto it = m_children.begin(); it != m_children.end(); ++it) {
|
|
1361
|
+
if (auto compositionChild = (*it).try_as<ComponentView>()) {
|
|
1362
|
+
Visual().Remove(compositionChild->OuterVisual());
|
|
1363
|
+
m_childrenContainer.InsertAt(compositionChild->OuterVisual(), childVisualIndex++);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
// Insert m_childrenContainer after border visuals in m_visual
|
|
1368
|
+
Visual().InsertAt(m_childrenContainer, borderCount);
|
|
1369
|
+
|
|
1370
|
+
// Use relative sizing so container automatically tracks parent's size
|
|
1371
|
+
m_childrenContainer.RelativeSizeWithOffset({0, 0}, {1, 1});
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// Clip children to view bounds using outer border radii (matches iOS default behavior)
|
|
1375
|
+
auto borderMetrics = BorderPrimitive::resolveAndAlignBorderMetrics(layoutMetrics, viewProps);
|
|
1376
|
+
winrt::com_ptr<ID2D1PathGeometry> pathGeometry = BorderPrimitive::GenerateRoundedRectPathGeometry(
|
|
1377
|
+
m_compContext, borderMetrics.borderRadii, {0, 0, 0, 0}, {0, 0, viewWidth, viewHeight});
|
|
1378
|
+
|
|
1379
|
+
m_childrenContainer.as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(
|
|
1380
|
+
pathGeometry.get());
|
|
1381
|
+
} else if (m_childrenContainer) {
|
|
1382
|
+
// overflow changed from hidden to visible. Keep container, just remove clip.
|
|
1383
|
+
m_childrenContainer.as<::Microsoft::ReactNative::Composition::Experimental::IVisualInterop>()->SetClippingPath(
|
|
1384
|
+
nullptr);
|
|
1385
|
+
}
|
|
1319
1386
|
}
|
|
1320
1387
|
|
|
1321
1388
|
void ViewComponentView::prepareForRecycle() noexcept {}
|
|
@@ -233,11 +233,15 @@ struct ViewComponentView : public ViewComponentViewT<
|
|
|
233
233
|
|
|
234
234
|
protected:
|
|
235
235
|
virtual winrt::Microsoft::ReactNative::ViewProps ViewPropsInner() noexcept;
|
|
236
|
+
virtual void updateChildrenClippingPath(
|
|
237
|
+
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
238
|
+
const facebook::react::ViewProps &viewProps) noexcept;
|
|
236
239
|
|
|
237
240
|
private:
|
|
238
241
|
bool m_hasNonVisualChildren{false};
|
|
239
242
|
facebook::react::SharedViewProps m_props;
|
|
240
243
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_visual{nullptr};
|
|
244
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_childrenContainer{nullptr};
|
|
241
245
|
winrt::Microsoft::ReactNative::Composition::Experimental::CreateInternalVisualDelegate m_createInternalVisualHandler{
|
|
242
246
|
nullptr};
|
|
243
247
|
};
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#include <winrt/Windows.UI.Composition.h>
|
|
15
15
|
#include "CompositionContextHelper.h"
|
|
16
16
|
#include "RootComponentView.h"
|
|
17
|
+
#include "ScrollViewComponentView.h"
|
|
17
18
|
|
|
18
19
|
#include "Composition.ContentIslandComponentView.g.cpp"
|
|
19
20
|
|
|
@@ -49,6 +50,14 @@ void ContentIslandComponentView::OnMounted() noexcept {
|
|
|
49
50
|
.as<winrt::Microsoft::UI::Composition::ContainerVisual>());
|
|
50
51
|
m_childSiteLink.ActualSize({m_layoutMetrics.frame.size.width, m_layoutMetrics.frame.size.height});
|
|
51
52
|
|
|
53
|
+
// Issue #15557: Set initial LocalToParentTransformMatrix synchronously before Connect.
|
|
54
|
+
// This fixes popup position being wrong even without scrolling.
|
|
55
|
+
// Note: getClientRect() returns physical pixels, but LocalToParentTransformMatrix expects DIPs.
|
|
56
|
+
auto clientRect = getClientRect();
|
|
57
|
+
float scaleFactor = m_layoutMetrics.pointScaleFactor;
|
|
58
|
+
m_childSiteLink.LocalToParentTransformMatrix(winrt::Windows::Foundation::Numerics::make_float4x4_translation(
|
|
59
|
+
static_cast<float>(clientRect.left) / scaleFactor, static_cast<float>(clientRect.top) / scaleFactor, 0.0f));
|
|
60
|
+
|
|
52
61
|
m_navigationHost = winrt::Microsoft::UI::Input::InputFocusNavigationHost::GetForSiteLink(m_childSiteLink);
|
|
53
62
|
|
|
54
63
|
m_navigationHostDepartFocusRequestedToken =
|
|
@@ -80,12 +89,34 @@ void ContentIslandComponentView::OnMounted() noexcept {
|
|
|
80
89
|
strongThis->ParentLayoutChanged();
|
|
81
90
|
}
|
|
82
91
|
}));
|
|
92
|
+
|
|
93
|
+
// Issue #15557: Register for ViewChanged on parent ScrollViews to update transform
|
|
94
|
+
// when scroll position changes, ensuring correct XAML popup positioning.
|
|
95
|
+
if (auto scrollView = view.try_as<winrt::Microsoft::ReactNative::Composition::ScrollViewComponentView>()) {
|
|
96
|
+
auto token =
|
|
97
|
+
scrollView.ViewChanged([wkThis = get_weak()](const winrt::IInspectable &, const winrt::IInspectable &) {
|
|
98
|
+
if (auto strongThis = wkThis.get()) {
|
|
99
|
+
strongThis->ParentLayoutChanged();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
m_viewChangedSubscriptions.push_back({scrollView, token});
|
|
103
|
+
}
|
|
104
|
+
|
|
83
105
|
view = view.Parent();
|
|
84
106
|
}
|
|
85
107
|
}
|
|
86
108
|
|
|
87
109
|
void ContentIslandComponentView::OnUnmounted() noexcept {
|
|
88
110
|
m_layoutMetricChangedRevokers.clear();
|
|
111
|
+
|
|
112
|
+
// Issue #15557: Unsubscribe from parent ScrollView events
|
|
113
|
+
for (auto &subscription : m_viewChangedSubscriptions) {
|
|
114
|
+
if (auto scrollView = subscription.scrollView.get()) {
|
|
115
|
+
scrollView.ViewChanged(subscription.token);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
m_viewChangedSubscriptions.clear();
|
|
119
|
+
|
|
89
120
|
if (m_navigationHostDepartFocusRequestedToken && m_navigationHost) {
|
|
90
121
|
m_navigationHost.DepartFocusRequested(m_navigationHostDepartFocusRequestedToken);
|
|
91
122
|
m_navigationHostDepartFocusRequestedToken = {};
|
|
@@ -93,21 +124,25 @@ void ContentIslandComponentView::OnUnmounted() noexcept {
|
|
|
93
124
|
}
|
|
94
125
|
|
|
95
126
|
void ContentIslandComponentView::ParentLayoutChanged() noexcept {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
// Issue #15557: Update transform synchronously to ensure correct popup position
|
|
128
|
+
// when user clicks. Async updates via UIDispatcher().Post() were causing the
|
|
129
|
+
// popup to open with stale transform values.
|
|
130
|
+
//
|
|
131
|
+
// Note: The original async approach was for batching notifications during layout passes.
|
|
132
|
+
// However, LocalToParentTransformMatrix is a cheap call (just sets a matrix), and
|
|
133
|
+
// synchronous updates are required to ensure correct popup position when clicked.
|
|
134
|
+
//
|
|
135
|
+
// getClientRect() returns values in physical pixels (scaled by pointScaleFactor),
|
|
136
|
+
// but LocalToParentTransformMatrix expects logical pixels (DIPs). We need to divide
|
|
137
|
+
// by the scale factor to convert.
|
|
138
|
+
auto clientRect = getClientRect();
|
|
139
|
+
float scaleFactor = m_layoutMetrics.pointScaleFactor;
|
|
140
|
+
|
|
141
|
+
float x = static_cast<float>(clientRect.left) / scaleFactor;
|
|
142
|
+
float y = static_cast<float>(clientRect.top) / scaleFactor;
|
|
143
|
+
|
|
144
|
+
m_childSiteLink.LocalToParentTransformMatrix(
|
|
145
|
+
winrt::Windows::Foundation::Numerics::make_float4x4_translation(x, y, 0.0f));
|
|
111
146
|
}
|
|
112
147
|
|
|
113
148
|
winrt::Windows::Foundation::IInspectable ContentIslandComponentView::CreateAutomationProvider() noexcept {
|
|
@@ -68,6 +68,13 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
|
|
|
68
68
|
winrt::Microsoft::UI::Input::InputFocusNavigationHost m_navigationHost{nullptr};
|
|
69
69
|
winrt::event_token m_navigationHostDepartFocusRequestedToken{};
|
|
70
70
|
|
|
71
|
+
// Issue #15557: Store ViewChanged subscriptions to parent ScrollViews for transform updates
|
|
72
|
+
struct ViewChangedSubscription {
|
|
73
|
+
winrt::weak_ref<winrt::Microsoft::ReactNative::Composition::ScrollViewComponentView> scrollView;
|
|
74
|
+
winrt::event_token token;
|
|
75
|
+
};
|
|
76
|
+
std::vector<ViewChangedSubscription> m_viewChangedSubscriptions;
|
|
77
|
+
|
|
71
78
|
// Automation
|
|
72
79
|
void ConfigureChildSiteLinkAutomation() noexcept;
|
|
73
80
|
};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
#include "ScrollViewComponentView.h"
|
|
8
8
|
|
|
9
|
+
#include <Fabric/ComponentView.h>
|
|
9
10
|
#include <Utils/ValueUtils.h>
|
|
10
11
|
|
|
11
12
|
#pragma warning(push)
|
|
@@ -19,6 +20,8 @@
|
|
|
19
20
|
#include <AutoDraw.h>
|
|
20
21
|
#include <Fabric/DWriteHelpers.h>
|
|
21
22
|
#include <unicode.h>
|
|
23
|
+
#include <functional>
|
|
24
|
+
#include "ContentIslandComponentView.h"
|
|
22
25
|
#include "JSValueReader.h"
|
|
23
26
|
#include "RootComponentView.h"
|
|
24
27
|
|
|
@@ -884,6 +887,13 @@ void ScrollViewComponentView::updateContentVisualSize() noexcept {
|
|
|
884
887
|
|
|
885
888
|
void ScrollViewComponentView::prepareForRecycle() noexcept {}
|
|
886
889
|
|
|
890
|
+
void ScrollViewComponentView::updateChildrenClippingPath(
|
|
891
|
+
facebook::react::LayoutMetrics const & /*layoutMetrics*/,
|
|
892
|
+
const facebook::react::ViewProps & /*viewProps*/) noexcept {
|
|
893
|
+
// No-op: ScrollView mounts children into m_scrollVisual (not Visual()),
|
|
894
|
+
// and scroll visuals inherently clip their content.
|
|
895
|
+
}
|
|
896
|
+
|
|
887
897
|
/*
|
|
888
898
|
ScrollViewComponentView::ScrollInteractionTrackerOwner::ScrollInteractionTrackerOwner(
|
|
889
899
|
ScrollViewComponentView *outer)
|
|
@@ -1325,6 +1335,10 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
|
|
|
1325
1335
|
m_allowNextScrollNoMatterWhat = false;
|
|
1326
1336
|
}
|
|
1327
1337
|
}
|
|
1338
|
+
|
|
1339
|
+
// Issue #15557: Notify listeners that scroll position has changed,
|
|
1340
|
+
// so ContentIslandComponentView can update LocalToParentTransformMatrix
|
|
1341
|
+
FireViewChanged();
|
|
1328
1342
|
});
|
|
1329
1343
|
|
|
1330
1344
|
m_scrollBeginDragRevoker = m_scrollVisual.ScrollBeginDrag(
|
|
@@ -1332,6 +1346,9 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
|
|
|
1332
1346
|
[this](
|
|
1333
1347
|
winrt::IInspectable const & /*sender*/,
|
|
1334
1348
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
|
|
1349
|
+
// Issue #15557: Notify listeners that scroll position has changed
|
|
1350
|
+
FireViewChanged();
|
|
1351
|
+
|
|
1335
1352
|
m_allowNextScrollNoMatterWhat = true; // Ensure next scroll event is recorded, regardless of throttle
|
|
1336
1353
|
updateStateWithContentOffset();
|
|
1337
1354
|
auto eventEmitter = GetEventEmitter();
|
|
@@ -1478,4 +1495,20 @@ void ScrollViewComponentView::updateShowsVerticalScrollIndicator(bool value) noe
|
|
|
1478
1495
|
void ScrollViewComponentView::updateDecelerationRate(float value) noexcept {
|
|
1479
1496
|
m_scrollVisual.SetDecelerationRate({value, value, value});
|
|
1480
1497
|
}
|
|
1498
|
+
|
|
1499
|
+
// Issue #15557: Notify listeners that scroll position has changed.
|
|
1500
|
+
// ContentIslandComponentView subscribes to this to update LocalToParentTransformMatrix.
|
|
1501
|
+
void ScrollViewComponentView::FireViewChanged() noexcept {
|
|
1502
|
+
m_viewChangedEvent(*this, nullptr);
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
// Issue #15557: Event accessors for ViewChanged
|
|
1506
|
+
winrt::event_token ScrollViewComponentView::ViewChanged(
|
|
1507
|
+
winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable> const &handler) noexcept {
|
|
1508
|
+
return m_viewChangedEvent.add(handler);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
void ScrollViewComponentView::ViewChanged(winrt::event_token const &token) noexcept {
|
|
1512
|
+
m_viewChangedEvent.remove(token);
|
|
1513
|
+
}
|
|
1481
1514
|
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|
|
@@ -118,6 +118,18 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
|
|
|
118
118
|
double getVerticalSize() noexcept;
|
|
119
119
|
double getHorizontalSize() noexcept;
|
|
120
120
|
|
|
121
|
+
// Issue #15557: Event accessors for ViewChanged (used by ContentIslandComponentView for transform update)
|
|
122
|
+
winrt::event_token ViewChanged(
|
|
123
|
+
winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable> const &handler) noexcept;
|
|
124
|
+
void ViewChanged(winrt::event_token const &token) noexcept;
|
|
125
|
+
|
|
126
|
+
protected:
|
|
127
|
+
// ScrollView mounts children into m_scrollVisual (not Visual()), and scroll visuals
|
|
128
|
+
// inherently clip their content, so we skip the children container clipping logic.
|
|
129
|
+
void updateChildrenClippingPath(
|
|
130
|
+
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
131
|
+
const facebook::react::ViewProps &viewProps) noexcept override;
|
|
132
|
+
|
|
121
133
|
private:
|
|
122
134
|
void updateDecelerationRate(float value) noexcept;
|
|
123
135
|
void updateContentVisualSize() noexcept;
|
|
@@ -129,6 +141,8 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
|
|
|
129
141
|
bool scrollRight(float delta, bool animate) noexcept;
|
|
130
142
|
void updateBackgroundColor(const facebook::react::SharedColor &color) noexcept;
|
|
131
143
|
void updateStateWithContentOffset() noexcept;
|
|
144
|
+
// Issue #15557: Notify listeners that scroll position has changed
|
|
145
|
+
void FireViewChanged() noexcept;
|
|
132
146
|
facebook::react::ScrollViewEventEmitter::Metrics getScrollMetrics(
|
|
133
147
|
facebook::react::SharedViewEventEmitter const &eventEmitter,
|
|
134
148
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) noexcept;
|
|
@@ -160,6 +174,9 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
|
|
|
160
174
|
bool m_allowNextScrollNoMatterWhat{false};
|
|
161
175
|
std::chrono::steady_clock::time_point m_lastScrollEventTime{};
|
|
162
176
|
std::shared_ptr<facebook::react::ScrollViewShadowNode::ConcreteState const> m_state;
|
|
177
|
+
|
|
178
|
+
// Issue #15557: Event for notifying listeners when scroll position changes
|
|
179
|
+
winrt::event<winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>> m_viewChangedEvent;
|
|
163
180
|
};
|
|
164
181
|
|
|
165
182
|
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
12
12
|
<PropertyGroup>
|
|
13
|
-
<ReactNativeWindowsVersion>0.82.0-preview.
|
|
13
|
+
<ReactNativeWindowsVersion>0.82.0-preview.11</ReactNativeWindowsVersion>
|
|
14
14
|
<ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
|
|
15
15
|
<ReactNativeWindowsMinor>82</ReactNativeWindowsMinor>
|
|
16
16
|
<ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
|
|
17
17
|
<ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
|
|
18
|
-
<ReactNativeWindowsCommitId>
|
|
18
|
+
<ReactNativeWindowsCommitId>d7ba35e21aee54fe408ad39cd45ad5254334c673</ReactNativeWindowsCommitId>
|
|
19
19
|
</PropertyGroup>
|
|
20
20
|
</Project>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<WinUI3ExperimentalVersion Condition="'$(WinUI3ExperimentalVersion)'==''">2.0.0-experimental3</WinUI3ExperimentalVersion>
|
|
11
11
|
<!-- This value is also used by the CLI, see /packages/@react-native-windows/cli/.../autolinkWindows.ts -->
|
|
12
12
|
<WinUI3Version Condition="'$(WinUI3Version)'=='' AND '$(UseExperimentalWinUI3)'=='true'">$(WinUI3ExperimentalVersion)</WinUI3Version>
|
|
13
|
-
<WinUI3Version Condition="'$(WinUI3Version)'==''">1.8.
|
|
13
|
+
<WinUI3Version Condition="'$(WinUI3Version)'==''">1.8.260209005</WinUI3Version>
|
|
14
14
|
<!-- This is needed to prevent build errors with WinAppSDK >= 1.7 trying to double build WindowsAppRuntimeAutoInitializer.cpp -->
|
|
15
15
|
<WindowsAppSdkAutoInitialize Condition="'$(WindowsAppSdkAutoInitialize)'=='' And $([MSBuild]::VersionGreaterThan('$(WinUI3Version)', '1.7.0'))">false</WindowsAppSdkAutoInitialize>
|
|
16
16
|
</PropertyGroup>
|
|
@@ -20,23 +20,17 @@ try {
|
|
|
20
20
|
$packagesSolutions = (Get-ChildItem -File -Recurse -Path $RepoRoot\packages -Filter *.sln ) | Where-Object { !$_.FullName.Contains('node_modules') -and !$_.FullName.Contains('e2etest') }
|
|
21
21
|
$vnextSolutions = (Get-ChildItem -File -Path $RepoRoot\vnext -Filter *.sln)
|
|
22
22
|
|
|
23
|
-
# Run all solutions
|
|
24
|
-
# (some projects are only configured for specific platforms)
|
|
25
|
-
$platforms = @("x64","x86","ARM64")
|
|
23
|
+
# Run all solutions with their defaults
|
|
26
24
|
$($packagesSolutions; $vnextSolutions) | Foreach-Object {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
& msbuild /t:Restore /p:RestoreForceEvaluate=true /p:Platform=$platform $_.FullName
|
|
30
|
-
}
|
|
25
|
+
Write-Host Restoring $_.FullName with defaults
|
|
26
|
+
& msbuild /t:Restore /p:RestoreForceEvaluate=true $_.FullName
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
# Re-run solutions that build with UseExperimentalWinUI3
|
|
34
30
|
$experimentalSolutions = @("playground-composition.sln", "Microsoft.ReactNative.NewArch.sln", "ReactWindows-Desktop.sln");
|
|
35
31
|
$($packagesSolutions; $vnextSolutions) | Where-Object { $experimentalSolutions -contains $_.Name } | Foreach-Object {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
& msbuild /t:Restore /p:RestoreForceEvaluate=true /p:UseExperimentalWinUI3=true /p:Platform=$platform $_.FullName
|
|
39
|
-
}
|
|
32
|
+
Write-Host Restoring $_.FullName with UseExperimentalWinUI3=true
|
|
33
|
+
& msbuild /t:Restore /p:RestoreForceEvaluate=true /p:UseExperimentalWinUI3=true $_.FullName
|
|
40
34
|
}
|
|
41
35
|
}
|
|
42
36
|
finally {
|