react-native-windows 0.84.0-preview.5 → 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/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/Generated/PackageVersion.g.props +2 -2
- package/package.json +1 -1
|
@@ -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:
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#include <winrt/Windows.Devices.Input.h>
|
|
15
15
|
#include <optional>
|
|
16
16
|
#include <set>
|
|
17
|
+
#include <unordered_set>
|
|
17
18
|
|
|
18
19
|
namespace winrt {
|
|
19
20
|
using namespace Windows::UI;
|
|
@@ -79,7 +80,7 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
79
80
|
bool releasePointerCapture(PointerId pointerId, facebook::react::Tag tag) noexcept;
|
|
80
81
|
|
|
81
82
|
facebook::react::SurfaceId SurfaceId() const noexcept;
|
|
82
|
-
winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView
|
|
83
|
+
winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *RootComponentView() const noexcept;
|
|
83
84
|
|
|
84
85
|
enum class UITouchType {
|
|
85
86
|
Mouse,
|
|
@@ -141,7 +142,7 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
141
142
|
ReactTaggedView initialComponentView{nullptr};
|
|
142
143
|
};
|
|
143
144
|
|
|
144
|
-
|
|
145
|
+
bool IsPointerWithinInitialTree(const ActiveTouch &activeTouch) noexcept;
|
|
145
146
|
static bool IsEndishEventType(TouchEventType eventType) noexcept;
|
|
146
147
|
static const char *PointerTypeCStringFromUITouchType(UITouchType type) noexcept;
|
|
147
148
|
static facebook::react::PointerEvent CreatePointerEventFromActiveTouch(
|
|
@@ -150,6 +151,14 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
150
151
|
static void
|
|
151
152
|
UpdateActiveTouch(ActiveTouch &activeTouch, facebook::react::Point ptScaled, facebook::react::Point ptLocal) noexcept;
|
|
152
153
|
|
|
154
|
+
void DispatchSynthesizedTouchCancelForActiveTouch(
|
|
155
|
+
const ActiveTouch &cancelledTouch,
|
|
156
|
+
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
|
|
157
|
+
winrt::Windows::System::VirtualKeyModifiers keyModifiers);
|
|
158
|
+
|
|
159
|
+
std::vector<winrt::Microsoft::ReactNative::ComponentView> GetTouchableViewsInPathToRoot(
|
|
160
|
+
const winrt::Microsoft::ReactNative::ComponentView &componentView);
|
|
161
|
+
|
|
153
162
|
void UpdateCursor() noexcept;
|
|
154
163
|
void SetCursor(facebook::react::Cursor cursor, HCURSOR hcur) noexcept;
|
|
155
164
|
|
|
@@ -161,7 +170,7 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
161
170
|
winrt::Microsoft::ReactNative::ReactContext m_context;
|
|
162
171
|
|
|
163
172
|
facebook::react::Tag m_pointerCapturingComponentTag{-1}; // Component that has captured input
|
|
164
|
-
std::
|
|
173
|
+
std::unordered_set<PointerId> m_capturedPointers;
|
|
165
174
|
HCURSOR m_hcursor{nullptr};
|
|
166
175
|
bool m_hcursorOwned{false}; // If we create the cursor, so we need to destroy it
|
|
167
176
|
facebook::react::Cursor m_currentCursor{facebook::react::Cursor::Auto};
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
#include "CompositionViewComponentView.h"
|
|
8
8
|
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
9
11
|
#include <AutoDraw.h>
|
|
10
12
|
#include <Fabric/AbiState.h>
|
|
11
13
|
#include <Fabric/AbiViewProps.h>
|
|
@@ -1013,15 +1015,18 @@ bool ComponentView::anyHitTestHelper(
|
|
|
1013
1015
|
facebook::react::Tag &targetTag,
|
|
1014
1016
|
facebook::react::Point &ptContent,
|
|
1015
1017
|
facebook::react::Point &localPt) const noexcept {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1018
|
+
auto size = m_children.Size();
|
|
1019
|
+
if (size == 0) {
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
// m_children is backed by single_threaded_vector (std::vector), so GetAt is O(1)
|
|
1024
|
+
for (uint32_t i = size; i > 0; --i) {
|
|
1025
|
+
targetTag = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_children.GetAt(i - 1))
|
|
1026
|
+
->hitTest(ptContent, localPt);
|
|
1027
|
+
if (targetTag != -1) {
|
|
1028
|
+
return true;
|
|
1029
|
+
}
|
|
1025
1030
|
}
|
|
1026
1031
|
|
|
1027
1032
|
return false;
|
package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
#include <winrt/Microsoft.UI.Input.h>
|
|
19
19
|
#include <winrt/Windows.System.h>
|
|
20
20
|
#include <winrt/Windows.UI.h>
|
|
21
|
+
#include <mutex>
|
|
21
22
|
#include "../Composition.Input.h"
|
|
22
23
|
#include "../CompositionHelpers.h"
|
|
23
24
|
#include "../RootComponentView.h"
|
|
@@ -75,37 +76,38 @@ WindowsTextInputComponentView::DrawBlock::~DrawBlock() {
|
|
|
75
76
|
|
|
76
77
|
// Msftedit.dll vs "Riched20.dll"?
|
|
77
78
|
|
|
79
|
+
static std::once_flag g_richEditLoadedFlag;
|
|
78
80
|
static HINSTANCE g_hInstRichEdit = nullptr;
|
|
79
81
|
static PCreateTextServices g_pfnCreateTextServices;
|
|
80
82
|
|
|
81
83
|
HRESULT HrEnsureRichEd20Loaded() noexcept {
|
|
82
|
-
|
|
84
|
+
HRESULT hr = S_OK;
|
|
85
|
+
std::call_once(g_richEditLoadedFlag, [&hr]() {
|
|
83
86
|
g_hInstRichEdit = LoadLibrary(L"Msftedit.dll");
|
|
84
|
-
if (!g_hInstRichEdit)
|
|
85
|
-
|
|
87
|
+
if (!g_hInstRichEdit) {
|
|
88
|
+
hr = E_FAIL;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
86
91
|
|
|
87
92
|
// Create the windowless control (text services object)
|
|
88
93
|
g_pfnCreateTextServices = (PCreateTextServices)GetProcAddress(g_hInstRichEdit, "CreateTextServices");
|
|
89
|
-
if (!g_pfnCreateTextServices)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
pfnRegister();
|
|
98
|
-
return S_OK;
|
|
99
|
-
} else
|
|
100
|
-
return E_FAIL;
|
|
101
|
-
*/
|
|
102
|
-
}
|
|
103
|
-
return NOERROR;
|
|
94
|
+
if (!g_pfnCreateTextServices) {
|
|
95
|
+
hr = E_FAIL;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
if (!g_hInstRichEdit || !g_pfnCreateTextServices)
|
|
100
|
+
return E_FAIL;
|
|
101
|
+
return hr;
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
107
105
|
CompTextHost(WindowsTextInputComponentView *outer) : m_outer(outer) {}
|
|
108
106
|
|
|
107
|
+
void Detach() {
|
|
108
|
+
m_outer = nullptr;
|
|
109
|
+
}
|
|
110
|
+
|
|
109
111
|
//@cmember Get the DC for the host
|
|
110
112
|
HDC TxGetDC() override {
|
|
111
113
|
assert(false);
|
|
@@ -144,6 +146,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
144
146
|
|
|
145
147
|
//@cmember InvalidateRect
|
|
146
148
|
void TxInvalidateRect(LPCRECT prc, BOOL fMode) override {
|
|
149
|
+
if (!m_outer)
|
|
150
|
+
return;
|
|
147
151
|
if (m_outer->m_drawing)
|
|
148
152
|
return;
|
|
149
153
|
m_outer->DrawText();
|
|
@@ -151,6 +155,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
151
155
|
|
|
152
156
|
//@cmember Send a WM_PAINT to the window
|
|
153
157
|
void TxViewChange(BOOL fUpdate) override {
|
|
158
|
+
if (!m_outer)
|
|
159
|
+
return;
|
|
154
160
|
// When keyboard scrolling without scrollbar, TxInvalidateRect is not called.
|
|
155
161
|
// Instead TxViewChange is called with fUpdate = true
|
|
156
162
|
// if (fUpdate && !OnInnerViewerExtentChanged())
|
|
@@ -163,12 +169,16 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
163
169
|
|
|
164
170
|
//@cmember Create the caret
|
|
165
171
|
BOOL TxCreateCaret(HBITMAP hbmp, INT xWidth, INT yHeight) override {
|
|
172
|
+
if (!m_outer)
|
|
173
|
+
return false;
|
|
166
174
|
m_outer->m_caretVisual.Size({static_cast<float>(xWidth), static_cast<float>(yHeight)});
|
|
167
175
|
return true;
|
|
168
176
|
}
|
|
169
177
|
|
|
170
178
|
//@cmember Show the caret
|
|
171
179
|
BOOL TxShowCaret(BOOL fShow) override {
|
|
180
|
+
if (!m_outer)
|
|
181
|
+
return false;
|
|
172
182
|
// Only show the caret if we have focus
|
|
173
183
|
if (fShow && !m_outer->m_hasFocus) {
|
|
174
184
|
return false;
|
|
@@ -179,6 +189,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
179
189
|
|
|
180
190
|
//@cmember Set the caret position
|
|
181
191
|
BOOL TxSetCaretPos(INT x, INT y) override {
|
|
192
|
+
if (!m_outer)
|
|
193
|
+
return false;
|
|
182
194
|
if (x < 0 && y < 0) {
|
|
183
195
|
// RichEdit sends (-32000,-32000) when the caret is not currently visible.
|
|
184
196
|
return false;
|
|
@@ -217,6 +229,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
217
229
|
|
|
218
230
|
//@cmember Get mouse capture
|
|
219
231
|
void TxSetCapture(BOOL fCapture) override {
|
|
232
|
+
if (!m_outer)
|
|
233
|
+
return;
|
|
220
234
|
auto mousePointer = winrt::make<winrt::Microsoft::ReactNative::Composition::Input::implementation::Pointer>(
|
|
221
235
|
winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse, 1 /* 1 is Mouse PointerId*/);
|
|
222
236
|
|
|
@@ -229,6 +243,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
229
243
|
|
|
230
244
|
//@cmember Set the focus to the text window
|
|
231
245
|
void TxSetFocus() override {
|
|
246
|
+
if (!m_outer)
|
|
247
|
+
return;
|
|
232
248
|
winrt::Microsoft::ReactNative::ComponentView view{nullptr};
|
|
233
249
|
winrt::check_hresult(
|
|
234
250
|
m_outer->QueryInterface(winrt::guid_of<winrt::Microsoft::ReactNative::ComponentView>(), winrt::put_abi(view)));
|
|
@@ -242,11 +258,15 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
242
258
|
|
|
243
259
|
//@cmember Establish a new cursor shape
|
|
244
260
|
void TxSetCursor(HCURSOR hcur, BOOL fText) override {
|
|
261
|
+
if (!m_outer)
|
|
262
|
+
return;
|
|
245
263
|
m_outer->m_hcursor = hcur;
|
|
246
264
|
}
|
|
247
265
|
|
|
248
266
|
//@cmember Converts screen coordinates of a specified point to the client coordinates
|
|
249
267
|
BOOL TxScreenToClient(LPPOINT lppt) override {
|
|
268
|
+
if (!m_outer)
|
|
269
|
+
return false;
|
|
250
270
|
winrt::Windows::Foundation::Point pt{static_cast<float>(lppt->x), static_cast<float>(lppt->y)};
|
|
251
271
|
pt.X -= m_outer->m_contentOffsetPx.x;
|
|
252
272
|
pt.Y -= m_outer->m_contentOffsetPx.y;
|
|
@@ -258,6 +278,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
258
278
|
|
|
259
279
|
//@cmember Converts the client coordinates of a specified point to screen coordinates
|
|
260
280
|
BOOL TxClientToScreen(LPPOINT lppt) override {
|
|
281
|
+
if (!m_outer)
|
|
282
|
+
return false;
|
|
261
283
|
winrt::Windows::Foundation::Point pt{static_cast<float>(lppt->x), static_cast<float>(lppt->y)};
|
|
262
284
|
|
|
263
285
|
if (!m_outer->m_parent) {
|
|
@@ -284,6 +306,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
284
306
|
|
|
285
307
|
//@cmember Retrieves the coordinates of a window's client area
|
|
286
308
|
HRESULT TxGetClientRect(LPRECT prc) override {
|
|
309
|
+
if (!m_outer)
|
|
310
|
+
return E_FAIL;
|
|
287
311
|
*prc = m_outer->getClientRect();
|
|
288
312
|
|
|
289
313
|
prc->top += m_outer->m_contentOffsetPx.y;
|
|
@@ -310,6 +334,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
310
334
|
|
|
311
335
|
//@cmember Get the default character format for the text
|
|
312
336
|
HRESULT TxGetCharFormat(const CHARFORMATW **ppCF) override {
|
|
337
|
+
if (!m_outer)
|
|
338
|
+
return E_FAIL;
|
|
313
339
|
m_outer->UpdateCharFormat();
|
|
314
340
|
|
|
315
341
|
*ppCF = &(m_outer->m_cf);
|
|
@@ -318,6 +344,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
318
344
|
|
|
319
345
|
//@cmember Get the default paragraph format for the text
|
|
320
346
|
HRESULT TxGetParaFormat(const PARAFORMAT **ppPF) override {
|
|
347
|
+
if (!m_outer)
|
|
348
|
+
return E_FAIL;
|
|
321
349
|
m_outer->UpdateParaFormat();
|
|
322
350
|
|
|
323
351
|
*ppPF = &(m_outer->m_pf);
|
|
@@ -326,6 +354,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
326
354
|
|
|
327
355
|
//@cmember Get the background color for the window
|
|
328
356
|
COLORREF TxGetSysColor(int nIndex) override {
|
|
357
|
+
if (!m_outer)
|
|
358
|
+
return GetSysColor(nIndex);
|
|
329
359
|
// if (/* !m_isDisabled || */ nIndex != COLOR_WINDOW && nIndex != COLOR_WINDOWTEXT && nIndex != COLOR_GRAYTEXT) {
|
|
330
360
|
// This window is either not disabled or the color isn't interesting
|
|
331
361
|
// in the disabled case.
|
|
@@ -400,6 +430,10 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
400
430
|
|
|
401
431
|
//@cmember Get the maximum length for the text
|
|
402
432
|
HRESULT TxGetMaxLength(DWORD *plength) override {
|
|
433
|
+
if (!m_outer) {
|
|
434
|
+
*plength = std::numeric_limits<DWORD>::max();
|
|
435
|
+
return S_OK;
|
|
436
|
+
}
|
|
403
437
|
auto length = m_outer->windowsTextInputProps().maxLength;
|
|
404
438
|
if (length > static_cast<decltype(m_outer->windowsTextInputProps().maxLength)>(std::numeric_limits<DWORD>::max())) {
|
|
405
439
|
length = std::numeric_limits<DWORD>::max();
|
|
@@ -410,6 +444,10 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
410
444
|
|
|
411
445
|
//@cmember Get the bits representing requested scroll bars for the window
|
|
412
446
|
HRESULT TxGetScrollBars(DWORD *pdwScrollBar) override {
|
|
447
|
+
if (!m_outer) {
|
|
448
|
+
*pdwScrollBar = WS_HSCROLL | ES_AUTOHSCROLL;
|
|
449
|
+
return S_OK;
|
|
450
|
+
}
|
|
413
451
|
if (m_outer->m_multiline) {
|
|
414
452
|
*pdwScrollBar = WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_AUTOHSCROLL;
|
|
415
453
|
} else {
|
|
@@ -457,7 +495,8 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
457
495
|
|
|
458
496
|
//@cmember Notify host of events
|
|
459
497
|
HRESULT TxNotify(DWORD iNotify, void *pv) override {
|
|
460
|
-
|
|
498
|
+
if (!m_outer)
|
|
499
|
+
return S_OK;
|
|
461
500
|
|
|
462
501
|
switch (iNotify) {
|
|
463
502
|
case EN_UPDATE:
|
|
@@ -542,6 +581,16 @@ WindowsTextInputComponentView::WindowsTextInputComponentView(
|
|
|
542
581
|
reactContext,
|
|
543
582
|
ComponentViewFeatures::Default & ~ComponentViewFeatures::Background) {}
|
|
544
583
|
|
|
584
|
+
WindowsTextInputComponentView::~WindowsTextInputComponentView() {
|
|
585
|
+
// Release text services first to prevent further callbacks into CompTextHost.
|
|
586
|
+
m_textServices = nullptr;
|
|
587
|
+
|
|
588
|
+
// Detach the CompTextHost so any lingering references cannot use a dangling pointer.
|
|
589
|
+
if (m_textHost) {
|
|
590
|
+
winrt::get_self<CompTextHost>(m_textHost)->Detach();
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
545
594
|
void WindowsTextInputComponentView::HandleCommand(
|
|
546
595
|
const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
|
|
547
596
|
Super::HandleCommand(args);
|
|
@@ -649,17 +698,22 @@ WPARAM PointerRoutedEventArgsToMouseWParam(
|
|
|
649
698
|
return wParam;
|
|
650
699
|
}
|
|
651
700
|
|
|
652
|
-
bool WindowsTextInputComponentView::IsDoubleClick() {
|
|
701
|
+
bool WindowsTextInputComponentView::IsDoubleClick(uint32_t pointerId) {
|
|
653
702
|
using namespace std::chrono;
|
|
654
703
|
|
|
655
704
|
auto now = steady_clock::now();
|
|
656
|
-
auto
|
|
705
|
+
auto it = m_lastClickTimeByPointer.find(pointerId);
|
|
706
|
+
bool isDouble = false;
|
|
657
707
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
708
|
+
if (it != m_lastClickTimeByPointer.end()) {
|
|
709
|
+
auto duration = duration_cast<milliseconds>(now - it->second).count();
|
|
710
|
+
isDouble = (duration < ::GetDoubleClickTime());
|
|
711
|
+
it->second = now;
|
|
712
|
+
} else {
|
|
713
|
+
m_lastClickTimeByPointer[pointerId] = now;
|
|
714
|
+
}
|
|
661
715
|
|
|
662
|
-
return
|
|
716
|
+
return isDouble;
|
|
663
717
|
}
|
|
664
718
|
|
|
665
719
|
void WindowsTextInputComponentView::OnPointerPressed(
|
|
@@ -678,7 +732,7 @@ void WindowsTextInputComponentView::OnPointerPressed(
|
|
|
678
732
|
if (pp.PointerDeviceType() == winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse) {
|
|
679
733
|
switch (pp.Properties().PointerUpdateKind()) {
|
|
680
734
|
case winrt::Microsoft::ReactNative::Composition::Input::PointerUpdateKind::LeftButtonPressed:
|
|
681
|
-
if (IsDoubleClick()) {
|
|
735
|
+
if (IsDoubleClick(pp.PointerId())) {
|
|
682
736
|
msg = WM_LBUTTONDBLCLK;
|
|
683
737
|
} else {
|
|
684
738
|
msg = WM_LBUTTONDOWN;
|
|
@@ -699,10 +753,14 @@ void WindowsTextInputComponentView::OnPointerPressed(
|
|
|
699
753
|
wParam |= (XBUTTON2 << 16);
|
|
700
754
|
break;
|
|
701
755
|
}
|
|
702
|
-
wParam
|
|
756
|
+
wParam |= PointerRoutedEventArgsToMouseWParam(args);
|
|
703
757
|
} else {
|
|
704
|
-
|
|
705
|
-
|
|
758
|
+
if (IsDoubleClick(pp.PointerId())) {
|
|
759
|
+
msg = WM_LBUTTONDBLCLK;
|
|
760
|
+
} else {
|
|
761
|
+
msg = WM_LBUTTONDOWN;
|
|
762
|
+
}
|
|
763
|
+
wParam = PointerRoutedEventArgsToMouseWParam(args);
|
|
706
764
|
}
|
|
707
765
|
|
|
708
766
|
if (m_textServices && msg) {
|
|
@@ -764,10 +822,10 @@ void WindowsTextInputComponentView::OnPointerReleased(
|
|
|
764
822
|
wParam |= (XBUTTON2 << 16);
|
|
765
823
|
break;
|
|
766
824
|
}
|
|
767
|
-
wParam
|
|
825
|
+
wParam |= PointerRoutedEventArgsToMouseWParam(args);
|
|
768
826
|
} else {
|
|
769
|
-
msg =
|
|
770
|
-
wParam =
|
|
827
|
+
msg = WM_LBUTTONUP;
|
|
828
|
+
wParam = PointerRoutedEventArgsToMouseWParam(args);
|
|
771
829
|
}
|
|
772
830
|
|
|
773
831
|
if (m_textServices && msg) {
|
|
@@ -817,23 +875,18 @@ void WindowsTextInputComponentView::OnPointerMoved(
|
|
|
817
875
|
static_cast<LONG>(position.Y * m_layoutMetrics.pointScaleFactor)};
|
|
818
876
|
lParam = static_cast<LPARAM>(POINTTOPOINTS(ptContainer));
|
|
819
877
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
wParam = PointerRoutedEventArgsToMouseWParam(args);
|
|
823
|
-
} else {
|
|
824
|
-
msg = WM_POINTERUPDATE;
|
|
825
|
-
wParam = PointerPointToPointerWParam(pp);
|
|
826
|
-
}
|
|
878
|
+
msg = WM_MOUSEMOVE;
|
|
879
|
+
wParam = PointerRoutedEventArgsToMouseWParam(args);
|
|
827
880
|
|
|
828
881
|
if (m_textServices) {
|
|
829
882
|
LRESULT lresult;
|
|
830
883
|
DrawBlock db(*this);
|
|
831
884
|
auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
|
|
832
885
|
args.Handled(hr != S_FALSE);
|
|
833
|
-
}
|
|
834
886
|
|
|
835
|
-
|
|
836
|
-
|
|
887
|
+
m_textServices->OnTxSetCursor(
|
|
888
|
+
DVASPECT_CONTENT, -1, nullptr, nullptr, nullptr, nullptr, nullptr, ptContainer.x, ptContainer.y);
|
|
889
|
+
}
|
|
837
890
|
}
|
|
838
891
|
|
|
839
892
|
void WindowsTextInputComponentView::OnPointerWheelChanged(
|
|
@@ -935,7 +988,7 @@ bool WindowsTextInputComponentView::ShouldSubmit(
|
|
|
935
988
|
bool ctrlDown = (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Control) &
|
|
936
989
|
winrt::Microsoft::UI::Input::VirtualKeyStates::Down) ==
|
|
937
990
|
winrt::Microsoft::UI::Input::VirtualKeyStates::Down;
|
|
938
|
-
bool altDown = (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::
|
|
991
|
+
bool altDown = (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Menu) &
|
|
939
992
|
winrt::Microsoft::UI::Input::VirtualKeyStates::Down) ==
|
|
940
993
|
winrt::Microsoft::UI::Input::VirtualKeyStates::Down;
|
|
941
994
|
bool metaDown = (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::LeftWindows) &
|
|
@@ -946,7 +999,7 @@ bool WindowsTextInputComponentView::ShouldSubmit(
|
|
|
946
999
|
winrt::Microsoft::UI::Input::VirtualKeyStates::Down;
|
|
947
1000
|
return (submitKeyEvent.shiftKey && shiftDown) || (submitKeyEvent.ctrlKey && ctrlDown) ||
|
|
948
1001
|
(submitKeyEvent.altKey && altDown) || (submitKeyEvent.metaKey && metaDown) ||
|
|
949
|
-
(!submitKeyEvent.shiftKey && !submitKeyEvent.
|
|
1002
|
+
(!submitKeyEvent.shiftKey && !submitKeyEvent.ctrlKey && !submitKeyEvent.altKey && !submitKeyEvent.metaKey &&
|
|
950
1003
|
!shiftDown && !ctrlDown && !altDown && !metaDown);
|
|
951
1004
|
} else {
|
|
952
1005
|
shouldSubmit = false;
|
|
@@ -1836,6 +1889,7 @@ WindowsTextInputComponentView::createVisual() noexcept {
|
|
|
1836
1889
|
winrt::com_ptr<::IUnknown> spUnk;
|
|
1837
1890
|
winrt::check_hresult(g_pfnCreateTextServices(nullptr, m_textHost.get(), spUnk.put()));
|
|
1838
1891
|
spUnk.as(m_textServices);
|
|
1892
|
+
winrt::check_bool(m_textServices != nullptr);
|
|
1839
1893
|
|
|
1840
1894
|
LRESULT res;
|
|
1841
1895
|
winrt::check_hresult(m_textServices->TxSendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0, &res));
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include <textserv.h>
|
|
12
12
|
#include <windows.ui.composition.interop.h>
|
|
13
13
|
#include <winrt/Windows.UI.Composition.h>
|
|
14
|
+
#include <unordered_map>
|
|
14
15
|
#include "../ComponentView.h"
|
|
15
16
|
#include "../CompositionHelpers.h"
|
|
16
17
|
#include "../CompositionViewComponentView.h"
|
|
@@ -74,12 +75,13 @@ struct WindowsTextInputComponentView
|
|
|
74
75
|
std::optional<std::string> getAccessiblityValue() noexcept override;
|
|
75
76
|
void setAcccessiblityValue(std::string &&value) noexcept override;
|
|
76
77
|
bool getAcccessiblityIsReadOnly() noexcept override;
|
|
77
|
-
bool IsDoubleClick();
|
|
78
|
+
bool IsDoubleClick(uint32_t pointerId);
|
|
78
79
|
|
|
79
80
|
WindowsTextInputComponentView(
|
|
80
81
|
const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
|
|
81
82
|
facebook::react::Tag tag,
|
|
82
83
|
winrt::Microsoft::ReactNative::ReactContext const &reactContext);
|
|
84
|
+
~WindowsTextInputComponentView();
|
|
83
85
|
|
|
84
86
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual createVisual() noexcept;
|
|
85
87
|
|
|
@@ -152,7 +154,7 @@ struct WindowsTextInputComponentView
|
|
|
152
154
|
DWORD m_propBits{0};
|
|
153
155
|
HCURSOR m_hcursor{nullptr};
|
|
154
156
|
POINT m_caretPosition{0, 0};
|
|
155
|
-
std::chrono::steady_clock::time_point
|
|
157
|
+
std::unordered_map<uint32_t, std::chrono::steady_clock::time_point> m_lastClickTimeByPointer;
|
|
156
158
|
std::vector<facebook::react::CompWindowsTextInputSubmitKeyEventsStruct> m_submitKeyEvents;
|
|
157
159
|
};
|
|
158
160
|
|
|
@@ -46,12 +46,12 @@ WindowsComponentDescriptorRegistry::WindowsComponentDescriptorRegistry()
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
void WindowsComponentDescriptorRegistry::add(const facebook::react::ComponentDescriptorProvider &provider) noexcept {
|
|
49
|
-
m_componentNames.
|
|
49
|
+
m_componentNames.insert(provider.name);
|
|
50
50
|
m_componentDescriptorRegistry->add(provider);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
bool WindowsComponentDescriptorRegistry::hasComponentProvider(const std::string &name) noexcept {
|
|
54
|
-
return
|
|
54
|
+
return m_componentNames.count(name) != 0;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
bool WindowsComponentDescriptorRegistry::isXamlSupportRequired() const noexcept {
|
|
@@ -68,7 +68,7 @@ void WindowsComponentDescriptorRegistry::Add(
|
|
|
68
68
|
auto builder = winrt::make<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>();
|
|
69
69
|
provider(builder);
|
|
70
70
|
|
|
71
|
-
m_componentNames.
|
|
71
|
+
m_componentNames.insert(winrt::to_string(componentName));
|
|
72
72
|
m_descriptorFlavors.emplace_back(std::make_shared<std::string>(winrt::to_string(componentName)));
|
|
73
73
|
auto handle = reinterpret_cast<facebook::react::ComponentHandle>(
|
|
74
74
|
facebook::react::ComponentName(m_descriptorFlavors.back()->c_str()));
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
#include <ReactPropertyBag.h>
|
|
11
11
|
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
|
|
12
12
|
|
|
13
|
+
#include <unordered_set>
|
|
14
|
+
|
|
13
15
|
namespace Microsoft::ReactNative {
|
|
14
16
|
|
|
15
17
|
struct WindowsComponentDescriptorRegistry {
|
|
@@ -41,7 +43,7 @@ struct WindowsComponentDescriptorRegistry {
|
|
|
41
43
|
void add(const facebook::react::ComponentDescriptorProvider &provider) noexcept;
|
|
42
44
|
|
|
43
45
|
std::vector<std::shared_ptr<const std::string>> m_descriptorFlavors;
|
|
44
|
-
std::
|
|
46
|
+
std::unordered_set<std::string> m_componentNames;
|
|
45
47
|
std::shared_ptr<facebook::react::ComponentDescriptorProviderRegistry> m_componentDescriptorRegistry;
|
|
46
48
|
|
|
47
49
|
std::map<std::shared_ptr<const std::string>, winrt::Microsoft::ReactNative::IReactViewComponentBuilder const>
|
|
@@ -72,7 +72,6 @@ wicBitmapSourceFromStream(const winrt::Windows::Storage::Streams::IRandomAccessS
|
|
|
72
72
|
return {decodedFrame, imagingFactory, nullptr};
|
|
73
73
|
} catch (winrt::hresult_error const &ex) {
|
|
74
74
|
auto errorInfo = std::make_shared<facebook::react::ImageErrorInfo>();
|
|
75
|
-
errorInfo = std::make_shared<facebook::react::ImageErrorInfo>();
|
|
76
75
|
errorInfo->error = ::Microsoft::ReactNative::FormatHResultError(winrt::hresult_error(ex));
|
|
77
76
|
return {nullptr, nullptr, errorInfo};
|
|
78
77
|
}
|
|
@@ -22,19 +22,19 @@ int64_t AnimatedNode::Tag() {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
void AnimatedNode::AddChild(const int64_t animatedNodeTag) {
|
|
25
|
-
m_children.
|
|
25
|
+
m_children.insert(animatedNodeTag);
|
|
26
26
|
GetChildNode(animatedNodeTag)->OnAttachToNode(m_tag);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
void AnimatedNode::RemoveChild(const int64_t tag) {
|
|
30
30
|
if (const auto childNode = GetChildNode(tag)) {
|
|
31
31
|
childNode->OnDetachedFromNode(m_tag);
|
|
32
|
-
m_children.erase(
|
|
32
|
+
m_children.erase(tag);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
AnimatedNode *AnimatedNode::GetChildNode(int64_t tag) {
|
|
37
|
-
if (
|
|
37
|
+
if (m_children.count(tag)) {
|
|
38
38
|
if (const auto manager = m_manager.lock()) {
|
|
39
39
|
return manager->GetAnimatedNode(tag);
|
|
40
40
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include <JSValue.h>
|
|
7
7
|
#include <cstdint>
|
|
8
8
|
#include <memory>
|
|
9
|
+
#include <unordered_set>
|
|
9
10
|
#include <vector>
|
|
10
11
|
|
|
11
12
|
namespace Microsoft::ReactNative {
|
|
@@ -20,7 +21,7 @@ class AnimatedNode {
|
|
|
20
21
|
void AddChild(int64_t animatedNode);
|
|
21
22
|
void RemoveChild(int64_t animatedNode);
|
|
22
23
|
|
|
23
|
-
std::
|
|
24
|
+
std::unordered_set<int64_t> &Children() {
|
|
24
25
|
return m_children;
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -37,7 +38,7 @@ class AnimatedNode {
|
|
|
37
38
|
AnimatedNode *GetChildNode(int64_t tag);
|
|
38
39
|
int64_t m_tag{0};
|
|
39
40
|
const std::weak_ptr<NativeAnimatedNodeManager> m_manager;
|
|
40
|
-
std::
|
|
41
|
+
std::unordered_set<int64_t> m_children{};
|
|
41
42
|
bool m_useComposition{false};
|
|
42
43
|
|
|
43
44
|
bool HasCompatibleAnimationDriver(int64_t tag);
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#include <ReactCoreInjection.h>
|
|
10
10
|
#include <react/runtime/PlatformTimerRegistry.h>
|
|
11
11
|
#include <react/runtime/TimerManager.h>
|
|
12
|
+
#include <atomic>
|
|
12
13
|
|
|
13
14
|
namespace Microsoft::ReactNative {
|
|
14
15
|
|
|
@@ -114,7 +115,7 @@ struct Timing : public std::enable_shared_from_this<Timing> {
|
|
|
114
115
|
xaml::Media::CompositionTarget::Rendering_revoker m_rendering;
|
|
115
116
|
winrt::Microsoft::ReactNative::ITimer m_dispatcherQueueTimer{nullptr};
|
|
116
117
|
winrt::weak_ref<winrt::Microsoft::ReactNative::IReactDispatcher> m_uiDispatcher;
|
|
117
|
-
bool m_usingRendering{false};
|
|
118
|
+
std::atomic<bool> m_usingRendering{false};
|
|
118
119
|
bool m_usePostForRendering{false};
|
|
119
120
|
};
|
|
120
121
|
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
-->
|
|
11
11
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
12
12
|
<PropertyGroup>
|
|
13
|
-
<ReactNativeWindowsVersion>0.84.0-preview.
|
|
13
|
+
<ReactNativeWindowsVersion>0.84.0-preview.6</ReactNativeWindowsVersion>
|
|
14
14
|
<ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
|
|
15
15
|
<ReactNativeWindowsMinor>84</ReactNativeWindowsMinor>
|
|
16
16
|
<ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
|
|
17
17
|
<ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
|
|
18
|
-
<ReactNativeWindowsCommitId>
|
|
18
|
+
<ReactNativeWindowsCommitId>91ceaa8418a39db986927aaaff0cdd07dbf9ba2e</ReactNativeWindowsCommitId>
|
|
19
19
|
</PropertyGroup>
|
|
20
20
|
</Project>
|