react-native-windows 0.74.25 → 0.74.27
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 +352 -0
- package/Microsoft.ReactNative/Fabric/ComponentView.cpp +26 -46
- package/Microsoft.ReactNative/Fabric/ComponentView.h +6 -19
- package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.cpp +5 -0
- package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.h +4 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +164 -3
- package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +7 -0
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +205 -101
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +21 -13
- package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +9 -2
- package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +2 -1
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +59 -9
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +2 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +78 -30
- package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +21 -1
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +10 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +3 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +14 -1
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +4 -0
- package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -1
- package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +25 -0
- package/PropertySheets/Generated/PackageVersion.g.props +3 -3
- package/codegen/NativeAccessibilityInfoSpec.g.h +1 -0
- package/codegen/NativeAccessibilityManagerSpec.g.h +1 -0
- package/codegen/NativeActionSheetManagerSpec.g.h +1 -0
- package/codegen/NativeAlertManagerSpec.g.h +1 -0
- package/codegen/NativeAnimatedModuleSpec.g.h +1 -0
- package/codegen/NativeAnimatedTurboModuleSpec.g.h +1 -0
- package/codegen/NativeAnimationsDebugModuleSpec.g.h +1 -0
- package/codegen/NativeAppStateSpec.g.h +1 -0
- package/codegen/NativeAppThemeSpec.g.h +1 -0
- package/codegen/NativeAppearanceSpec.g.h +1 -0
- package/codegen/NativeBlobModuleSpec.g.h +1 -0
- package/codegen/NativeBugReportingSpec.g.h +1 -0
- package/codegen/NativeClipboardSpec.g.h +1 -0
- package/codegen/NativeDevLoadingViewSpec.g.h +1 -0
- package/codegen/NativeDevMenuSpec.g.h +1 -0
- package/codegen/NativeDevSettingsSpec.g.h +1 -0
- package/codegen/NativeDevToolsSettingsManagerSpec.g.h +1 -0
- package/codegen/NativeDeviceEventManagerSpec.g.h +1 -0
- package/codegen/NativeDeviceInfoSpec.g.h +1 -0
- package/codegen/NativeDialogManagerAndroidSpec.g.h +1 -0
- package/codegen/NativeDialogManagerWindowsSpec.g.h +1 -0
- package/codegen/NativeExceptionsManagerSpec.g.h +1 -0
- package/codegen/NativeFileReaderModuleSpec.g.h +1 -0
- package/codegen/NativeFrameRateLoggerSpec.g.h +1 -0
- package/codegen/NativeHeadlessJsTaskSupportSpec.g.h +1 -0
- package/codegen/NativeI18nManagerSpec.g.h +1 -0
- package/codegen/NativeImageEditorSpec.g.h +1 -0
- package/codegen/NativeImageLoaderAndroidSpec.g.h +1 -0
- package/codegen/NativeImageLoaderIOSSpec.g.h +1 -0
- package/codegen/NativeImageStoreAndroidSpec.g.h +1 -0
- package/codegen/NativeImageStoreIOSSpec.g.h +1 -0
- package/codegen/NativeIntentAndroidSpec.g.h +1 -0
- package/codegen/NativeIntersectionObserverSpec.g.h +1 -0
- package/codegen/NativeJSCHeapCaptureSpec.g.h +1 -0
- package/codegen/NativeJSCSamplingProfilerSpec.g.h +1 -0
- package/codegen/NativeKeyboardObserverSpec.g.h +1 -0
- package/codegen/NativeLinkingManagerSpec.g.h +1 -0
- package/codegen/NativeLogBoxSpec.g.h +1 -0
- package/codegen/NativeModalManagerSpec.g.h +1 -0
- package/codegen/NativeMutationObserverSpec.g.h +1 -0
- package/codegen/NativeNetworkingAndroidSpec.g.h +1 -0
- package/codegen/NativeNetworkingIOSSpec.g.h +1 -0
- package/codegen/NativePerformanceObserverSpec.g.h +1 -0
- package/codegen/NativePerformanceSpec.g.h +1 -0
- package/codegen/NativePermissionsAndroidSpec.g.h +1 -0
- package/codegen/NativePlatformConstantsAndroidSpec.g.h +1 -0
- package/codegen/NativePlatformConstantsIOSSpec.g.h +1 -0
- package/codegen/NativePlatformConstantsWinSpec.g.h +1 -0
- package/codegen/NativePushNotificationManagerIOSSpec.g.h +1 -0
- package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +1 -0
- package/codegen/NativeRedBoxSpec.g.h +1 -0
- package/codegen/NativeSampleTurboModuleSpec.g.h +1 -0
- package/codegen/NativeSegmentFetcherSpec.g.h +1 -0
- package/codegen/NativeSettingsManagerSpec.g.h +1 -0
- package/codegen/NativeShareModuleSpec.g.h +1 -0
- package/codegen/NativeSoundManagerSpec.g.h +1 -0
- package/codegen/NativeSourceCodeSpec.g.h +1 -0
- package/codegen/NativeStatusBarManagerAndroidSpec.g.h +1 -0
- package/codegen/NativeStatusBarManagerIOSSpec.g.h +1 -0
- package/codegen/NativeTimingSpec.g.h +1 -0
- package/codegen/NativeToastAndroidSpec.g.h +1 -0
- package/codegen/NativeUIManagerSpec.g.h +1 -0
- package/codegen/NativeVibrationSpec.g.h +1 -0
- package/codegen/NativeWebSocketModuleSpec.g.h +1 -0
- package/package.json +3 -3
|
@@ -12,15 +12,18 @@
|
|
|
12
12
|
#include <Views/ShadowNodeBase.h>
|
|
13
13
|
#include <windows.h>
|
|
14
14
|
#include <windowsx.h>
|
|
15
|
+
#include <winrt/Windows.UI.Core.h>
|
|
15
16
|
#include <winrt/Windows.UI.Input.h>
|
|
16
17
|
#include "Composition.Input.h"
|
|
17
18
|
#include "CompositionViewComponentView.h"
|
|
18
19
|
#include "ReactNativeIsland.h"
|
|
19
20
|
#include "RootComponentView.h"
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
namespace ABI::Microsoft::UI::Input {
|
|
23
|
+
struct IInputCursor;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#include <Microsoft.UI.Input.InputCursor.Interop.h>
|
|
24
27
|
|
|
25
28
|
namespace Microsoft::ReactNative {
|
|
26
29
|
|
|
@@ -328,6 +331,11 @@ CompositionEventHandler::~CompositionEventHandler() {
|
|
|
328
331
|
}
|
|
329
332
|
}
|
|
330
333
|
#endif
|
|
334
|
+
|
|
335
|
+
if (m_hcursorOwned) {
|
|
336
|
+
::DestroyCursor(m_hcursor);
|
|
337
|
+
m_hcursor = nullptr;
|
|
338
|
+
}
|
|
331
339
|
}
|
|
332
340
|
|
|
333
341
|
facebook::react::SurfaceId CompositionEventHandler::SurfaceId() const noexcept {
|
|
@@ -507,6 +515,10 @@ int64_t CompositionEventHandler::SendMessage(HWND hwnd, uint32_t msg, uint64_t w
|
|
|
507
515
|
}
|
|
508
516
|
break;
|
|
509
517
|
}
|
|
518
|
+
case WM_SETCURSOR: {
|
|
519
|
+
UpdateCursor();
|
|
520
|
+
return 1;
|
|
521
|
+
}
|
|
510
522
|
}
|
|
511
523
|
|
|
512
524
|
return 0;
|
|
@@ -753,6 +765,155 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
|
|
|
753
765
|
hoveredViews.emplace_back(ReactTaggedView(componentViewDescriptor.view));
|
|
754
766
|
}
|
|
755
767
|
m_currentlyHoveredViewsPerPointer[pointerId] = std::move(hoveredViews);
|
|
768
|
+
|
|
769
|
+
if (IsMousePointerEvent(event)) {
|
|
770
|
+
UpdateCursor();
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
void CompositionEventHandler::UpdateCursor() noexcept {
|
|
775
|
+
for (auto &taggedView : m_currentlyHoveredViewsPerPointer[MOUSE_POINTER_ID]) {
|
|
776
|
+
if (auto view = taggedView.view()) {
|
|
777
|
+
if (auto viewcomponent =
|
|
778
|
+
view.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ComponentView>()) {
|
|
779
|
+
auto cursorInfo = viewcomponent->cursor();
|
|
780
|
+
if (cursorInfo.first != facebook::react::Cursor::Auto || cursorInfo.second != nullptr) {
|
|
781
|
+
SetCursor(cursorInfo.first, cursorInfo.second);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
SetCursor(facebook::react::Cursor::Auto, nullptr);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
void CompositionEventHandler::SetCursor(facebook::react::Cursor cursor, HCURSOR hcur) noexcept {
|
|
792
|
+
if (m_currentCursor == cursor && m_hcursor == hcur)
|
|
793
|
+
return;
|
|
794
|
+
|
|
795
|
+
if (auto strongRootView = m_wkRootView.get()) {
|
|
796
|
+
if (auto island = strongRootView.Island()) {
|
|
797
|
+
auto pointerSource = winrt::Microsoft::UI::Input::InputPointerSource::GetForIsland(island);
|
|
798
|
+
|
|
799
|
+
if (!hcur) {
|
|
800
|
+
winrt::Windows::UI::Core::CoreCursorType type = winrt::Windows::UI::Core::CoreCursorType::Arrow;
|
|
801
|
+
switch (cursor) {
|
|
802
|
+
case facebook::react::Cursor::Pointer:
|
|
803
|
+
type = winrt::Windows::UI::Core::CoreCursorType::Hand;
|
|
804
|
+
break;
|
|
805
|
+
/* -- Additional cursors not added in core until later version
|
|
806
|
+
case facebook::react::Cursor::Help:
|
|
807
|
+
type = winrt::Windows::UI::Core::CoreCursorType::Help;
|
|
808
|
+
break;
|
|
809
|
+
case facebook::react::Cursor::NotAllowed:
|
|
810
|
+
type = winrt::Windows::UI::Core::CoreCursorType::UniversalNo;
|
|
811
|
+
break;
|
|
812
|
+
case facebook::react::Cursor::Wait:
|
|
813
|
+
type = winrt::Windows::UI::Core::CoreCursorType::Wait;
|
|
814
|
+
break;
|
|
815
|
+
case facebook::react::Cursor::Move:
|
|
816
|
+
type = winrt::Windows::UI::Core::CoreCursorType::SizeAll;
|
|
817
|
+
break;
|
|
818
|
+
case facebook::react::Cursor::NESWResize:
|
|
819
|
+
type = winrt::Windows::UI::Core::CoreCursorType::SizeNortheastSouthwest;
|
|
820
|
+
break;
|
|
821
|
+
case facebook::react::Cursor::NSResize:
|
|
822
|
+
type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthSouth;
|
|
823
|
+
break;
|
|
824
|
+
case facebook::react::Cursor::NWSEResize:
|
|
825
|
+
type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthwestSoutheast;
|
|
826
|
+
break;
|
|
827
|
+
case facebook::react::Cursor::EWResize:
|
|
828
|
+
type = winrt::Windows::UI::Core::CoreCursorType::SizeWestEast;
|
|
829
|
+
break;
|
|
830
|
+
case facebook::react::Cursor::Text:
|
|
831
|
+
type = winrt::Windows::UI::Core::CoreCursorType::IBeam;
|
|
832
|
+
break;
|
|
833
|
+
case facebook::react::Cursor::Progress:
|
|
834
|
+
type = winrt::Windows::UI::Core::CoreCursorType::Wait; // IDC_APPSTARTING not mapped to CoreCursor?
|
|
835
|
+
break;
|
|
836
|
+
case facebook::react::Cursor::Crosshair:
|
|
837
|
+
type = winrt::Windows::UI::Core::CoreCursorType::Cross;
|
|
838
|
+
break;
|
|
839
|
+
*/
|
|
840
|
+
default:
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
m_inputCursor = winrt::Microsoft::UI::Input::InputCursor::CreateFromCoreCursor(
|
|
845
|
+
winrt::Windows::UI::Core::CoreCursor(type, 0));
|
|
846
|
+
m_hcursor = hcur;
|
|
847
|
+
} else {
|
|
848
|
+
auto cursorInterop = winrt::get_activation_factory<
|
|
849
|
+
winrt::Microsoft::UI::Input::InputCursor,
|
|
850
|
+
ABI::Microsoft::UI::Input::IInputCursorStaticsInterop>();
|
|
851
|
+
winrt::com_ptr<IUnknown> spunk;
|
|
852
|
+
winrt::check_hresult(cursorInterop->CreateFromHCursor(
|
|
853
|
+
hcur, reinterpret_cast<ABI::Microsoft::UI::Input::IInputCursor **>(spunk.put_void())));
|
|
854
|
+
m_hcursor = hcur;
|
|
855
|
+
m_inputCursor = spunk.as<winrt::Microsoft::UI::Input::InputCursor>();
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
pointerSource.Cursor(m_inputCursor);
|
|
859
|
+
} else {
|
|
860
|
+
if (m_hcursorOwned) {
|
|
861
|
+
::DestroyCursor(m_hcursor);
|
|
862
|
+
m_hcursorOwned = false;
|
|
863
|
+
}
|
|
864
|
+
if (hcur == nullptr) {
|
|
865
|
+
const WCHAR *idc = IDC_ARROW;
|
|
866
|
+
switch (cursor) {
|
|
867
|
+
case facebook::react::Cursor::Pointer:
|
|
868
|
+
idc = IDC_HAND;
|
|
869
|
+
break;
|
|
870
|
+
/* -- Additional cursors not added in core until later version
|
|
871
|
+
case facebook::react::Cursor::Help:
|
|
872
|
+
idc = IDC_HELP;
|
|
873
|
+
break;
|
|
874
|
+
case facebook::react::Cursor::NotAllowed:
|
|
875
|
+
idc = IDC_NO;
|
|
876
|
+
break;
|
|
877
|
+
case facebook::react::Cursor::Wait:
|
|
878
|
+
idc = IDC_WAIT;
|
|
879
|
+
break;
|
|
880
|
+
case facebook::react::Cursor::Move:
|
|
881
|
+
idc = IDC_SIZEALL;
|
|
882
|
+
break;
|
|
883
|
+
case facebook::react::Cursor::NESWResize:
|
|
884
|
+
idc = IDC_SIZENESW;
|
|
885
|
+
break;
|
|
886
|
+
case facebook::react::Cursor::NSResize:
|
|
887
|
+
idc = IDC_SIZENS;
|
|
888
|
+
break;
|
|
889
|
+
case facebook::react::Cursor::NWSEResize:
|
|
890
|
+
idc = IDC_SIZENWSE;
|
|
891
|
+
break;
|
|
892
|
+
case facebook::react::Cursor::EWResize:
|
|
893
|
+
idc = IDC_SIZEWE;
|
|
894
|
+
break;
|
|
895
|
+
case facebook::react::Cursor::Text:
|
|
896
|
+
idc = IDC_IBEAM;
|
|
897
|
+
break;
|
|
898
|
+
case facebook::react::Cursor::Progress:
|
|
899
|
+
idc = IDC_APPSTARTING;
|
|
900
|
+
break;
|
|
901
|
+
case facebook::react::Cursor::Crosshair:
|
|
902
|
+
idc = IDC_CROSS;
|
|
903
|
+
break;
|
|
904
|
+
*/
|
|
905
|
+
default:
|
|
906
|
+
break;
|
|
907
|
+
}
|
|
908
|
+
m_hcursor = ::LoadCursor(nullptr, idc);
|
|
909
|
+
m_hcursorOwned = true;
|
|
910
|
+
} else {
|
|
911
|
+
m_hcursor = hcur;
|
|
912
|
+
}
|
|
913
|
+
::SetCursor(m_hcursor);
|
|
914
|
+
}
|
|
915
|
+
m_currentCursor = cursor;
|
|
916
|
+
}
|
|
756
917
|
}
|
|
757
918
|
|
|
758
919
|
void CompositionEventHandler::UpdateActiveTouch(
|
|
@@ -147,6 +147,9 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
147
147
|
static void
|
|
148
148
|
UpdateActiveTouch(ActiveTouch &activeTouch, facebook::react::Point ptScaled, facebook::react::Point ptLocal) noexcept;
|
|
149
149
|
|
|
150
|
+
void UpdateCursor() noexcept;
|
|
151
|
+
void SetCursor(facebook::react::Cursor cursor, HCURSOR hcur) noexcept;
|
|
152
|
+
|
|
150
153
|
std::map<PointerId, ActiveTouch> m_activeTouches; // iOS is map of touch event args to ActiveTouch..?
|
|
151
154
|
PointerId m_touchId = 0;
|
|
152
155
|
int m_fragmentTag = -1;
|
|
@@ -157,6 +160,10 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
|
|
|
157
160
|
|
|
158
161
|
facebook::react::Tag m_pointerCapturingComponentTag{-1}; // Component that has captured input
|
|
159
162
|
std::vector<PointerId> m_capturedPointers;
|
|
163
|
+
HCURSOR m_hcursor{nullptr};
|
|
164
|
+
bool m_hcursorOwned{false}; // If we create the cursor, so we need to destroy it
|
|
165
|
+
facebook::react::Cursor m_currentCursor{facebook::react::Cursor::Auto};
|
|
166
|
+
winrt::Microsoft::UI::Input::InputCursor m_inputCursor{nullptr};
|
|
160
167
|
|
|
161
168
|
#ifdef USE_WINUI3
|
|
162
169
|
winrt::event_token m_pointerPressedToken;
|
|
@@ -40,7 +40,7 @@ constexpr float FOCUS_VISUAL_WIDTH = 2.0f;
|
|
|
40
40
|
// ----- m_visual <-- Background / clip - Can be a custom visual depending on Component type
|
|
41
41
|
// |
|
|
42
42
|
// ----- Border Visuals x N (BorderPrimitive attached to m_visual)
|
|
43
|
-
// ------Focus Visual Container
|
|
43
|
+
// ------Focus Visual Container (created when hosting focus visuals)
|
|
44
44
|
// |
|
|
45
45
|
// |------Inner Focus Visual
|
|
46
46
|
// |
|
|
@@ -53,13 +53,11 @@ ComponentView::ComponentView(
|
|
|
53
53
|
const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
|
|
54
54
|
facebook::react::Tag tag,
|
|
55
55
|
winrt::Microsoft::ReactNative::ReactContext const &reactContext,
|
|
56
|
-
ComponentViewFeatures flags
|
|
57
|
-
|
|
56
|
+
ComponentViewFeatures flags,
|
|
57
|
+
winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder)
|
|
58
|
+
: base_type(tag, reactContext, builder), m_compContext(compContext), m_flags(flags) {
|
|
58
59
|
m_outerVisual = compContext.CreateSpriteVisual(); // TODO could be a raw ContainerVisual if we had a
|
|
59
60
|
// CreateContainerVisual in ICompositionContext
|
|
60
|
-
m_focusVisual = compContext.CreateSpriteVisual(); // TODO could be a raw ContainerVisual if we had a
|
|
61
|
-
// CreateContainerVisual in ICompositionContext
|
|
62
|
-
m_outerVisual.InsertAt(m_focusVisual, 0);
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
ComponentView::~ComponentView() {
|
|
@@ -90,13 +88,17 @@ void ComponentView::onThemeChanged() noexcept {
|
|
|
90
88
|
m_borderPrimitive->onThemeChanged(
|
|
91
89
|
m_layoutMetrics, BorderPrimitive::resolveAndAlignBorderMetrics(m_layoutMetrics, *viewProps()));
|
|
92
90
|
}
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
91
|
+
if (m_componentHostingFocusVisual) {
|
|
92
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
|
|
93
|
+
auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
94
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->onThemeChanged(
|
|
95
|
+
innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
96
|
+
}
|
|
97
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
|
|
98
|
+
auto outerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
99
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->onThemeChanged(
|
|
100
|
+
outerFocusMetrics, focusBorderMetrics(false /*inner*/, outerFocusMetrics));
|
|
101
|
+
}
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
if ((m_flags & ComponentViewFeatures::ShadowProps) == ComponentViewFeatures::ShadowProps) {
|
|
@@ -160,14 +162,18 @@ void ComponentView::updateProps(
|
|
|
160
162
|
if (m_borderPrimitive) {
|
|
161
163
|
m_borderPrimitive->updateProps(oldViewProps, newViewProps);
|
|
162
164
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
165
|
+
|
|
166
|
+
if (m_componentHostingFocusVisual) {
|
|
167
|
+
if (!newViewProps.enableFocusRing) {
|
|
168
|
+
m_componentHostingFocusVisual->hostFocusVisual(false, get_strong());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
|
|
172
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->updateProps(oldViewProps, newViewProps);
|
|
173
|
+
}
|
|
174
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
|
|
175
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->updateProps(oldViewProps, newViewProps);
|
|
176
|
+
}
|
|
171
177
|
}
|
|
172
178
|
if ((m_flags & ComponentViewFeatures::ShadowProps) == ComponentViewFeatures::ShadowProps) {
|
|
173
179
|
updateShadowProps(oldViewProps, newViewProps);
|
|
@@ -200,44 +206,70 @@ void ComponentView::updateLayoutMetrics(
|
|
|
200
206
|
});
|
|
201
207
|
}
|
|
202
208
|
|
|
203
|
-
|
|
209
|
+
base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
|
|
204
210
|
|
|
205
211
|
if (layoutMetrics != oldLayoutMetrics) {
|
|
206
212
|
if (m_borderPrimitive) {
|
|
207
213
|
m_borderPrimitive->markNeedsUpdate();
|
|
208
214
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (m_focusOuterPrimitive) {
|
|
213
|
-
m_focusOuterPrimitive->markNeedsUpdate();
|
|
215
|
+
|
|
216
|
+
if (m_componentHostingFocusVisual) {
|
|
217
|
+
m_componentHostingFocusVisual->updateFocusLayoutMetrics();
|
|
214
218
|
}
|
|
215
219
|
}
|
|
216
220
|
|
|
217
|
-
base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
|
|
218
221
|
UpdateCenterPropertySet();
|
|
219
222
|
}
|
|
220
223
|
|
|
221
|
-
void ComponentView::updateFocusLayoutMetrics(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
224
|
+
void ComponentView::updateFocusLayoutMetrics() noexcept {
|
|
225
|
+
facebook::react::RectangleEdges<bool> nudgeEdges;
|
|
226
|
+
auto scaleFactor = m_focusPrimitive->m_focusVisualComponent->m_layoutMetrics.pointScaleFactor;
|
|
227
|
+
if (m_focusPrimitive) {
|
|
228
|
+
if (m_focusPrimitive->m_focusOuterPrimitive) {
|
|
229
|
+
auto outerFocusMetrics = m_focusPrimitive->m_focusVisualComponent->focusLayoutMetrics(false /*inner*/);
|
|
230
|
+
|
|
231
|
+
if (outerFocusMetrics.frame.origin.x < 0) {
|
|
232
|
+
nudgeEdges.left = true;
|
|
233
|
+
}
|
|
234
|
+
if (outerFocusMetrics.frame.origin.y < 0) {
|
|
235
|
+
nudgeEdges.top = true;
|
|
236
|
+
}
|
|
237
|
+
if (outerFocusMetrics.frame.getMaxX() > m_layoutMetrics.frame.getMaxX()) {
|
|
238
|
+
nudgeEdges.right = true;
|
|
239
|
+
}
|
|
240
|
+
if (outerFocusMetrics.frame.getMaxY() > m_layoutMetrics.frame.getMaxY()) {
|
|
241
|
+
nudgeEdges.bottom = true;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
m_focusPrimitive->m_focusOuterPrimitive->RootVisual().Size(
|
|
245
|
+
{outerFocusMetrics.frame.size.width * scaleFactor -
|
|
246
|
+
(nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0) -
|
|
247
|
+
(nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0),
|
|
248
|
+
outerFocusMetrics.frame.size.height * scaleFactor -
|
|
249
|
+
(nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0) -
|
|
250
|
+
(nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * 2 * scaleFactor) : 0)});
|
|
251
|
+
m_focusPrimitive->m_focusOuterPrimitive->RootVisual().Offset(
|
|
252
|
+
{nudgeEdges.left ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
|
|
253
|
+
nudgeEdges.top ? 0 : -(FOCUS_VISUAL_WIDTH * 2 * scaleFactor),
|
|
254
|
+
0.0f});
|
|
255
|
+
m_focusPrimitive->m_focusOuterPrimitive->markNeedsUpdate();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (m_focusPrimitive->m_focusInnerPrimitive) {
|
|
259
|
+
auto innerFocusMetrics = m_focusPrimitive->m_focusVisualComponent->focusLayoutMetrics(true /*inner*/);
|
|
260
|
+
m_focusPrimitive->m_focusInnerPrimitive->RootVisual().Size(
|
|
261
|
+
{innerFocusMetrics.frame.size.width * scaleFactor -
|
|
262
|
+
(nudgeEdges.left ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0) -
|
|
263
|
+
(nudgeEdges.right ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0),
|
|
264
|
+
innerFocusMetrics.frame.size.height * scaleFactor -
|
|
265
|
+
(nudgeEdges.top ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0) -
|
|
266
|
+
(nudgeEdges.bottom ? (FOCUS_VISUAL_WIDTH * scaleFactor) : 0)});
|
|
267
|
+
m_focusPrimitive->m_focusInnerPrimitive->RootVisual().Offset(
|
|
268
|
+
{nudgeEdges.left ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
|
|
269
|
+
nudgeEdges.top ? 0 : -FOCUS_VISUAL_WIDTH * scaleFactor,
|
|
270
|
+
0.0f});
|
|
271
|
+
m_focusPrimitive->m_focusInnerPrimitive->markNeedsUpdate();
|
|
272
|
+
}
|
|
241
273
|
}
|
|
242
274
|
}
|
|
243
275
|
|
|
@@ -288,13 +320,17 @@ void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentView
|
|
|
288
320
|
}
|
|
289
321
|
}
|
|
290
322
|
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
323
|
+
if (m_componentHostingFocusVisual) {
|
|
324
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive) {
|
|
325
|
+
auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
326
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusInnerPrimitive->finalize(
|
|
327
|
+
innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
328
|
+
}
|
|
329
|
+
if (m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive) {
|
|
330
|
+
auto outerFocusMetrics = focusLayoutMetrics(false /*inner*/);
|
|
331
|
+
m_componentHostingFocusVisual->m_focusPrimitive->m_focusOuterPrimitive->finalize(
|
|
332
|
+
outerFocusMetrics, focusBorderMetrics(false /*inner*/, outerFocusMetrics));
|
|
333
|
+
}
|
|
298
334
|
}
|
|
299
335
|
|
|
300
336
|
if (m_FinalizeTransform) {
|
|
@@ -308,7 +344,12 @@ void ComponentView::onLostFocus(
|
|
|
308
344
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
309
345
|
if (args.OriginalSource() == Tag()) {
|
|
310
346
|
m_eventEmitter->onBlur();
|
|
311
|
-
|
|
347
|
+
|
|
348
|
+
if (m_componentHostingFocusVisual) {
|
|
349
|
+
auto s = get_strong();
|
|
350
|
+
|
|
351
|
+
m_componentHostingFocusVisual->hostFocusVisual(false, get_strong());
|
|
352
|
+
}
|
|
312
353
|
if (m_uiaProvider) {
|
|
313
354
|
winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
|
|
314
355
|
m_uiaProvider, UIA_HasKeyboardFocusPropertyId, true, false);
|
|
@@ -317,12 +358,47 @@ void ComponentView::onLostFocus(
|
|
|
317
358
|
base_type::onLostFocus(args);
|
|
318
359
|
}
|
|
319
360
|
|
|
361
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ComponentView::visualToHostFocus() noexcept {
|
|
362
|
+
return OuterVisual();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// We want to host focus visuals as close to the focused component as possible. However since the focus visuals extend
|
|
366
|
+
// past the bounds of the component, in cases where additional components are positioned directly next to this one, we'd
|
|
367
|
+
// get zorder issues causing most of the focus rect to be obscured. So we go up the tree until we find a component who's
|
|
368
|
+
// bounds will fix the entire focus rect.
|
|
369
|
+
winrt::com_ptr<ComponentView> ComponentView::focusVisualRoot(const facebook::react::Rect &focusRect) noexcept {
|
|
370
|
+
auto compVisual =
|
|
371
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(OuterVisual());
|
|
372
|
+
if (!compVisual) {
|
|
373
|
+
return get_strong();
|
|
374
|
+
// When not using lifted composition, force the focus visual to host within its own component, as we do not support
|
|
375
|
+
// ParentForTransform
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (facebook::react::Rect::intersect(focusRect, m_layoutMetrics.frame) == focusRect) {
|
|
379
|
+
return get_strong();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (!m_parent) {
|
|
383
|
+
return get_strong();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return m_parent.as<ComponentView>()->focusVisualRoot(
|
|
387
|
+
{{focusRect.origin.x + m_layoutMetrics.frame.origin.x, focusRect.origin.y + m_layoutMetrics.frame.origin.y},
|
|
388
|
+
focusRect.size});
|
|
389
|
+
}
|
|
390
|
+
|
|
320
391
|
void ComponentView::onGotFocus(
|
|
321
392
|
const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
|
|
322
393
|
if (args.OriginalSource() == Tag()) {
|
|
323
394
|
m_eventEmitter->onFocus();
|
|
324
395
|
if (viewProps()->enableFocusRing) {
|
|
325
|
-
|
|
396
|
+
facebook::react::Rect focusRect = m_layoutMetrics.frame;
|
|
397
|
+
focusRect.origin.x -= (FOCUS_VISUAL_WIDTH * 2);
|
|
398
|
+
focusRect.origin.y -= (FOCUS_VISUAL_WIDTH * 2);
|
|
399
|
+
focusRect.size.width += (FOCUS_VISUAL_WIDTH * 2);
|
|
400
|
+
focusRect.size.height += (FOCUS_VISUAL_WIDTH * 2);
|
|
401
|
+
focusVisualRoot(focusRect)->hostFocusVisual(true, get_strong());
|
|
326
402
|
}
|
|
327
403
|
if (m_uiaProvider) {
|
|
328
404
|
auto spProviderSimple = m_uiaProvider.try_as<IRawElementProviderSimple>();
|
|
@@ -493,39 +569,70 @@ facebook::react::BorderMetrics ComponentView::focusBorderMetrics(
|
|
|
493
569
|
return metrics;
|
|
494
570
|
}
|
|
495
571
|
|
|
496
|
-
void ComponentView::
|
|
497
|
-
if ((m_flags & ComponentViewFeatures::FocusVisual) == ComponentViewFeatures::FocusVisual) {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
572
|
+
void ComponentView::hostFocusVisual(bool show, winrt::com_ptr<ComponentView> view) noexcept {
|
|
573
|
+
if ((view->m_flags & ComponentViewFeatures::FocusVisual) == ComponentViewFeatures::FocusVisual) {
|
|
574
|
+
// Any previous view showing focus visuals should have removed them before another shows it
|
|
575
|
+
assert(
|
|
576
|
+
!m_focusPrimitive || !m_focusPrimitive->m_focusVisualComponent ||
|
|
577
|
+
m_focusPrimitive->m_focusVisualComponent == view);
|
|
578
|
+
assert(
|
|
579
|
+
!m_focusPrimitive || !m_focusPrimitive->m_focusVisualComponent ||
|
|
580
|
+
view->m_componentHostingFocusVisual.get() == this);
|
|
581
|
+
if (show && !view->m_componentHostingFocusVisual) {
|
|
582
|
+
view->m_componentHostingFocusVisual = get_strong();
|
|
583
|
+
|
|
584
|
+
if (!m_focusPrimitive) {
|
|
585
|
+
m_focusPrimitive = std::make_unique<FocusPrimitive>();
|
|
506
586
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
587
|
+
m_focusPrimitive->m_focusVisualComponent = view;
|
|
588
|
+
|
|
589
|
+
if (!m_focusPrimitive->m_focusVisual) {
|
|
590
|
+
m_focusPrimitive->m_focusVisual = m_compContext.CreateSpriteVisual();
|
|
591
|
+
auto hostingVisual =
|
|
592
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
593
|
+
visualToHostFocus())
|
|
594
|
+
.as<winrt::Microsoft::UI::Composition::ContainerVisual>();
|
|
595
|
+
if (hostingVisual) {
|
|
596
|
+
hostingVisual.Children().InsertAtTop(
|
|
597
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
598
|
+
m_focusPrimitive->m_focusVisual));
|
|
599
|
+
} else {
|
|
600
|
+
assert(
|
|
601
|
+
view.get() ==
|
|
602
|
+
this); // When not using lifted comp, focus visuals should always host within their own component
|
|
603
|
+
OuterVisual().InsertAt(m_focusPrimitive->m_focusVisual, 1);
|
|
604
|
+
}
|
|
510
605
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
auto innerFocusMetrics = focusLayoutMetrics(true /*inner*/);
|
|
522
|
-
m_focusInnerPrimitive->finalize(innerFocusMetrics, focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
606
|
+
|
|
607
|
+
m_focusPrimitive->m_focusVisual.IsVisible(true);
|
|
608
|
+
assert(view->viewProps()->enableFocusRing);
|
|
609
|
+
if (!m_focusPrimitive->m_focusInnerPrimitive) {
|
|
610
|
+
m_focusPrimitive->m_focusInnerPrimitive = std::make_shared<BorderPrimitive>(*this);
|
|
611
|
+
m_focusPrimitive->m_focusVisual.InsertAt(m_focusPrimitive->m_focusInnerPrimitive->RootVisual(), 0);
|
|
612
|
+
}
|
|
613
|
+
if (!m_focusPrimitive->m_focusOuterPrimitive) {
|
|
614
|
+
m_focusPrimitive->m_focusOuterPrimitive = std::make_shared<BorderPrimitive>(*this);
|
|
615
|
+
m_focusPrimitive->m_focusVisual.InsertAt(m_focusPrimitive->m_focusOuterPrimitive->RootVisual(), 0);
|
|
523
616
|
}
|
|
524
|
-
if (
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
617
|
+
if (auto focusVisual =
|
|
618
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
619
|
+
m_focusPrimitive->m_focusVisual)) {
|
|
620
|
+
auto outerVisual =
|
|
621
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(
|
|
622
|
+
view->OuterVisual());
|
|
623
|
+
focusVisual.ParentForTransform(outerVisual);
|
|
528
624
|
}
|
|
625
|
+
updateFocusLayoutMetrics();
|
|
626
|
+
auto innerFocusMetrics = view->focusLayoutMetrics(true /*inner*/);
|
|
627
|
+
m_focusPrimitive->m_focusInnerPrimitive->finalize(
|
|
628
|
+
innerFocusMetrics, view->focusBorderMetrics(true /*inner*/, innerFocusMetrics));
|
|
629
|
+
auto outerFocusMetrics = view->focusLayoutMetrics(false /*inner*/);
|
|
630
|
+
m_focusPrimitive->m_focusOuterPrimitive->finalize(
|
|
631
|
+
outerFocusMetrics, view->focusBorderMetrics(false /*inner*/, outerFocusMetrics));
|
|
632
|
+
} else if (!show && view->m_componentHostingFocusVisual && m_focusPrimitive) {
|
|
633
|
+
m_focusPrimitive->m_focusVisualComponent = nullptr;
|
|
634
|
+
m_focusPrimitive->m_focusVisual.IsVisible(false);
|
|
635
|
+
view->m_componentHostingFocusVisual = nullptr;
|
|
529
636
|
}
|
|
530
637
|
}
|
|
531
638
|
}
|
|
@@ -685,6 +792,10 @@ void ComponentView::updateClippingPath(
|
|
|
685
792
|
}
|
|
686
793
|
}
|
|
687
794
|
|
|
795
|
+
std::pair<facebook::react::Cursor, HCURSOR> ComponentView::cursor() const noexcept {
|
|
796
|
+
return {viewProps()->cursor, nullptr};
|
|
797
|
+
}
|
|
798
|
+
|
|
688
799
|
void ComponentView::indexOffsetForBorder(uint32_t &index) const noexcept {
|
|
689
800
|
if (m_borderPrimitive) {
|
|
690
801
|
index += m_borderPrimitive->numberOfVisuals();
|
|
@@ -806,24 +917,15 @@ ViewComponentView::ViewComponentView(
|
|
|
806
917
|
const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
|
|
807
918
|
facebook::react::Tag tag,
|
|
808
919
|
winrt::Microsoft::ReactNative::ReactContext const &reactContext,
|
|
809
|
-
ComponentViewFeatures flags
|
|
810
|
-
|
|
920
|
+
ComponentViewFeatures flags,
|
|
921
|
+
winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder)
|
|
922
|
+
: base_type(compContext, tag, reactContext, flags, builder),
|
|
811
923
|
m_props(defaultProps ? defaultProps : ViewComponentView::defaultProps()) {}
|
|
812
924
|
|
|
813
925
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ViewComponentView::createVisual() noexcept {
|
|
814
926
|
return m_compContext.CreateSpriteVisual();
|
|
815
927
|
}
|
|
816
928
|
|
|
817
|
-
void ViewComponentView::CreateVisualHandler(
|
|
818
|
-
const winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate &handler) {
|
|
819
|
-
m_createVisualHandler = handler;
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate ViewComponentView::CreateVisualHandler()
|
|
823
|
-
const noexcept {
|
|
824
|
-
return m_createVisualHandler;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
929
|
void ViewComponentView::CreateInternalVisualHandler(
|
|
828
930
|
const winrt::Microsoft::ReactNative::Composition::Experimental::CreateInternalVisualDelegate &handler) {
|
|
829
931
|
m_createInternalVisualHandler = handler;
|
|
@@ -838,10 +940,10 @@ void ViewComponentView::ensureVisual() noexcept {
|
|
|
838
940
|
if (!m_visual) {
|
|
839
941
|
if (m_createInternalVisualHandler) {
|
|
840
942
|
m_visual = m_createInternalVisualHandler(*this);
|
|
841
|
-
} else if (
|
|
943
|
+
} else if (m_builder && m_builder->CreateVisualHandler()) {
|
|
842
944
|
m_visual =
|
|
843
945
|
winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::CreateVisual(
|
|
844
|
-
|
|
946
|
+
m_builder->CreateVisualHandler()(*this));
|
|
845
947
|
} else {
|
|
846
948
|
m_visual = createVisual();
|
|
847
949
|
}
|
|
@@ -859,6 +961,8 @@ winrt::Microsoft::ReactNative::ComponentView ViewComponentView::Create(
|
|
|
859
961
|
|
|
860
962
|
winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
|
|
861
963
|
ViewComponentView::VisualToMountChildrenInto() noexcept {
|
|
964
|
+
if (m_builder && m_builder->VisualToMountChildrenIntoHandler())
|
|
965
|
+
return m_builder->VisualToMountChildrenIntoHandler()(*this);
|
|
862
966
|
return Visual();
|
|
863
967
|
}
|
|
864
968
|
|
|
@@ -1106,7 +1210,7 @@ winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewProps() noexcept
|
|
|
1106
1210
|
|
|
1107
1211
|
winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewPropsInner() noexcept {
|
|
1108
1212
|
// If we have AbiViewProps, then we dont need to new up a props wrapper
|
|
1109
|
-
if (
|
|
1213
|
+
if (m_builder) {
|
|
1110
1214
|
const auto &abiViewProps = *std::static_pointer_cast<const ::Microsoft::ReactNative::AbiViewProps>(m_props);
|
|
1111
1215
|
return abiViewProps.ViewProps();
|
|
1112
1216
|
}
|