react-native-windows 0.81.21 → 0.81.22
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/Fabric/Composition/CompositionEventHandler.cpp +64 -16
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +11 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +28 -6
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/package.json +1 -1
- package/template/cpp-lib/proj/MyLib.vcxproj +1 -1
- package/templates/cpp-app/windows/MyApp/MyApp.vcxproj +1 -1
- package/templates/cpp-lib/windows/MyLib/MyLib.vcxproj +1 -1
|
@@ -227,6 +227,28 @@ void CompositionEventHandler::Initialize() noexcept {
|
|
|
227
227
|
}
|
|
228
228
|
});
|
|
229
229
|
|
|
230
|
+
// Issue #16047: when ScrollView calls VisualInteractionSource::TryRedirectForManipulation
|
|
231
|
+
// and the OS hands the pointer over to the InteractionTracker, WinAppSDK
|
|
232
|
+
// does not fire PointerCaptureLost on this source — but it does fire
|
|
233
|
+
// PointerRoutedAway. Treat it the same way as captureloss: cancel any
|
|
234
|
+
// active touch RN is tracking for this pointer so Pressables don't get
|
|
235
|
+
// stuck in their pressed state.
|
|
236
|
+
m_pointerRoutedAwayToken =
|
|
237
|
+
pointerSource.PointerRoutedAway([wkThis = weak_from_this()](
|
|
238
|
+
winrt::Microsoft::UI::Input::InputPointerSource const &,
|
|
239
|
+
winrt::Microsoft::UI::Input::PointerEventArgs const &args) {
|
|
240
|
+
if (auto strongThis = wkThis.lock()) {
|
|
241
|
+
if (auto strongRootView = strongThis->m_wkRootView.get()) {
|
|
242
|
+
if (strongThis->SurfaceId() == -1)
|
|
243
|
+
return;
|
|
244
|
+
|
|
245
|
+
auto pp = winrt::make<winrt::Microsoft::ReactNative::Composition::Input::implementation::PointerPoint>(
|
|
246
|
+
args.CurrentPoint(), strongRootView.ScaleFactor());
|
|
247
|
+
strongThis->onPointerRoutedAway(pp, args.KeyModifiers());
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
|
|
230
252
|
m_pointerWheelChangedToken =
|
|
231
253
|
pointerSource.PointerWheelChanged([wkThis = weak_from_this()](
|
|
232
254
|
winrt::Microsoft::UI::Input::InputPointerSource const &,
|
|
@@ -374,6 +396,7 @@ CompositionEventHandler::~CompositionEventHandler() {
|
|
|
374
396
|
pointerSource.PointerReleased(m_pointerReleasedToken);
|
|
375
397
|
pointerSource.PointerMoved(m_pointerMovedToken);
|
|
376
398
|
pointerSource.PointerCaptureLost(m_pointerCaptureLostToken);
|
|
399
|
+
pointerSource.PointerRoutedAway(m_pointerRoutedAwayToken);
|
|
377
400
|
pointerSource.PointerWheelChanged(m_pointerWheelChangedToken);
|
|
378
401
|
pointerSource.PointerExited(m_pointerExitedToken);
|
|
379
402
|
auto keyboardSource = winrt::Microsoft::UI::Input::InputKeyboardSource::GetForIsland(island);
|
|
@@ -1123,24 +1146,49 @@ void CompositionEventHandler::onPointerCaptureLost(
|
|
|
1123
1146
|
m_pointerCapturingComponentTag = -1;
|
|
1124
1147
|
}
|
|
1125
1148
|
|
|
1126
|
-
//
|
|
1127
|
-
// when no JS-level CapturePointer was ever issued.
|
|
1128
|
-
//
|
|
1129
|
-
//
|
|
1130
|
-
//
|
|
1131
|
-
//
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1149
|
+
// Defense-in-depth cleanup for the specific pointer that lost capture, even
|
|
1150
|
+
// when no JS-level CapturePointer was ever issued. The ScrollView
|
|
1151
|
+
// TryRedirectForManipulation path comes in via PointerRoutedAway, not
|
|
1152
|
+
// PointerCaptureLost (see onPointerRoutedAway and issue #16047), so this
|
|
1153
|
+
// path covers the remaining system-driven losses (focus change, another
|
|
1154
|
+
// window stealing input, system back gesture, etc.).
|
|
1155
|
+
CancelActiveTouchForPointerInternal(pointerPoint.PointerId(), pointerPoint, keyModifiers);
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
void CompositionEventHandler::onPointerRoutedAway(
|
|
1159
|
+
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
1160
|
+
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
|
|
1161
|
+
if (SurfaceId() == -1)
|
|
1162
|
+
return;
|
|
1163
|
+
|
|
1164
|
+
// Issue #16047: WinAppSDK fires PointerRoutedAway when the OS hands the
|
|
1165
|
+
// pointer to another InputPointerSource — most importantly for us, when
|
|
1166
|
+
// ScrollView calls VisualInteractionSource::TryRedirectForManipulation and
|
|
1167
|
+
// the InteractionTracker takes the gesture for scrolling. We never get
|
|
1168
|
+
// PointerMoved / PointerReleased / PointerCaptureLost for that pointer
|
|
1169
|
+
// afterwards, so without this cleanup m_activeTouches keeps a zombie entry
|
|
1170
|
+
// and the originally-pressed Pressable stays stuck in its pressed state.
|
|
1171
|
+
CancelActiveTouchForPointerInternal(pointerPoint.PointerId(), pointerPoint, keyModifiers);
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
bool CompositionEventHandler::CancelActiveTouchForPointerInternal(
|
|
1175
|
+
PointerId pointerId,
|
|
1176
|
+
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
1177
|
+
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
|
|
1136
1178
|
auto activeTouch = m_activeTouches.find(pointerId);
|
|
1137
|
-
if (activeTouch
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1179
|
+
if (activeTouch == m_activeTouches.end()) {
|
|
1180
|
+
return false;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
ActiveTouch cancelledTouchCopy = std::move(activeTouch->second);
|
|
1184
|
+
m_activeTouches.erase(activeTouch);
|
|
1185
|
+
|
|
1186
|
+
if (!cancelledTouchCopy.eventEmitter) {
|
|
1187
|
+
return false;
|
|
1143
1188
|
}
|
|
1189
|
+
|
|
1190
|
+
DispatchSynthesizedTouchCancelForActiveTouch(cancelledTouchCopy, pointerPoint, keyModifiers);
|
|
1191
|
+
return true;
|
|
1144
1192
|
}
|
|
1145
1193
|
|
|
1146
1194
|
void CompositionEventHandler::onPointerMoved(
|
|
@@ -66,6 +66,9 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
66
66
|
void onPointerCaptureLost(
|
|
67
67
|
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
68
68
|
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept;
|
|
69
|
+
void onPointerRoutedAway(
|
|
70
|
+
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
71
|
+
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept;
|
|
69
72
|
void onKeyDown(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept;
|
|
70
73
|
void onKeyUp(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept;
|
|
71
74
|
void onCharacterReceived(
|
|
@@ -156,6 +159,13 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
156
159
|
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
157
160
|
winrt::Windows::System::VirtualKeyModifiers keyModifiers);
|
|
158
161
|
|
|
162
|
+
// Look up the active touch for pointerId, erase it, and dispatch cancel events.
|
|
163
|
+
// Returns true iff a touch was found and cancel events were dispatched.
|
|
164
|
+
bool CancelActiveTouchForPointerInternal(
|
|
165
|
+
PointerId pointerId,
|
|
166
|
+
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
167
|
+
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept;
|
|
168
|
+
|
|
159
169
|
std::vector<winrt::Microsoft::ReactNative::ComponentView> GetTouchableViewsInPathToRoot(
|
|
160
170
|
const winrt::Microsoft::ReactNative::ComponentView &componentView);
|
|
161
171
|
|
|
@@ -187,6 +197,7 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
187
197
|
winrt::event_token m_pointerMovedToken;
|
|
188
198
|
winrt::event_token m_pointerWheelChangedToken;
|
|
189
199
|
winrt::event_token m_pointerCaptureLostToken;
|
|
200
|
+
winrt::event_token m_pointerRoutedAwayToken;
|
|
190
201
|
winrt::event_token m_pointerExitedToken;
|
|
191
202
|
winrt::event_token m_keyDownToken;
|
|
192
203
|
winrt::event_token m_keyUpToken;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
#include <functional>
|
|
24
24
|
#include "ContentIslandComponentView.h"
|
|
25
25
|
#include "JSValueReader.h"
|
|
26
|
+
#include "ReactNativeIsland.h"
|
|
26
27
|
#include "RootComponentView.h"
|
|
27
28
|
|
|
28
29
|
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
@@ -849,13 +850,27 @@ void ScrollViewComponentView::updateStateWithContentOffset() noexcept {
|
|
|
849
850
|
return;
|
|
850
851
|
}
|
|
851
852
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
853
|
+
// Issue #16047: m_scrollVisual.ScrollPosition() returns the InteractionTracker
|
|
854
|
+
// position in PHYSICAL pixels (the visual is sized as
|
|
855
|
+
// layoutMetrics.frame.size.* * pointScaleFactor — see updateLayoutMetrics /
|
|
856
|
+
// updateContentVisualSize) but ScrollViewShadowNode state's contentOffset is
|
|
857
|
+
// in DIPs. Without the conversion, JS UIManager.measure() over-subtracts by
|
|
858
|
+
// pointScaleFactor on non-100% display scales, leaving Pressables inside a
|
|
859
|
+
// scrolled ScrollView with stale page-space bounds that don't contain the
|
|
860
|
+
// touch — Pressability fires LEAVE_PRESS_RECT inside pressIn and suppresses
|
|
861
|
+
// press. The JS-event-emitter paths in this file (see lines using
|
|
862
|
+
// args.Position() / pointScaleFactor) already do this division.
|
|
863
|
+
auto rawScrollPosition = m_scrollVisual.ScrollPosition();
|
|
864
|
+
const float pointScaleFactor = m_layoutMetrics.pointScaleFactor > 0.0f ? m_layoutMetrics.pointScaleFactor : 1.0f;
|
|
865
|
+
facebook::react::Point contentOffsetDips{
|
|
866
|
+
rawScrollPosition.x / pointScaleFactor, rawScrollPosition.y / pointScaleFactor};
|
|
867
|
+
|
|
868
|
+
m_verticalScrollbarComponent->ContentOffset(rawScrollPosition);
|
|
869
|
+
m_horizontalScrollbarComponent->ContentOffset(rawScrollPosition);
|
|
870
|
+
|
|
871
|
+
m_state->updateState([contentOffsetDips](const facebook::react::ScrollViewShadowNode::ConcreteState::Data &data) {
|
|
857
872
|
auto newData = data;
|
|
858
|
-
newData.contentOffset =
|
|
873
|
+
newData.contentOffset = contentOffsetDips;
|
|
859
874
|
return std::make_shared<facebook::react::ScrollViewShadowNode::ConcreteState::Data const>(newData);
|
|
860
875
|
});
|
|
861
876
|
}
|
|
@@ -1389,6 +1404,13 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
|
|
|
1389
1404
|
[this](
|
|
1390
1405
|
winrt::IInspectable const & /*sender*/,
|
|
1391
1406
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
|
|
1407
|
+
// Issue #16047: push the FINAL settled scroll position into Fabric's
|
|
1408
|
+
// shadow tree before notifying JS. The per-frame ScrollPositionChanged
|
|
1409
|
+
// updates can drop the last inertia delta, leaving contentOffset stale
|
|
1410
|
+
// and JS UIManager.measure() returning pre-settle-relative bounds.
|
|
1411
|
+
// ScrollEndDrag / ScrollBeginDrag already call this; momentum-end was
|
|
1412
|
+
// the missing completion path.
|
|
1413
|
+
updateStateWithContentOffset();
|
|
1392
1414
|
auto eventEmitter = GetEventEmitter();
|
|
1393
1415
|
if (eventEmitter) {
|
|
1394
1416
|
auto scrollMetrics = getScrollMetrics(eventEmitter, args);
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
12
12
|
<PropertyGroup>
|
|
13
|
-
<ReactNativeWindowsVersion>0.81.
|
|
13
|
+
<ReactNativeWindowsVersion>0.81.22</ReactNativeWindowsVersion>
|
|
14
14
|
<ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
|
|
15
15
|
<ReactNativeWindowsMinor>81</ReactNativeWindowsMinor>
|
|
16
|
-
<ReactNativeWindowsPatch>
|
|
16
|
+
<ReactNativeWindowsPatch>22</ReactNativeWindowsPatch>
|
|
17
17
|
<ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
|
|
18
|
-
<ReactNativeWindowsCommitId>
|
|
18
|
+
<ReactNativeWindowsCommitId>aaa05f5c3491ec4f2d62cb630b7ae51cd6a0f750</ReactNativeWindowsCommitId>
|
|
19
19
|
</PropertyGroup>
|
|
20
20
|
</Project>
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
<ApplicationType>Windows Store</ApplicationType>
|
|
16
16
|
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
|
17
17
|
</PropertyGroup>
|
|
18
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
18
19
|
<PropertyGroup Label="ReactNativeWindowsProps">
|
|
19
20
|
<ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(SolutionDir), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\</ReactNativeWindowsDir>
|
|
20
21
|
</PropertyGroup>
|
|
@@ -23,7 +24,6 @@
|
|
|
23
24
|
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.22621.0</WindowsTargetPlatformVersion>
|
|
24
25
|
<WindowsTargetPlatformMinVersion Condition=" '$(WindowsTargetPlatformMinVersion)' == '' ">10.0.17763.0</WindowsTargetPlatformMinVersion>
|
|
25
26
|
</PropertyGroup>
|
|
26
|
-
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
27
27
|
<ItemGroup Label="ProjectConfigurations">
|
|
28
28
|
<ProjectConfiguration Include="Debug|ARM64">
|
|
29
29
|
<Configuration>Debug</Configuration>
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
<MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
|
|
17
17
|
<AppxPackage>false</AppxPackage>
|
|
18
18
|
</PropertyGroup>
|
|
19
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
19
20
|
<PropertyGroup Label="ReactNativeWindowsProps">
|
|
20
21
|
<ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\</ReactNativeWindowsDir>
|
|
21
22
|
</PropertyGroup>
|
|
22
23
|
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.WindowsSdk.Default.props" />
|
|
23
|
-
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
24
24
|
<ItemGroup Label="ProjectConfigurations">
|
|
25
25
|
<ProjectConfiguration Include="Debug|Win32">
|
|
26
26
|
<Configuration>Debug</Configuration>
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
<MinimumVisualStudioVersion>17.0</MinimumVisualStudioVersion>
|
|
15
15
|
<AppxPackage>false</AppxPackage>
|
|
16
16
|
</PropertyGroup>
|
|
17
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
17
18
|
<PropertyGroup Label="ReactNativeWindowsProps">
|
|
18
19
|
<ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\</ReactNativeWindowsDir>
|
|
19
20
|
<RunAutolinkCheck>false</RunAutolinkCheck>
|
|
20
21
|
</PropertyGroup>
|
|
21
22
|
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.WindowsSdk.Default.props" />
|
|
22
|
-
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
23
23
|
<ItemGroup Label="ProjectConfigurations">
|
|
24
24
|
<ProjectConfiguration Include="Debug|Win32">
|
|
25
25
|
<Configuration>Debug</Configuration>
|