react-native-windows 0.84.0-preview.4 → 0.84.0-preview.6
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/Libraries/Modal/Modal.windows.js +1 -7
- package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +58 -20
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +197 -54
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +12 -3
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +14 -9
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +0 -2
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +98 -44
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +4 -2
- package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +3 -3
- package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.h +3 -1
- package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +0 -1
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -1
- package/Microsoft.ReactNative/Modules/Animated/AnimatedNode.cpp +3 -3
- package/Microsoft.ReactNative/Modules/Animated/AnimatedNode.h +3 -2
- package/Microsoft.ReactNative/Modules/Timing.h +2 -1
- package/PropertySheets/External/Microsoft.ReactNative.Uwp.CSharpApp.targets +1 -1
- package/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.targets +1 -1
- package/PropertySheets/Generated/PackageVersion.g.props +2 -2
- package/PropertySheets/JSEngine.props +2 -1
- package/Scripts/Tfs/Invoke-WebRequestWithRetry.ps1 +40 -0
- package/package.json +2 -2
|
@@ -41,13 +41,7 @@ export type PublicModalInstance = HostInstance;
|
|
|
41
41
|
const ModalEventEmitter =
|
|
42
42
|
(Platform.OS === 'ios' || Platform.OS === 'windows') && // [Windows]
|
|
43
43
|
NativeModalManager != null
|
|
44
|
-
? new NativeEventEmitter<ModalEventDefinitions>(
|
|
45
|
-
// T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
|
|
46
|
-
// If you want to use the native module on other platforms, please remove this condition and test its behavior
|
|
47
|
-
Platform.OS !== 'ios' && Platform.OS !== 'windows' // [Windows]
|
|
48
|
-
? null
|
|
49
|
-
: NativeModalManager,
|
|
50
|
-
)
|
|
44
|
+
? new NativeEventEmitter<ModalEventDefinitions>(NativeModalManager)
|
|
51
45
|
: null;
|
|
52
46
|
|
|
53
47
|
/**
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
#include "pch.h"
|
|
3
3
|
#include "CompositionContextHelper.h"
|
|
4
4
|
#include <algorithm>
|
|
5
|
+
#include <cassert>
|
|
6
|
+
#include <exception>
|
|
7
|
+
#include <vector>
|
|
5
8
|
#if __has_include("Composition.Experimental.SystemCompositionContextHelper.g.cpp")
|
|
6
9
|
#include "Composition.Experimental.SystemCompositionContextHelper.g.cpp"
|
|
7
10
|
#endif
|
|
@@ -431,30 +434,43 @@ struct CompVisualImpl {
|
|
|
431
434
|
void InsertAt(
|
|
432
435
|
const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual,
|
|
433
436
|
uint32_t index) noexcept {
|
|
437
|
+
if (index > m_childrenCache.size()) {
|
|
438
|
+
std::terminate();
|
|
439
|
+
}
|
|
434
440
|
auto containerChildren = InnerVisual().as<typename TTypeRedirects::ContainerVisual>().Children();
|
|
435
441
|
auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
|
|
436
442
|
if (index == 0) {
|
|
437
443
|
containerChildren.InsertAtBottom(compVisual);
|
|
438
|
-
|
|
444
|
+
} else {
|
|
445
|
+
auto insertAfter = containerChildren.First();
|
|
446
|
+
for (uint32_t i = 1; i < index; i++)
|
|
447
|
+
insertAfter.MoveNext();
|
|
448
|
+
containerChildren.InsertAbove(compVisual, insertAfter.Current());
|
|
449
|
+
}
|
|
450
|
+
if (index >= m_childrenCache.size()) {
|
|
451
|
+
m_childrenCache.push_back(visual);
|
|
452
|
+
} else {
|
|
453
|
+
m_childrenCache.insert(m_childrenCache.begin() + index, visual);
|
|
439
454
|
}
|
|
440
|
-
auto insertAfter = containerChildren.First();
|
|
441
|
-
for (uint32_t i = 1; i < index; i++)
|
|
442
|
-
insertAfter.MoveNext();
|
|
443
|
-
containerChildren.InsertAbove(compVisual, insertAfter.Current());
|
|
444
455
|
}
|
|
445
456
|
|
|
446
457
|
void Remove(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept {
|
|
447
458
|
auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
|
|
448
459
|
auto containerChildren = InnerVisual().as<typename TTypeRedirects::ContainerVisual>().Children();
|
|
449
460
|
containerChildren.Remove(compVisual);
|
|
461
|
+
auto it = std::find_if(
|
|
462
|
+
m_childrenCache.begin(), m_childrenCache.end(), [&visual](const auto &cached) { return cached == visual; });
|
|
463
|
+
if (it != m_childrenCache.end()) {
|
|
464
|
+
m_childrenCache.erase(it);
|
|
465
|
+
}
|
|
450
466
|
}
|
|
451
467
|
|
|
452
468
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual GetAt(uint32_t index) noexcept {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
return
|
|
469
|
+
if (index < m_childrenCache.size()) {
|
|
470
|
+
return m_childrenCache[index];
|
|
471
|
+
}
|
|
472
|
+
assert(false && "GetAt called with out-of-range index");
|
|
473
|
+
return nullptr;
|
|
458
474
|
}
|
|
459
475
|
|
|
460
476
|
void SetClippingPath(ID2D1Geometry *clippingPath) noexcept {
|
|
@@ -534,6 +550,7 @@ struct CompVisualImpl {
|
|
|
534
550
|
|
|
535
551
|
protected:
|
|
536
552
|
TVisual m_visual;
|
|
553
|
+
std::vector<winrt::Microsoft::ReactNative::Composition::Experimental::IVisual> m_childrenCache;
|
|
537
554
|
};
|
|
538
555
|
|
|
539
556
|
template <typename TTypeRedirects>
|
|
@@ -848,30 +865,43 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
848
865
|
void InsertAt(
|
|
849
866
|
const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual,
|
|
850
867
|
uint32_t index) noexcept {
|
|
868
|
+
if (index > m_childrenCache.size()) {
|
|
869
|
+
std::terminate();
|
|
870
|
+
}
|
|
851
871
|
auto containerChildren = m_contentVisual.Children();
|
|
852
872
|
auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
|
|
853
873
|
if (index == 0) {
|
|
854
874
|
containerChildren.InsertAtBottom(compVisual);
|
|
855
|
-
|
|
875
|
+
} else {
|
|
876
|
+
auto insertAfter = containerChildren.First();
|
|
877
|
+
for (uint32_t i = 1; i < index; i++)
|
|
878
|
+
insertAfter.MoveNext();
|
|
879
|
+
containerChildren.InsertAbove(compVisual, insertAfter.Current());
|
|
880
|
+
}
|
|
881
|
+
if (index >= m_childrenCache.size()) {
|
|
882
|
+
m_childrenCache.push_back(visual);
|
|
883
|
+
} else {
|
|
884
|
+
m_childrenCache.insert(m_childrenCache.begin() + index, visual);
|
|
856
885
|
}
|
|
857
|
-
auto insertAfter = containerChildren.First();
|
|
858
|
-
for (uint32_t i = 1; i < index; i++)
|
|
859
|
-
insertAfter.MoveNext();
|
|
860
|
-
containerChildren.InsertAbove(compVisual, insertAfter.Current());
|
|
861
886
|
}
|
|
862
887
|
|
|
863
888
|
void Remove(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept {
|
|
864
889
|
auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
|
|
865
890
|
auto containerChildren = m_contentVisual.Children();
|
|
866
891
|
containerChildren.Remove(compVisual);
|
|
892
|
+
auto it = std::find_if(
|
|
893
|
+
m_childrenCache.begin(), m_childrenCache.end(), [&visual](const auto &cached) { return cached == visual; });
|
|
894
|
+
if (it != m_childrenCache.end()) {
|
|
895
|
+
m_childrenCache.erase(it);
|
|
896
|
+
}
|
|
867
897
|
}
|
|
868
898
|
|
|
869
899
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual GetAt(uint32_t index) noexcept {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
return
|
|
900
|
+
if (index < m_childrenCache.size()) {
|
|
901
|
+
return m_childrenCache[index];
|
|
902
|
+
}
|
|
903
|
+
assert(false && "GetAt called with out-of-range index");
|
|
904
|
+
return nullptr;
|
|
875
905
|
}
|
|
876
906
|
|
|
877
907
|
void Brush(const winrt::Microsoft::ReactNative::Composition::Experimental::IBrush &brush) noexcept {
|
|
@@ -1255,6 +1285,12 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
1255
1285
|
std::sort(snapPositions.begin(), snapPositions.end());
|
|
1256
1286
|
snapPositions.erase(std::unique(snapPositions.begin(), snapPositions.end()), snapPositions.end());
|
|
1257
1287
|
|
|
1288
|
+
// Skip reconfiguration if snap points haven't changed
|
|
1289
|
+
if (snapPositions == m_previousSnapPositions) {
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
m_previousSnapPositions = snapPositions;
|
|
1293
|
+
|
|
1258
1294
|
std::vector<typename TTypeRedirects::InteractionTrackerInertiaRestingValue> restingValues;
|
|
1259
1295
|
|
|
1260
1296
|
for (size_t i = 0; i < snapPositions.size(); ++i) {
|
|
@@ -1384,6 +1420,7 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
1384
1420
|
winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment m_snapToAlignment{
|
|
1385
1421
|
winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment::Near};
|
|
1386
1422
|
std::vector<float> m_snapToOffsets;
|
|
1423
|
+
std::vector<float> m_previousSnapPositions;
|
|
1387
1424
|
bool m_inertia{false};
|
|
1388
1425
|
bool m_custom{false};
|
|
1389
1426
|
bool m_interacting{false};
|
|
@@ -1410,6 +1447,7 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
1410
1447
|
typename TTypeRedirects::SpriteVisual m_contentVisual{nullptr};
|
|
1411
1448
|
typename TTypeRedirects::InteractionTracker m_interactionTracker{nullptr};
|
|
1412
1449
|
typename TTypeRedirects::VisualInteractionSource m_visualInteractionSource{nullptr};
|
|
1450
|
+
std::vector<winrt::Microsoft::ReactNative::Composition::Experimental::IVisual> m_childrenCache;
|
|
1413
1451
|
};
|
|
1414
1452
|
using WindowsCompScrollerVisual = CompScrollerVisual<WindowsTypeRedirects>;
|
|
1415
1453
|
using MicrosoftCompScrollerVisual = CompScrollerVisual<MicrosoftTypeRedirects>;
|
|
@@ -250,7 +250,10 @@ void CompositionEventHandler::Initialize() noexcept {
|
|
|
250
250
|
if (strongThis->SurfaceId() == -1)
|
|
251
251
|
return;
|
|
252
252
|
|
|
253
|
-
auto
|
|
253
|
+
auto *rootView = strongThis->RootComponentView();
|
|
254
|
+
if (!rootView)
|
|
255
|
+
return;
|
|
256
|
+
auto focusedComponent = rootView->GetFocusedComponent();
|
|
254
257
|
auto keyboardSource = winrt::make<CompositionInputKeyboardSource>(source);
|
|
255
258
|
auto keyArgs =
|
|
256
259
|
winrt::make<winrt::Microsoft::ReactNative::Composition::Input::implementation::KeyRoutedEventArgs>(
|
|
@@ -276,7 +279,10 @@ void CompositionEventHandler::Initialize() noexcept {
|
|
|
276
279
|
if (strongThis->SurfaceId() == -1)
|
|
277
280
|
return;
|
|
278
281
|
|
|
279
|
-
auto
|
|
282
|
+
auto *rootView = strongThis->RootComponentView();
|
|
283
|
+
if (!rootView)
|
|
284
|
+
return;
|
|
285
|
+
auto focusedComponent = rootView->GetFocusedComponent();
|
|
280
286
|
auto keyboardSource = winrt::make<CompositionInputKeyboardSource>(source);
|
|
281
287
|
auto keyArgs =
|
|
282
288
|
winrt::make<winrt::Microsoft::ReactNative::Composition::Input::implementation::KeyRoutedEventArgs>(
|
|
@@ -303,7 +309,10 @@ void CompositionEventHandler::Initialize() noexcept {
|
|
|
303
309
|
if (strongThis->SurfaceId() == -1)
|
|
304
310
|
return;
|
|
305
311
|
|
|
306
|
-
auto
|
|
312
|
+
auto *rootView = strongThis->RootComponentView();
|
|
313
|
+
if (!rootView)
|
|
314
|
+
return;
|
|
315
|
+
auto focusedComponent = rootView->GetFocusedComponent();
|
|
307
316
|
auto keyboardSource = winrt::make<CompositionInputKeyboardSource>(source);
|
|
308
317
|
auto charArgs = winrt::make<
|
|
309
318
|
winrt::Microsoft::ReactNative::Composition::Input::implementation::CharacterReceivedRoutedEventArgs>(
|
|
@@ -330,7 +339,10 @@ void CompositionEventHandler::Initialize() noexcept {
|
|
|
330
339
|
if (strongThis->SurfaceId() == -1)
|
|
331
340
|
return;
|
|
332
341
|
|
|
333
|
-
auto
|
|
342
|
+
auto *rootView = strongThis->RootComponentView();
|
|
343
|
+
if (!rootView)
|
|
344
|
+
return;
|
|
345
|
+
auto focusedComponent = rootView->GetFocusedComponent();
|
|
334
346
|
if (focusedComponent) {
|
|
335
347
|
auto tag =
|
|
336
348
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)
|
|
@@ -358,6 +370,7 @@ CompositionEventHandler::~CompositionEventHandler() {
|
|
|
358
370
|
pointerSource.PointerMoved(m_pointerMovedToken);
|
|
359
371
|
pointerSource.PointerCaptureLost(m_pointerCaptureLostToken);
|
|
360
372
|
pointerSource.PointerWheelChanged(m_pointerWheelChangedToken);
|
|
373
|
+
pointerSource.PointerExited(m_pointerExitedToken);
|
|
361
374
|
auto keyboardSource = winrt::Microsoft::UI::Input::InputKeyboardSource::GetForIsland(island);
|
|
362
375
|
keyboardSource.KeyDown(m_keyDownToken);
|
|
363
376
|
keyboardSource.KeyUp(m_keyUpToken);
|
|
@@ -380,10 +393,15 @@ facebook::react::SurfaceId CompositionEventHandler::SurfaceId() const noexcept {
|
|
|
380
393
|
return -1;
|
|
381
394
|
}
|
|
382
395
|
|
|
383
|
-
winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView
|
|
396
|
+
winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *
|
|
384
397
|
CompositionEventHandler::RootComponentView() const noexcept {
|
|
385
398
|
auto island = m_wkRootView.get();
|
|
386
|
-
|
|
399
|
+
if (!island) {
|
|
400
|
+
return nullptr;
|
|
401
|
+
}
|
|
402
|
+
return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(island)
|
|
403
|
+
->GetComponentView()
|
|
404
|
+
.get();
|
|
387
405
|
}
|
|
388
406
|
|
|
389
407
|
void CompositionEventHandler::onPointerWheelChanged(
|
|
@@ -398,8 +416,11 @@ void CompositionEventHandler::onPointerWheelChanged(
|
|
|
398
416
|
|
|
399
417
|
// In the case of a sub rootview, we may have a non-zero origin. hitTest takes a pt in the parent coords, so we
|
|
400
418
|
// need to apply the current origin
|
|
401
|
-
|
|
402
|
-
|
|
419
|
+
auto *rootView = RootComponentView();
|
|
420
|
+
if (!rootView)
|
|
421
|
+
return;
|
|
422
|
+
ptScaled += rootView->layoutMetrics().frame.origin;
|
|
423
|
+
auto tag = rootView->hitTest(ptScaled, ptLocal);
|
|
403
424
|
|
|
404
425
|
if (tag == -1)
|
|
405
426
|
return;
|
|
@@ -553,7 +574,10 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
|
|
|
553
574
|
case WM_CHAR:
|
|
554
575
|
case WM_SYSCHAR: {
|
|
555
576
|
if (auto strongRootView = m_wkRootView.get()) {
|
|
556
|
-
auto
|
|
577
|
+
auto *rootView = RootComponentView();
|
|
578
|
+
if (!rootView)
|
|
579
|
+
break;
|
|
580
|
+
auto focusedComponent = rootView->GetFocusedComponent();
|
|
557
581
|
auto keyboardSource = winrt::make<CompositionKeyboardSource>(this);
|
|
558
582
|
auto args = winrt::make<
|
|
559
583
|
winrt::Microsoft::ReactNative::Composition::Input::implementation::CharacterReceivedRoutedEventArgs>(
|
|
@@ -576,7 +600,10 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
|
|
|
576
600
|
case WM_SYSKEYDOWN:
|
|
577
601
|
case WM_SYSKEYUP: {
|
|
578
602
|
if (auto strongRootView = m_wkRootView.get()) {
|
|
579
|
-
auto
|
|
603
|
+
auto *rootView = RootComponentView();
|
|
604
|
+
if (!rootView)
|
|
605
|
+
break;
|
|
606
|
+
auto focusedComponent = rootView->GetFocusedComponent();
|
|
580
607
|
auto keyboardSource = winrt::make<CompositionKeyboardSource>(this);
|
|
581
608
|
auto args = winrt::make<winrt::Microsoft::ReactNative::Composition::Input::implementation::KeyRoutedEventArgs>(
|
|
582
609
|
focusedComponent
|
|
@@ -608,9 +635,12 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
|
|
|
608
635
|
|
|
609
636
|
void CompositionEventHandler::onKeyDown(
|
|
610
637
|
const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
|
|
611
|
-
RootComponentView()
|
|
638
|
+
auto *rootView = RootComponentView();
|
|
639
|
+
if (!rootView)
|
|
640
|
+
return;
|
|
641
|
+
rootView->UseKeyboardForProgrammaticFocus(true);
|
|
612
642
|
|
|
613
|
-
if (auto focusedComponent =
|
|
643
|
+
if (auto focusedComponent = rootView->GetFocusedComponent()) {
|
|
614
644
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)->OnKeyDown(args);
|
|
615
645
|
|
|
616
646
|
if (args.Handled())
|
|
@@ -633,7 +663,7 @@ void CompositionEventHandler::onKeyDown(
|
|
|
633
663
|
}
|
|
634
664
|
|
|
635
665
|
if (!fCtrl && args.Key() == winrt::Windows::System::VirtualKey::Tab) {
|
|
636
|
-
if (
|
|
666
|
+
if (rootView->TryMoveFocus(!fShift, winrt::Microsoft::ReactNative::FocusState::Keyboard)) {
|
|
637
667
|
args.Handled(true);
|
|
638
668
|
}
|
|
639
669
|
|
|
@@ -643,9 +673,12 @@ void CompositionEventHandler::onKeyDown(
|
|
|
643
673
|
|
|
644
674
|
void CompositionEventHandler::onKeyUp(
|
|
645
675
|
const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
|
|
646
|
-
RootComponentView()
|
|
676
|
+
auto *rootView = RootComponentView();
|
|
677
|
+
if (!rootView)
|
|
678
|
+
return;
|
|
679
|
+
rootView->UseKeyboardForProgrammaticFocus(true);
|
|
647
680
|
|
|
648
|
-
if (auto focusedComponent =
|
|
681
|
+
if (auto focusedComponent = rootView->GetFocusedComponent()) {
|
|
649
682
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)->OnKeyUp(args);
|
|
650
683
|
|
|
651
684
|
if (args.Handled())
|
|
@@ -655,7 +688,10 @@ void CompositionEventHandler::onKeyUp(
|
|
|
655
688
|
|
|
656
689
|
void CompositionEventHandler::onCharacterReceived(
|
|
657
690
|
const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs &args) noexcept {
|
|
658
|
-
|
|
691
|
+
auto *rootView = RootComponentView();
|
|
692
|
+
if (!rootView)
|
|
693
|
+
return;
|
|
694
|
+
if (auto focusedComponent = rootView->GetFocusedComponent()) {
|
|
659
695
|
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(focusedComponent)
|
|
660
696
|
->OnCharacterReceived(args);
|
|
661
697
|
|
|
@@ -664,7 +700,7 @@ void CompositionEventHandler::onCharacterReceived(
|
|
|
664
700
|
}
|
|
665
701
|
}
|
|
666
702
|
|
|
667
|
-
std::vector<winrt::Microsoft::ReactNative::ComponentView> GetTouchableViewsInPathToRoot(
|
|
703
|
+
std::vector<winrt::Microsoft::ReactNative::ComponentView> CompositionEventHandler::GetTouchableViewsInPathToRoot(
|
|
668
704
|
const winrt::Microsoft::ReactNative::ComponentView &componentView) {
|
|
669
705
|
std::vector<winrt::Microsoft::ReactNative::ComponentView> results;
|
|
670
706
|
auto view = componentView;
|
|
@@ -674,6 +710,7 @@ std::vector<winrt::Microsoft::ReactNative::ComponentView> GetTouchableViewsInPat
|
|
|
674
710
|
}
|
|
675
711
|
view = view.Parent();
|
|
676
712
|
}
|
|
713
|
+
|
|
677
714
|
return results;
|
|
678
715
|
}
|
|
679
716
|
|
|
@@ -974,8 +1011,8 @@ void CompositionEventHandler::UpdateActiveTouch(
|
|
|
974
1011
|
// activeTouch.touch.isEraser = false;
|
|
975
1012
|
activeTouch.touch.pagePoint.x = ptScaled.x;
|
|
976
1013
|
activeTouch.touch.pagePoint.y = ptScaled.y;
|
|
977
|
-
activeTouch.touch.screenPoint.x =
|
|
978
|
-
activeTouch.touch.screenPoint.y =
|
|
1014
|
+
activeTouch.touch.screenPoint.x = ptScaled.x;
|
|
1015
|
+
activeTouch.touch.screenPoint.y = ptScaled.y;
|
|
979
1016
|
activeTouch.touch.offsetPoint.x = ptLocal.x;
|
|
980
1017
|
activeTouch.touch.offsetPoint.y = ptLocal.y;
|
|
981
1018
|
activeTouch.touch.timestamp = static_cast<facebook::react::Float>(
|
|
@@ -1028,9 +1065,12 @@ void CompositionEventHandler::getTargetPointerArgs(
|
|
|
1028
1065
|
|
|
1029
1066
|
// In the case of a sub rootview, we may have a non-zero origin. hitTest takes a pt in the parent coords, so we need
|
|
1030
1067
|
// to apply the current origin
|
|
1031
|
-
|
|
1068
|
+
auto *rootView = RootComponentView();
|
|
1069
|
+
if (!rootView)
|
|
1070
|
+
return;
|
|
1071
|
+
ptScaled += rootView->layoutMetrics().frame.origin;
|
|
1032
1072
|
|
|
1033
|
-
if (
|
|
1073
|
+
if (m_capturedPointers.count(pointerId)) {
|
|
1034
1074
|
assert(m_pointerCapturingComponentTag != -1);
|
|
1035
1075
|
tag = m_pointerCapturingComponentTag;
|
|
1036
1076
|
|
|
@@ -1042,7 +1082,7 @@ void CompositionEventHandler::getTargetPointerArgs(
|
|
|
1042
1082
|
ptLocal.y = ptScaled.y - (clientRect.top / strongRootView.ScaleFactor());
|
|
1043
1083
|
}
|
|
1044
1084
|
} else {
|
|
1045
|
-
tag =
|
|
1085
|
+
tag = rootView->hitTest(ptScaled, ptLocal);
|
|
1046
1086
|
}
|
|
1047
1087
|
}
|
|
1048
1088
|
|
|
@@ -1054,7 +1094,7 @@ void CompositionEventHandler::onPointerCaptureLost(
|
|
|
1054
1094
|
|
|
1055
1095
|
if (m_pointerCapturingComponentTag) {
|
|
1056
1096
|
// copy array to avoid iterator being invalidated during deletion
|
|
1057
|
-
std::
|
|
1097
|
+
std::unordered_set<PointerId> capturedPointers = m_capturedPointers;
|
|
1058
1098
|
|
|
1059
1099
|
for (auto pointerId : capturedPointers) {
|
|
1060
1100
|
releasePointerCapture(pointerId, m_pointerCapturingComponentTag);
|
|
@@ -1101,10 +1141,11 @@ void CompositionEventHandler::onPointerMoved(
|
|
|
1101
1141
|
|
|
1102
1142
|
auto handler = [&, targetView, pointerEvent, isActiveTouch](
|
|
1103
1143
|
std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {
|
|
1144
|
+
auto *rootViewForEmitter = RootComponentView();
|
|
1104
1145
|
const auto eventEmitter = targetView
|
|
1105
1146
|
? winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(targetView)
|
|
1106
1147
|
->eventEmitterAtPoint(pointerEvent.offsetPoint)
|
|
1107
|
-
:
|
|
1148
|
+
: (rootViewForEmitter ? rootViewForEmitter->eventEmitterAtPoint(pointerEvent.offsetPoint) : nullptr);
|
|
1108
1149
|
|
|
1109
1150
|
if (eventEmitter != nullptr) {
|
|
1110
1151
|
eventEmitter->onPointerMove(pointerEvent);
|
|
@@ -1130,7 +1171,10 @@ void CompositionEventHandler::ClearAllHoveredForPointer(const facebook::react::P
|
|
|
1130
1171
|
// events. If we get null for the targetView, that means that the mouse is no over any components, so we have no
|
|
1131
1172
|
// element to send the move event to. However we need to send something so that any previously hovered elements
|
|
1132
1173
|
// are no longer hovered.
|
|
1133
|
-
auto
|
|
1174
|
+
auto *rootView = RootComponentView();
|
|
1175
|
+
if (!rootView)
|
|
1176
|
+
return;
|
|
1177
|
+
auto children = rootView->Children();
|
|
1134
1178
|
if (auto size = children.Size()) {
|
|
1135
1179
|
auto firstChild = children.GetAt(0);
|
|
1136
1180
|
if (auto childEventEmitter =
|
|
@@ -1175,23 +1219,31 @@ void CompositionEventHandler::onPointerPressed(
|
|
|
1175
1219
|
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
|
|
1176
1220
|
namespace Composition = winrt::Microsoft::ReactNative::Composition;
|
|
1177
1221
|
|
|
1178
|
-
RootComponentView()
|
|
1222
|
+
auto *rootView = RootComponentView();
|
|
1223
|
+
if (!rootView)
|
|
1224
|
+
return;
|
|
1225
|
+
rootView->UseKeyboardForProgrammaticFocus(false);
|
|
1179
1226
|
|
|
1180
1227
|
// Clears any active text selection when left pointer is pressed
|
|
1181
1228
|
if (pointerPoint.Properties().PointerUpdateKind() != Composition::Input::PointerUpdateKind::RightButtonPressed) {
|
|
1182
|
-
|
|
1229
|
+
rootView->ClearCurrentTextSelection();
|
|
1183
1230
|
}
|
|
1184
1231
|
|
|
1185
1232
|
PointerId pointerId = pointerPoint.PointerId();
|
|
1186
1233
|
|
|
1187
|
-
auto staleTouch =
|
|
1188
|
-
return pair.second.touch.identifier == pointerId;
|
|
1189
|
-
});
|
|
1234
|
+
auto staleTouch = m_activeTouches.find(pointerId);
|
|
1190
1235
|
|
|
1191
1236
|
if (staleTouch != m_activeTouches.end()) {
|
|
1192
|
-
// A pointer with this ID
|
|
1193
|
-
//
|
|
1194
|
-
|
|
1237
|
+
// A previous pointer with this ID was never properly released (e.g., app lost focus,
|
|
1238
|
+
// pointer left window). Cancel the stale touch and clean it up so the new press can proceed.
|
|
1239
|
+
// Copy and erase before dispatching to avoid holding a reference into m_activeTouches
|
|
1240
|
+
// across DispatchSynthesizedTouchCancelForActiveTouch, which calls HandleIncomingPointerEvent
|
|
1241
|
+
// and iterates m_activeTouches internally.
|
|
1242
|
+
ActiveTouch staleTouchCopy = std::move(staleTouch->second);
|
|
1243
|
+
m_activeTouches.erase(staleTouch);
|
|
1244
|
+
if (staleTouchCopy.eventEmitter) {
|
|
1245
|
+
DispatchSynthesizedTouchCancelForActiveTouch(staleTouchCopy, pointerPoint, keyModifiers);
|
|
1246
|
+
}
|
|
1195
1247
|
}
|
|
1196
1248
|
|
|
1197
1249
|
const auto eventType = TouchEventType::Start;
|
|
@@ -1212,7 +1264,18 @@ void CompositionEventHandler::onPointerPressed(
|
|
|
1212
1264
|
->OnPointerPressed(args);
|
|
1213
1265
|
|
|
1214
1266
|
ActiveTouch activeTouch{0};
|
|
1215
|
-
|
|
1267
|
+
switch (pointerPoint.PointerDeviceType()) {
|
|
1268
|
+
case Composition::Input::PointerDeviceType::Touch:
|
|
1269
|
+
activeTouch.touchType = UITouchType::Touch;
|
|
1270
|
+
break;
|
|
1271
|
+
case Composition::Input::PointerDeviceType::Pen:
|
|
1272
|
+
activeTouch.touchType = UITouchType::Pen;
|
|
1273
|
+
break;
|
|
1274
|
+
case Composition::Input::PointerDeviceType::Mouse:
|
|
1275
|
+
default:
|
|
1276
|
+
activeTouch.touchType = UITouchType::Mouse;
|
|
1277
|
+
break;
|
|
1278
|
+
}
|
|
1216
1279
|
|
|
1217
1280
|
// Map PointerUpdateKind to W3C button value
|
|
1218
1281
|
// https://developer.mozilla.org/docs/Web/API/MouseEvent/button
|
|
@@ -1250,6 +1313,12 @@ void CompositionEventHandler::onPointerPressed(
|
|
|
1250
1313
|
targetComponentView = targetComponentView.Parent();
|
|
1251
1314
|
}
|
|
1252
1315
|
|
|
1316
|
+
// Don't register the touch if no eventEmitter was found — inserting a null-emitter entry
|
|
1317
|
+
// into m_activeTouches would block future presses with the same pointer ID.
|
|
1318
|
+
if (!activeTouch.eventEmitter) {
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1253
1322
|
UpdateActiveTouch(activeTouch, ptScaled, ptLocal);
|
|
1254
1323
|
|
|
1255
1324
|
activeTouch.isPrimary = pointerId == 1;
|
|
@@ -1273,11 +1342,12 @@ void CompositionEventHandler::onPointerReleased(
|
|
|
1273
1342
|
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
|
|
1274
1343
|
int pointerId = pointerPoint.PointerId();
|
|
1275
1344
|
|
|
1276
|
-
RootComponentView()
|
|
1345
|
+
auto *rootView = RootComponentView();
|
|
1346
|
+
if (!rootView)
|
|
1347
|
+
return;
|
|
1348
|
+
rootView->UseKeyboardForProgrammaticFocus(false);
|
|
1277
1349
|
|
|
1278
|
-
auto activeTouch =
|
|
1279
|
-
return pair.second.touch.identifier == pointerId;
|
|
1280
|
-
});
|
|
1350
|
+
auto activeTouch = m_activeTouches.find(pointerId);
|
|
1281
1351
|
|
|
1282
1352
|
if (activeTouch == m_activeTouches.end()) {
|
|
1283
1353
|
return;
|
|
@@ -1289,8 +1359,13 @@ void CompositionEventHandler::onPointerReleased(
|
|
|
1289
1359
|
facebook::react::Point ptLocal, ptScaled;
|
|
1290
1360
|
getTargetPointerArgs(fabricuiManager, pointerPoint, tag, ptScaled, ptLocal);
|
|
1291
1361
|
|
|
1292
|
-
if (tag == -1)
|
|
1362
|
+
if (tag == -1) {
|
|
1363
|
+
if (activeTouch->second.eventEmitter) {
|
|
1364
|
+
DispatchSynthesizedTouchCancelForActiveTouch(activeTouch->second, pointerPoint, keyModifiers);
|
|
1365
|
+
}
|
|
1366
|
+
m_activeTouches.erase(pointerId);
|
|
1293
1367
|
return;
|
|
1368
|
+
}
|
|
1294
1369
|
|
|
1295
1370
|
auto targetComponentView = fabricuiManager->GetViewRegistry().componentViewDescriptorWithTag(tag).view;
|
|
1296
1371
|
auto args = winrt::make<winrt::Microsoft::ReactNative::Composition::Input::implementation::PointerRoutedEventArgs>(
|
|
@@ -1322,7 +1397,7 @@ bool CompositionEventHandler::CapturePointer(
|
|
|
1322
1397
|
}
|
|
1323
1398
|
|
|
1324
1399
|
m_pointerCapturingComponentTag = tag;
|
|
1325
|
-
m_capturedPointers.
|
|
1400
|
+
m_capturedPointers.insert(pointer.PointerId());
|
|
1326
1401
|
return true;
|
|
1327
1402
|
}
|
|
1328
1403
|
|
|
@@ -1337,11 +1412,9 @@ bool CompositionEventHandler::releasePointerCapture(PointerId pointerId, faceboo
|
|
|
1337
1412
|
bool result = false;
|
|
1338
1413
|
|
|
1339
1414
|
if (m_pointerCapturingComponentTag == tag) {
|
|
1340
|
-
|
|
1341
|
-
if (it == m_capturedPointers.end()) {
|
|
1415
|
+
if (m_capturedPointers.erase(pointerId) == 0) {
|
|
1342
1416
|
return false;
|
|
1343
1417
|
}
|
|
1344
|
-
m_capturedPointers.erase(it);
|
|
1345
1418
|
|
|
1346
1419
|
if (std::shared_ptr<FabricUIManager> fabricuiManager =
|
|
1347
1420
|
::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties())) {
|
|
@@ -1352,7 +1425,7 @@ bool CompositionEventHandler::releasePointerCapture(PointerId pointerId, faceboo
|
|
|
1352
1425
|
->OnPointerCaptureLost();
|
|
1353
1426
|
}
|
|
1354
1427
|
|
|
1355
|
-
if (m_capturedPointers.
|
|
1428
|
+
if (m_capturedPointers.empty()) {
|
|
1356
1429
|
m_pointerCapturingComponentTag = -1;
|
|
1357
1430
|
return true;
|
|
1358
1431
|
}
|
|
@@ -1467,16 +1540,83 @@ bool CompositionEventHandler::IsPointerWithinInitialTree(const ActiveTouch &acti
|
|
|
1467
1540
|
if (!initialComponentView)
|
|
1468
1541
|
return false;
|
|
1469
1542
|
|
|
1470
|
-
auto
|
|
1543
|
+
auto *rootView = RootComponentView();
|
|
1544
|
+
if (!rootView)
|
|
1545
|
+
return false;
|
|
1546
|
+
|
|
1547
|
+
facebook::react::Point ptLocal;
|
|
1548
|
+
auto currentTag = rootView->hitTest(activeTouch.touch.pagePoint, ptLocal);
|
|
1549
|
+
if (currentTag == -1)
|
|
1550
|
+
return false;
|
|
1471
1551
|
|
|
1472
|
-
|
|
1473
|
-
|
|
1552
|
+
auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(m_context.Properties());
|
|
1553
|
+
if (!fabricuiManager)
|
|
1554
|
+
return false;
|
|
1555
|
+
|
|
1556
|
+
auto initialTag = initialComponentView.Tag();
|
|
1557
|
+
auto &viewRegistry = fabricuiManager->GetViewRegistry();
|
|
1558
|
+
auto currentView = viewRegistry.componentViewDescriptorWithTag(currentTag).view;
|
|
1559
|
+
while (currentView) {
|
|
1560
|
+
if (currentView.Tag() == initialTag)
|
|
1561
|
+
return true;
|
|
1562
|
+
currentView = currentView.Parent();
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
// Fallback: if the pointer drifted spatially but the original target
|
|
1566
|
+
// is still structurally within the initial tree, honor the tap.
|
|
1567
|
+
// This provides touch-device tolerance for finger drift.
|
|
1568
|
+
auto targetView = viewRegistry.componentViewDescriptorWithTag(activeTouch.touch.target).view;
|
|
1569
|
+
while (targetView) {
|
|
1570
|
+
if (targetView.Tag() == initialTag)
|
|
1474
1571
|
return true;
|
|
1572
|
+
targetView = targetView.Parent();
|
|
1475
1573
|
}
|
|
1476
1574
|
|
|
1477
1575
|
return false;
|
|
1478
1576
|
}
|
|
1479
1577
|
|
|
1578
|
+
void CompositionEventHandler::DispatchSynthesizedTouchCancelForActiveTouch(
|
|
1579
|
+
const ActiveTouch &cancelledTouch,
|
|
1580
|
+
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
1581
|
+
winrt::Windows::System::VirtualKeyModifiers keyModifiers) {
|
|
1582
|
+
if (!cancelledTouch.eventEmitter) {
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
facebook::react::PointerEvent pointerEvent =
|
|
1587
|
+
CreatePointerEventFromActiveTouch(cancelledTouch, TouchEventType::Cancel);
|
|
1588
|
+
winrt::Microsoft::ReactNative::ComponentView targetView{nullptr};
|
|
1589
|
+
facebook::react::SharedTouchEventEmitter emitter = cancelledTouch.eventEmitter;
|
|
1590
|
+
auto pointerHandler = [emitter, pointerEvent](std::vector<winrt::Microsoft::ReactNative::ComponentView> &) {
|
|
1591
|
+
emitter->onPointerCancel(pointerEvent);
|
|
1592
|
+
};
|
|
1593
|
+
HandleIncomingPointerEvent(pointerEvent, targetView, pointerPoint, keyModifiers, pointerHandler);
|
|
1594
|
+
|
|
1595
|
+
facebook::react::TouchEvent touchEvent;
|
|
1596
|
+
touchEvent.changedTouches.insert(cancelledTouch.touch);
|
|
1597
|
+
|
|
1598
|
+
for (const auto &pair : m_activeTouches) {
|
|
1599
|
+
if (!pair.second.eventEmitter) {
|
|
1600
|
+
continue;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
if (touchEvent.changedTouches.find(pair.second.touch) != touchEvent.changedTouches.end()) {
|
|
1604
|
+
continue;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
touchEvent.touches.insert(pair.second.touch);
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
for (const auto &pair : m_activeTouches) {
|
|
1611
|
+
if (pair.second.eventEmitter == cancelledTouch.eventEmitter &&
|
|
1612
|
+
touchEvent.changedTouches.find(pair.second.touch) == touchEvent.changedTouches.end()) {
|
|
1613
|
+
touchEvent.targetTouches.insert(pair.second.touch);
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
cancelledTouch.eventEmitter->onTouchCancel(touchEvent);
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1480
1620
|
// If we have events that include multiple pointer updates, we should change arg from pointerId to vector<pointerId>
|
|
1481
1621
|
void CompositionEventHandler::DispatchTouchEvent(
|
|
1482
1622
|
TouchEventType eventType,
|
|
@@ -1512,16 +1652,19 @@ void CompositionEventHandler::DispatchTouchEvent(
|
|
|
1512
1652
|
bool shouldLeave = (eventType == TouchEventType::End && activeTouch.shouldLeaveWhenReleased) ||
|
|
1513
1653
|
eventType == TouchEventType::Cancel;
|
|
1514
1654
|
if (!shouldLeave) {
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
auto
|
|
1520
|
-
|
|
1655
|
+
auto *rootViewForHit = RootComponentView();
|
|
1656
|
+
if (rootViewForHit) {
|
|
1657
|
+
const auto &viewRegistry = fabricuiManager->GetViewRegistry();
|
|
1658
|
+
facebook::react::Point ptLocal;
|
|
1659
|
+
auto targetTag = rootViewForHit->hitTest(pointerEvent.clientPoint, ptLocal);
|
|
1660
|
+
if (targetTag != -1) {
|
|
1661
|
+
auto targetComponentViewDescriptor = viewRegistry.componentViewDescriptorWithTag(targetTag);
|
|
1662
|
+
targetView = FindClosestFabricManagedTouchableView(targetComponentViewDescriptor.view);
|
|
1663
|
+
}
|
|
1521
1664
|
}
|
|
1522
1665
|
}
|
|
1523
1666
|
|
|
1524
|
-
auto handler = [&activeTouch, eventType, &pointerEvent](
|
|
1667
|
+
auto handler = [this, &activeTouch, eventType, &pointerEvent](
|
|
1525
1668
|
std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {
|
|
1526
1669
|
switch (eventType) {
|
|
1527
1670
|
case TouchEventType::Start:
|