react-native-windows 0.66.3 → 0.67.0-preview.3
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/.flowconfig +2 -1
- package/CHANGELOG.json +917 -85
- package/CHANGELOG.md +352 -37
- package/Chakra/Chakra.vcxitems +0 -1
- package/Chakra/Chakra.vcxitems.filters +0 -3
- package/Chakra/ChakraHelpers.cpp +0 -267
- package/Chakra/ChakraInstanceArgs.h +0 -5
- package/Chakra/ChakraPlatform.h +0 -4
- package/Chakra/ChakraTracing.cpp +0 -33
- package/Chakra/ChakraValue.h +0 -4
- package/Chakra/Utf8DebugExtensions.cpp +0 -5
- package/Chakra/Utf8DebugExtensions.h +0 -6
- package/Libraries/ActionSheetIOS/ActionSheetIOS.js +14 -1
- package/Libraries/ActionSheetIOS/NativeActionSheetManager.js +2 -0
- package/Libraries/Alert/Alert.windows.js +48 -21
- package/Libraries/Alert/NativeDialogManagerWindows.js +49 -0
- package/Libraries/Animated/AnimatedEvent.js +23 -4
- package/Libraries/Animated/NativeAnimatedHelper.js +2 -2
- package/Libraries/Animated/components/AnimatedImage.js +3 -3
- package/Libraries/Animated/components/AnimatedScrollView.js +3 -3
- package/Libraries/Animated/components/AnimatedText.js +3 -3
- package/Libraries/Animated/components/AnimatedView.js +1 -3
- package/Libraries/Animated/createAnimatedComponent.js +3 -34
- package/Libraries/Components/Button.js +3 -0
- package/Libraries/Components/Button.windows.js +70 -38
- package/Libraries/Components/DatePicker/DatePickerIOS.ios.js +3 -6
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +4 -7
- package/Libraries/Components/Flyout/Flyout.js +3 -3
- package/Libraries/Components/Flyout/Flyout.js.map +1 -1
- package/Libraries/Components/Flyout/FlyoutProps.d.ts +4 -0
- package/Libraries/Components/Flyout/FlyoutProps.js.map +1 -1
- package/Libraries/Components/Glyph/Glyph.js +2 -2
- package/Libraries/Components/Glyph/Glyph.js.map +1 -1
- package/Libraries/Components/Keyboard/KeyboardExt.js +4 -3
- package/Libraries/Components/Keyboard/KeyboardExt.js.map +1 -1
- package/Libraries/Components/Popup/Popup.js +3 -3
- package/Libraries/Components/Popup/Popup.js.map +1 -1
- package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +1 -0
- package/Libraries/Components/ScrollView/ScrollView.js +17 -16
- package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +268 -252
- package/Libraries/Components/View/View.js +1 -1
- package/Libraries/Components/View/View.windows.js +1 -1
- package/Libraries/Components/View/ViewAccessibility.js +1 -1
- package/Libraries/Components/View/ViewAccessibility.windows.js +1 -1
- package/Libraries/Components/View/ViewWindows.js +1 -1
- package/Libraries/Components/View/ViewWindows.js.map +1 -1
- package/Libraries/Components/View/ViewWindowsProps.d.ts +42 -2
- package/Libraries/Components/View/ViewWindowsProps.js.map +1 -1
- package/Libraries/Core/ExceptionsManager.js +45 -80
- package/Libraries/Core/ExtendedError.js +0 -1
- package/Libraries/Core/ReactNativeVersion.js +2 -2
- package/Libraries/Core/setUpBatchedBridge.js +1 -1
- package/Libraries/Core/setUpGlobals.js +2 -4
- package/Libraries/Core/setUpTimers.js +2 -2
- package/Libraries/Image/Image.ios.js +6 -0
- package/Libraries/Image/Image.windows.js +6 -0
- package/Libraries/Image/ImageBackground.js +10 -8
- package/Libraries/Image/ImageProps.js +28 -0
- package/Libraries/LogBox/Data/LogBoxData.js +18 -19
- package/Libraries/LogBox/UI/LogBoxImages/alert-triangle.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/chevron-left.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/chevron-right.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/close.png +0 -0
- package/Libraries/LogBox/UI/LogBoxImages/loader.png +0 -0
- package/Libraries/NewAppScreen/components/logo.png +0 -0
- package/Libraries/PermissionsAndroid/NativePermissionsAndroid.js +2 -1
- package/Libraries/PermissionsAndroid/PermissionsAndroid.js +2 -0
- package/Libraries/Pressability/Pressability.js +13 -13
- package/Libraries/Pressability/Pressability.windows.js +13 -13
- package/Libraries/Pressability/PressabilityPerformanceEventEmitter.js +1 -1
- package/Libraries/ReactNative/AppRegistry.js +4 -2
- package/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +1569 -875
- package/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +529 -319
- package/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +570 -362
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +1592 -891
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +521 -311
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +562 -354
- package/Libraries/Share/Share.js +1 -1
- package/Libraries/StyleSheet/normalizeColor.js +2 -2
- package/Libraries/Text/Text.windows.js +1 -0
- package/Libraries/Text/TextNativeComponent.windows.js +72 -0
- package/Libraries/Text/TextProps.js +1 -7
- package/Libraries/TurboModule/TurboModuleRegistry.js +1 -1
- package/Libraries/Utilities/HMRClient.js +1 -1
- package/Microsoft.ReactNative/ABIViewManager.cpp +10 -1
- package/Microsoft.ReactNative/ABIViewManager.h +3 -0
- package/Microsoft.ReactNative/Base/CoreNativeModules.cpp +0 -6
- package/Microsoft.ReactNative/IReactDispatcher.cpp +16 -1
- package/Microsoft.ReactNative/IViewManager.idl +25 -0
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +35 -8
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +60 -0
- package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +3 -4
- package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.h +3 -3
- package/Microsoft.ReactNative/Modules/AlertModule.cpp +57 -14
- package/Microsoft.ReactNative/Modules/AlertModule.h +17 -24
- package/Microsoft.ReactNative/Modules/Animated/InterpolationAnimatedNode.cpp +4 -2
- package/Microsoft.ReactNative/Modules/Animated/PropsAnimatedNode.cpp +3 -1
- package/Microsoft.ReactNative/Modules/AppStateModule.cpp +8 -6
- package/Microsoft.ReactNative/Modules/AppStateModule.h +6 -9
- package/Microsoft.ReactNative/Modules/DeviceInfoModule.cpp +34 -22
- package/Microsoft.ReactNative/Modules/DeviceInfoModule.h +8 -4
- package/Microsoft.ReactNative/Modules/I18nManagerModule.cpp +6 -4
- package/Microsoft.ReactNative/Modules/I18nManagerModule.h +3 -2
- package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +47 -95
- package/Microsoft.ReactNative/Modules/ImageViewManagerModule.h +28 -17
- package/Microsoft.ReactNative/Modules/LinkingManagerModule.cpp +14 -4
- package/Microsoft.ReactNative/Modules/NativeUIManager.cpp +1 -1
- package/Microsoft.ReactNative/Modules/PaperUIManagerModule.cpp +82 -66
- package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +14 -1
- package/Microsoft.ReactNative/ReactInstanceSettings.idl +3 -1
- package/Microsoft.ReactNative/ReactPointerEventArgs.cpp +37 -0
- package/Microsoft.ReactNative/ReactPointerEventArgs.h +28 -0
- package/Microsoft.ReactNative/ReactPointerEventArgs.idl +67 -0
- package/Microsoft.ReactNative/Utils/TextTransform.h +1 -1
- package/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp +24 -10
- package/Microsoft.ReactNative/Utils/XamlIslandUtils.h +4 -2
- package/Microsoft.ReactNative/Version.rc +2 -19
- package/Microsoft.ReactNative/Views/FlyoutViewManager.cpp +57 -2
- package/Microsoft.ReactNative/Views/FrameworkElementTransferProperties.cpp +3 -0
- package/Microsoft.ReactNative/Views/FrameworkElementViewManager.cpp +7 -2
- package/Microsoft.ReactNative/Views/Image/ImageViewManager.cpp +16 -6
- package/Microsoft.ReactNative/Views/Image/ReactImage.cpp +18 -11
- package/Microsoft.ReactNative/Views/Image/ReactImage.h +3 -1
- package/Microsoft.ReactNative/Views/RawTextViewManager.cpp +4 -53
- package/Microsoft.ReactNative/Views/RawTextViewManager.h +0 -3
- package/Microsoft.ReactNative/Views/ShadowNodeBase.h +5 -0
- package/Microsoft.ReactNative/Views/Text/TextHighlighterVisitor.cpp +52 -0
- package/Microsoft.ReactNative/Views/Text/TextHighlighterVisitor.h +37 -0
- package/Microsoft.ReactNative/Views/Text/TextHitTestUtils.cpp +343 -0
- package/Microsoft.ReactNative/Views/Text/TextHitTestUtils.h +13 -0
- package/Microsoft.ReactNative/Views/Text/TextHitTestVisitor.cpp +76 -0
- package/Microsoft.ReactNative/Views/Text/TextHitTestVisitor.h +32 -0
- package/Microsoft.ReactNative/Views/Text/TextParentVisitor.cpp +12 -0
- package/Microsoft.ReactNative/Views/Text/TextParentVisitor.h +19 -0
- package/Microsoft.ReactNative/Views/Text/TextPropertyChangedParentVisitor.cpp +80 -0
- package/Microsoft.ReactNative/Views/Text/TextPropertyChangedParentVisitor.h +43 -0
- package/Microsoft.ReactNative/Views/Text/TextTransformParentVisitor.cpp +21 -0
- package/Microsoft.ReactNative/Views/Text/TextTransformParentVisitor.h +23 -0
- package/Microsoft.ReactNative/Views/Text/TextTransformVisitor.cpp +70 -0
- package/Microsoft.ReactNative/Views/Text/TextTransformVisitor.h +34 -0
- package/Microsoft.ReactNative/Views/Text/TextVisitor.cpp +56 -0
- package/Microsoft.ReactNative/Views/Text/TextVisitor.h +34 -0
- package/Microsoft.ReactNative/Views/Text/TextVisitorScope.h +35 -0
- package/Microsoft.ReactNative/Views/Text/TextVisitors.h +47 -0
- package/Microsoft.ReactNative/Views/TextViewManager.cpp +112 -103
- package/Microsoft.ReactNative/Views/TextViewManager.h +6 -12
- package/Microsoft.ReactNative/Views/TouchEventHandler.cpp +171 -129
- package/Microsoft.ReactNative/Views/TouchEventHandler.h +19 -15
- package/Microsoft.ReactNative/Views/ViewManagerBase.cpp +31 -0
- package/Microsoft.ReactNative/Views/ViewManagerBase.h +2 -0
- package/Microsoft.ReactNative/Views/ViewViewManager.cpp +0 -5
- package/Microsoft.ReactNative/Views/VirtualTextViewManager.cpp +21 -91
- package/Microsoft.ReactNative/Views/VirtualTextViewManager.h +5 -8
- package/Microsoft.ReactNative/XamlView.h +3 -3
- package/Microsoft.ReactNative/packages.config +1 -1
- package/Microsoft.ReactNative.Cxx/NativeModules.h +114 -0
- package/Microsoft.ReactNative.Cxx/VersionMacros.h +19 -0
- package/PropertySheets/External/Microsoft.ReactNative.Common.props +2 -0
- package/PropertySheets/External/Microsoft.ReactNative.Uwp.CppApp.props +1 -0
- package/PropertySheets/External/Microsoft.ReactNative.Uwp.CppLib.props +1 -0
- package/PropertySheets/Generated/PackageVersion.g.props +19 -0
- package/PropertySheets/PackageVersionDefinitions.props +28 -0
- package/PropertySheets/React.Cpp.props +2 -0
- package/PropertySheets/WinUI.props +1 -1
- package/Scripts/Microsoft.ReactNative.Managed.nuspec +1 -1
- package/Scripts/copyRNLibraries.js +12 -0
- package/Scripts/rnw-dependencies.ps1 +25 -24
- package/Shared/HermesSamplingProfiler.cpp +3 -21
- package/Shared/JSI/ChakraApi.cpp +1 -37
- package/Shared/JSI/ChakraApi.h +0 -4
- package/Shared/JSI/ChakraJsiRuntime_edgemode.cpp +1 -5
- package/Shared/JSI/ChakraRuntime.cpp +0 -12
- package/Shared/JSI/ChakraRuntimeFactory.h +0 -2
- package/Shared/Modules/PlatformConstantsModule.cpp +1 -15
- package/Shared/OInstance.cpp +6 -19
- package/Shared/Shared.vcxitems +0 -1
- package/Shared/Shared.vcxitems.filters +0 -3
- package/Shared/Utils.cpp +58 -0
- package/Shared/Utils.h +3 -0
- package/codegen/NativeAccessibilityInfoSpec.g.h +9 -9
- package/codegen/NativeAccessibilityManagerSpec.g.h +49 -21
- package/codegen/NativeActionSheetManagerSpec.g.h +62 -6
- package/codegen/NativeAlertManagerSpec.g.h +4 -4
- package/codegen/NativeAnimatedModuleSpec.g.h +10 -10
- package/codegen/NativeAnimatedTurboModuleSpec.g.h +10 -10
- package/codegen/NativeAppStateSpec.g.h +25 -3
- package/codegen/NativeAppearanceSpec.g.h +3 -3
- package/codegen/NativeAsyncLocalStorageSpec.g.h +66 -18
- package/codegen/NativeAsyncSQLiteDBStorageSpec.g.h +66 -18
- package/codegen/NativeBlobModuleSpec.g.h +24 -6
- package/codegen/NativeBugReportingSpec.g.h +3 -3
- package/codegen/NativeDatePickerAndroidSpec.g.h +3 -3
- package/codegen/NativeDevLoadingViewSpec.g.h +3 -3
- package/codegen/NativeDeviceInfoSpec.g.h +18 -0
- package/codegen/NativeDialogManagerAndroidSpec.g.h +28 -4
- package/codegen/NativeDialogManagerWindowsSpec.g.h +77 -0
- package/codegen/NativeExceptionsManagerSpec.g.h +11 -11
- package/codegen/NativeFileReaderModuleSpec.g.h +6 -6
- package/codegen/NativeFrameRateLoggerSpec.g.h +11 -3
- package/codegen/NativeI18nManagerSpec.g.h +20 -0
- package/codegen/NativeImageEditorSpec.g.h +30 -6
- package/codegen/NativeImageLoaderAndroidSpec.g.h +6 -6
- package/codegen/NativeImageLoaderIOSSpec.g.h +6 -6
- package/codegen/NativeImagePickerIOSSpec.g.h +28 -12
- package/codegen/NativeImageStoreAndroidSpec.g.h +3 -3
- package/codegen/NativeImageStoreIOSSpec.g.h +21 -9
- package/codegen/NativeIntentAndroidSpec.g.h +3 -3
- package/codegen/NativeJSCHeapCaptureSpec.g.h +3 -3
- package/codegen/NativeJSCSamplingProfilerSpec.g.h +3 -3
- package/codegen/NativeJSDevSupportSpec.g.h +18 -0
- package/codegen/NativeNetworkingAndroidSpec.g.h +6 -6
- package/codegen/NativeNetworkingIOSSpec.g.h +26 -6
- package/codegen/NativePermissionsAndroidSpec.g.h +3 -3
- package/codegen/NativePlatformConstantsAndroidSpec.g.h +48 -0
- package/codegen/NativePlatformConstantsIOSSpec.g.h +38 -0
- package/codegen/NativePlatformConstantsWinSpec.g.h +32 -0
- package/codegen/NativePushNotificationManagerIOSSpec.g.h +35 -25
- package/codegen/NativeRedBoxSpec.g.h +3 -3
- package/codegen/NativeSampleTurboModuleSpec.g.h +32 -12
- package/codegen/NativeSegmentFetcherSpec.g.h +6 -6
- package/codegen/NativeSettingsManagerSpec.g.h +22 -6
- package/codegen/NativeShareModuleSpec.g.h +11 -3
- package/codegen/NativeSourceCodeSpec.g.h +16 -0
- package/codegen/NativeStatusBarManagerAndroidSpec.g.h +21 -3
- package/codegen/NativeStatusBarManagerIOSSpec.g.h +30 -6
- package/codegen/NativeToastAndroidSpec.g.h +24 -0
- package/codegen/NativeUIManagerSpec.g.h +63 -63
- package/codegen/NativeVibrationSpec.g.h +3 -3
- package/codegen/NativeWebSocketModuleSpec.g.h +9 -3
- package/index.js +15 -10
- package/index.windows.js +15 -10
- package/jest/mockModal.js +31 -0
- package/jest/setup.js +5 -3
- package/just-task.js +2 -1
- package/package.json +23 -20
- package/rntypes/BatchedBridge.d.ts +23 -0
- package/rntypes/Devtools.d.ts +20 -0
- package/rntypes/LaunchScreen.d.ts +9 -0
- package/rntypes/globals.d.ts +496 -0
- package/rntypes/index.d.ts +9966 -0
- package/rntypes/legacy-properties.d.ts +266 -0
- package/template/cpp-app/proj/MyApp.vcxproj +0 -5
- package/template/cpp-app/src/pch.h +1 -0
- package/template/cpp-lib/src/pch.h +3 -0
- package/template/cs-app/proj/MyApp.csproj +0 -6
- package/typings-index.d.ts +2 -1
- package/typings-index.js +7 -5
- package/typings-index.js.map +1 -1
- package/Chakra/ChakraCoreDebugger.h +0 -147
- package/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js +0 -87
- package/Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js +0 -30
- package/Libraries/Components/DatePickerAndroid/DatePickerAndroid.windows.js +0 -30
- package/Libraries/Components/DatePickerAndroid/DatePickerAndroidTypes.js +0 -30
- package/Libraries/Components/StaticContainer.react.js +0 -51
- package/Libraries/Components/Touchable/ensurePositiveDelayProps.js +0 -25
- package/Libraries/Interaction/InteractionMixin.js +0 -54
- package/Libraries/ReactNative/queryLayoutByID.js +0 -58
- package/Scripts/Microsoft.ChakraCore.ARM64.nuspec +0 -50
- package/Scripts/Microsoft.ChakraCore.ARM64.targets +0 -15
- package/Shared/JSI/ChakraCoreRuntime.h +0 -59
- package/template/cpp-app/keys/MyApp_TemporaryKey.pfx +0 -0
- package/template/cs-app/keys/MyApp_TemporaryKey.pfx +0 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#include "pch.h"
|
|
5
|
+
|
|
6
|
+
#include "TextHitTestUtils.h"
|
|
7
|
+
|
|
8
|
+
#include <UI.Xaml.Documents.h>
|
|
9
|
+
#include <math.h>
|
|
10
|
+
|
|
11
|
+
namespace Microsoft::ReactNative {
|
|
12
|
+
|
|
13
|
+
struct BidirectionalTextBoundary {
|
|
14
|
+
xaml::Documents::TextPointer ltrPointer{nullptr};
|
|
15
|
+
xaml::Documents::TextPointer rtlPointer{nullptr};
|
|
16
|
+
winrt::Rect ltrRect;
|
|
17
|
+
winrt::Rect rtlRect;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* Checks if two text pointers are on the same line.
|
|
22
|
+
*/
|
|
23
|
+
static bool IsSameLine(const winrt::Rect &x, const winrt::Rect &y) {
|
|
24
|
+
return std::abs(x.Y - y.Y) <= std::numeric_limits<float>().epsilon();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/*
|
|
28
|
+
* Checks if a text pointer is zero width relative to the next character.
|
|
29
|
+
*/
|
|
30
|
+
static bool IsZeroWidth(const winrt::Rect &x, const winrt::Rect &y) {
|
|
31
|
+
return std::abs(x.X - y.X) <= std::numeric_limits<float>().epsilon();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Finds the character closest to X = 0 for the first line. I.e., the
|
|
36
|
+
* leftmost character when flow direction is left-to-right.
|
|
37
|
+
* ┌─────> X ↓
|
|
38
|
+
* │ (x,y) ┌─<─┐<┌─>─┐
|
|
39
|
+
* │ ┌──────┘ └─┘ │
|
|
40
|
+
* │ │ │
|
|
41
|
+
* ↓ │ ┌──────────┘
|
|
42
|
+
* Y └─────┘
|
|
43
|
+
*/
|
|
44
|
+
static BidirectionalTextBoundary FindStartRTLBoundary(
|
|
45
|
+
const xaml::Documents::TextPointer &start,
|
|
46
|
+
const xaml::Documents::TextPointer &end,
|
|
47
|
+
const winrt::Rect &target) {
|
|
48
|
+
auto textPointer = start;
|
|
49
|
+
auto L = start.Offset();
|
|
50
|
+
auto R = end.Offset();
|
|
51
|
+
while (L <= R) {
|
|
52
|
+
const auto m = /* floor */ (L + R) / 2;
|
|
53
|
+
const auto relativeOffset = m - textPointer.Offset();
|
|
54
|
+
textPointer = textPointer.GetPositionAtOffset(relativeOffset, xaml::Documents::LogicalDirection::Forward);
|
|
55
|
+
const auto rect = textPointer.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
56
|
+
// If median character is on different line, boundary is before median
|
|
57
|
+
if (!IsSameLine(rect, target)) {
|
|
58
|
+
R = m - 1;
|
|
59
|
+
} else {
|
|
60
|
+
const auto prevPointer = textPointer.GetPositionAtOffset(-1, xaml::Documents::LogicalDirection::Forward);
|
|
61
|
+
const auto prevRect = prevPointer.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
62
|
+
if (prevRect.X > target.X) {
|
|
63
|
+
// If previous character is right of start, boundary is before median
|
|
64
|
+
R = m - 1;
|
|
65
|
+
} else if (rect.X <= target.X) {
|
|
66
|
+
// If median character is left of start, boundary is after median
|
|
67
|
+
L = m + 1;
|
|
68
|
+
} else {
|
|
69
|
+
// Otherwise, we've found the boundary where the previous character is
|
|
70
|
+
// the last RTL character and the median is the first LTR character
|
|
71
|
+
BidirectionalTextBoundary result;
|
|
72
|
+
result.rtlPointer = prevPointer;
|
|
73
|
+
result.rtlRect = prevRect;
|
|
74
|
+
result.ltrPointer = textPointer;
|
|
75
|
+
result.ltrRect = rect;
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// No LTR characters on first line, R points to last character on first line
|
|
82
|
+
auto lastRTL = start;
|
|
83
|
+
auto lastRTLRect = target;
|
|
84
|
+
if (R > start.Offset()) {
|
|
85
|
+
const auto relativeOffset = R - start.Offset();
|
|
86
|
+
lastRTL = start.GetPositionAtOffset(relativeOffset, xaml::Documents::LogicalDirection::Forward);
|
|
87
|
+
lastRTLRect = lastRTL.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
BidirectionalTextBoundary result;
|
|
91
|
+
result.rtlPointer = lastRTL;
|
|
92
|
+
result.rtlRect = lastRTLRect;
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Finds the character farthest from X = 0 for the last line. I.e., the
|
|
98
|
+
* rightmost character when flow direction is left-to-right.
|
|
99
|
+
* ┌─────> X
|
|
100
|
+
* │ (x,y) ┌──────┐
|
|
101
|
+
* │ ┌─────┘ │
|
|
102
|
+
* │ │ │
|
|
103
|
+
* ↓ │ ┌─┐ ┌──┘
|
|
104
|
+
* Y └─>─┘<└─<─┘
|
|
105
|
+
* ↑
|
|
106
|
+
*/
|
|
107
|
+
static BidirectionalTextBoundary FindEndRTLBoundary(
|
|
108
|
+
const xaml::Documents::TextPointer &start,
|
|
109
|
+
const xaml::Documents::TextPointer &end,
|
|
110
|
+
const winrt::Rect &target) {
|
|
111
|
+
auto textPointer = start;
|
|
112
|
+
auto L = start.Offset();
|
|
113
|
+
auto R = end.Offset();
|
|
114
|
+
while (L <= R) {
|
|
115
|
+
const auto m = /* floor */ (L + R) / 2;
|
|
116
|
+
const auto relativeOffset = m - textPointer.Offset();
|
|
117
|
+
textPointer = textPointer.GetPositionAtOffset(relativeOffset, xaml::Documents::LogicalDirection::Forward);
|
|
118
|
+
const auto rect = textPointer.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
119
|
+
// If median character is on different line, boundary is after median
|
|
120
|
+
if (!IsSameLine(rect, target)) {
|
|
121
|
+
L = m + 1;
|
|
122
|
+
} else if (m < R) {
|
|
123
|
+
const auto nextPointer = textPointer.GetPositionAtOffset(1, xaml::Documents::LogicalDirection::Forward);
|
|
124
|
+
const auto nextRect = nextPointer.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
125
|
+
if (nextRect.X < target.X) {
|
|
126
|
+
// If next character is left of end, boundary is after median
|
|
127
|
+
L = m + 1;
|
|
128
|
+
} else if (rect.X >= target.X) {
|
|
129
|
+
// If median character is right of end, boundary is before median
|
|
130
|
+
R = m - 1;
|
|
131
|
+
} else {
|
|
132
|
+
// Otherwise, we've found the boundary where the next character is the
|
|
133
|
+
// first RTL character and the median is the last LTR character
|
|
134
|
+
BidirectionalTextBoundary result;
|
|
135
|
+
result.rtlPointer = nextPointer;
|
|
136
|
+
result.rtlRect = nextRect;
|
|
137
|
+
result.ltrPointer = textPointer;
|
|
138
|
+
result.ltrRect = rect;
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// No LTR characters on last line, L points to first character on last line
|
|
147
|
+
auto lastRTL = end;
|
|
148
|
+
auto lastRTLRect = target;
|
|
149
|
+
if (L < end.Offset()) {
|
|
150
|
+
const auto relativeOffset = L - end.Offset();
|
|
151
|
+
lastRTL = end.GetPositionAtOffset(relativeOffset, xaml::Documents::LogicalDirection::Forward);
|
|
152
|
+
lastRTLRect = lastRTL.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
BidirectionalTextBoundary result;
|
|
156
|
+
result.rtlPointer = lastRTL;
|
|
157
|
+
result.rtlRect = lastRTLRect;
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Determine if the next character in the given direction on the same line is
|
|
163
|
+
* RTL. If the next character is not on the same line, assume LTR. This may be
|
|
164
|
+
* The case if the run has only one character on the target line.
|
|
165
|
+
*/
|
|
166
|
+
static bool IsRTL(const xaml::Documents::TextPointer &textPointer, const winrt::Rect &rect, int direction) {
|
|
167
|
+
auto currentPointer = textPointer.GetPositionAtOffset(direction, xaml::Documents::LogicalDirection::Forward);
|
|
168
|
+
while (currentPointer != nullptr) {
|
|
169
|
+
const auto currentRect = currentPointer.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
170
|
+
if (!IsSameLine(currentRect, rect)) {
|
|
171
|
+
return false;
|
|
172
|
+
} else if (!IsZeroWidth(currentRect, rect)) {
|
|
173
|
+
return direction > 0 ? currentRect.X < rect.X : currentRect.X > rect.X;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
currentPointer = currentPointer.GetPositionAtOffset(direction, xaml::Documents::LogicalDirection::Forward);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Determine if the character is either the first or last character of a line in the given direction.
|
|
184
|
+
*/
|
|
185
|
+
static std::optional<winrt::Rect>
|
|
186
|
+
GetBoundaryCharacter(const xaml::Documents::TextPointer &textPointer, const winrt::Rect &rect, int direction) {
|
|
187
|
+
const auto nextPosition = textPointer.GetPositionAtOffset(direction, xaml::Documents::LogicalDirection::Forward);
|
|
188
|
+
if (nextPosition) {
|
|
189
|
+
const auto nextRect = nextPosition.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
190
|
+
if (IsSameLine(nextRect, rect)) {
|
|
191
|
+
return nextRect;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return std::nullopt;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
bool IsInBounds(const winrt::Point &point, float left, float right, float top, float bottom) {
|
|
199
|
+
return left <= point.X && right >= point.X && top <= point.Y && bottom >= point.Y;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
bool TextHitTestUtils::HitTest(const xaml::Documents::Run &run, const winrt::Point &targetPoint) {
|
|
203
|
+
const auto start = run.ContentStart();
|
|
204
|
+
const auto end = run.ContentEnd();
|
|
205
|
+
const auto startRect = start.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
206
|
+
const auto endRect = end.GetCharacterRect(xaml::Documents::LogicalDirection::Forward);
|
|
207
|
+
|
|
208
|
+
// Get first and last line vertical bounds
|
|
209
|
+
const auto startTop = startRect.Y;
|
|
210
|
+
const auto startBottom = startRect.Y + startRect.Height;
|
|
211
|
+
const auto endTop = endRect.Y;
|
|
212
|
+
const auto endBottom = endRect.Y + endRect.Height;
|
|
213
|
+
|
|
214
|
+
// Check if we have a single line of unidirectional text
|
|
215
|
+
const auto isSingleLine = IsSameLine(startRect, endRect);
|
|
216
|
+
const auto isStartRTL = IsRTL(start, startRect, 1);
|
|
217
|
+
const auto isEndRTL = IsRTL(end, endRect, -1);
|
|
218
|
+
const auto isUnidirectional = (!isStartRTL && !isEndRTL) || (isSingleLine && endRect.X < startRect.X);
|
|
219
|
+
|
|
220
|
+
// For unidirectional runs on the same line, we can use a simple bounding box test
|
|
221
|
+
if (isSingleLine && isUnidirectional) {
|
|
222
|
+
return endRect.X < startRect.X
|
|
223
|
+
? IsInBounds(targetPoint, endRect.X + endRect.Width, startRect.X, startTop, startBottom)
|
|
224
|
+
: IsInBounds(targetPoint, startRect.X, endRect.X + endRect.Width, startTop, startBottom);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// If we don't have a single line of unidirectional text, we need to search
|
|
228
|
+
// up to 5 bounding boxes for the target point:
|
|
229
|
+
// 1. The lines between the first and last lines
|
|
230
|
+
// 2. The LTR characters on the first line after initial RTL
|
|
231
|
+
// 3. The LTR characters on the last line before final RTL
|
|
232
|
+
// 4. The initial RTL characters on the first line
|
|
233
|
+
// 5. The final RTL characters on the last line
|
|
234
|
+
//
|
|
235
|
+
// We can optimize the following situations:
|
|
236
|
+
// a. Skip step 2 if no LTR characters on the first line
|
|
237
|
+
// b. Skip step 3 if no LTR characters on the last line
|
|
238
|
+
// c. Skip step 4 if the first character is LTR
|
|
239
|
+
// d. Skip step 5 if the last character is LTR
|
|
240
|
+
|
|
241
|
+
// Get the parent bounds
|
|
242
|
+
const auto maxLeft = 0;
|
|
243
|
+
const auto maxRight = static_cast<float>(start.VisualParent().Width());
|
|
244
|
+
|
|
245
|
+
// Check if run is either the start or end of a line
|
|
246
|
+
const auto characterBeforeStart = GetBoundaryCharacter(start, startRect, -1);
|
|
247
|
+
const auto characterAfterEnd = GetBoundaryCharacter(end, endRect, 1);
|
|
248
|
+
|
|
249
|
+
// Find leftmost character of the first line and first LTR character
|
|
250
|
+
BidirectionalTextBoundary startBoundary;
|
|
251
|
+
startBoundary.ltrPointer = start;
|
|
252
|
+
startBoundary.ltrRect = startRect;
|
|
253
|
+
if (isStartRTL) {
|
|
254
|
+
startBoundary = FindStartRTLBoundary(start, end, startRect);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Find rightmost character of the last line and last LTR character
|
|
258
|
+
BidirectionalTextBoundary endBoundary;
|
|
259
|
+
endBoundary.ltrPointer = end;
|
|
260
|
+
endBoundary.ltrRect = endRect;
|
|
261
|
+
if (isEndRTL) {
|
|
262
|
+
endBoundary = FindEndRTLBoundary(start, end, endRect);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Step 1: The lines between the first and last lines
|
|
266
|
+
const auto middleTop = startBottom;
|
|
267
|
+
const auto middleBottom = endRect.Y;
|
|
268
|
+
if (middleTop <= targetPoint.Y && middleBottom >= targetPoint.Y) {
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Step 2: The LTR characters on the first line before initial RTL
|
|
273
|
+
// Optimization b: Skip if no LTR characters in first line
|
|
274
|
+
if (startBoundary.ltrPointer) {
|
|
275
|
+
auto left = startBoundary.ltrRect.X;
|
|
276
|
+
if (!characterBeforeStart.has_value()) {
|
|
277
|
+
left = maxLeft;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
auto right = maxRight;
|
|
281
|
+
if (isSingleLine && characterAfterEnd.has_value()) {
|
|
282
|
+
// TODO(#7792): last LTR character is ignored because width is always 0
|
|
283
|
+
right = endBoundary.ltrRect.X + endBoundary.ltrRect.Width;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (IsInBounds(targetPoint, left, right, startTop, startBottom)) {
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Step 3: The LTR characters on the last line after final RTL
|
|
292
|
+
// Optimization b: Skip if no LTR characters in last line
|
|
293
|
+
if (!isSingleLine && endBoundary.ltrPointer) {
|
|
294
|
+
const auto left = 0;
|
|
295
|
+
// TODO(#7792): last LTR character is ignored because width is always 0
|
|
296
|
+
auto right = endBoundary.ltrRect.X + endBoundary.ltrRect.Width;
|
|
297
|
+
if (!characterAfterEnd.has_value()) {
|
|
298
|
+
right = maxRight;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (IsInBounds(targetPoint, left, right, endTop, endBottom)) {
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Step 4: The initial RTL characters on the first line
|
|
307
|
+
// Optimization c: Skip if first line starts with LTR
|
|
308
|
+
if (isStartRTL) {
|
|
309
|
+
// TODO(#7792): last RTL character is ignored because width is always 0
|
|
310
|
+
auto left = startBoundary.rtlRect.X + startBoundary.rtlRect.Width;
|
|
311
|
+
if (!characterBeforeStart.has_value()) {
|
|
312
|
+
left = maxLeft;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
auto right = maxRight;
|
|
316
|
+
if (isSingleLine) {
|
|
317
|
+
right = startRect.X;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (IsInBounds(targetPoint, left, right, startTop, startBottom)) {
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Step 5: The final RTL characters on the last line
|
|
326
|
+
// Optimization d: Skip if last line ends with LTR
|
|
327
|
+
if (isEndRTL) {
|
|
328
|
+
// TODO(#7792): last RTL character is ignored because width is always 0
|
|
329
|
+
const auto left = endRect.X + endRect.Width;
|
|
330
|
+
auto right = endBoundary.rtlRect.X;
|
|
331
|
+
if (!characterAfterEnd.has_value()) {
|
|
332
|
+
right = maxRight;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (IsInBounds(targetPoint, left, right, endTop, endBottom)) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <UI.Xaml.Controls.h>
|
|
7
|
+
#include <UI.Xaml.Documents.h>
|
|
8
|
+
|
|
9
|
+
namespace Microsoft::ReactNative {
|
|
10
|
+
struct TextHitTestUtils final {
|
|
11
|
+
static bool HitTest(const xaml::Documents::Run &run, const winrt::Point &targetPoint);
|
|
12
|
+
};
|
|
13
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#include "TextHitTestVisitor.h"
|
|
5
|
+
#include <Views/VirtualTextViewManager.h>
|
|
6
|
+
#include "TextHitTestUtils.h"
|
|
7
|
+
|
|
8
|
+
namespace winrt {
|
|
9
|
+
using namespace xaml::Documents;
|
|
10
|
+
} // namespace winrt
|
|
11
|
+
|
|
12
|
+
namespace Microsoft::ReactNative {
|
|
13
|
+
|
|
14
|
+
void TextHitTestVisitor::VisitCore(ShadowNodeBase *node) {
|
|
15
|
+
for (auto childTag : node->m_children) {
|
|
16
|
+
Visit(GetShadowNode(childTag));
|
|
17
|
+
|
|
18
|
+
// Stop recursion if we found the target
|
|
19
|
+
if (m_targetFound) {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void TextHitTestVisitor::VisitRawText(ShadowNodeBase *node) {
|
|
26
|
+
// Only hit test the raw text if there is a pressable ancestor
|
|
27
|
+
if (m_hasPressableAncestor) {
|
|
28
|
+
const auto run = node->GetView().as<winrt::Run>();
|
|
29
|
+
if (TextHitTestUtils::HitTest(run, m_point)) {
|
|
30
|
+
m_targetFound = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void TextHitTestVisitor::VisitVirtualText(ShadowNodeBase *node) {
|
|
36
|
+
const auto textNode = static_cast<VirtualTextShadowNode *>(node);
|
|
37
|
+
|
|
38
|
+
// Update pressable count and set pressable ancestor flag
|
|
39
|
+
const auto hadPressableAncestor = m_hasPressableAncestor;
|
|
40
|
+
if (textNode->isPressable) {
|
|
41
|
+
m_pressableCount++;
|
|
42
|
+
m_hasPressableAncestor = true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Capture initial count to determine if node still has pressable descendants
|
|
46
|
+
const auto initialCount = m_pressableCount;
|
|
47
|
+
|
|
48
|
+
// Continue recursion if there is a pressable descendant or ancestor
|
|
49
|
+
if (textNode->hasDescendantPressable || m_hasPressableAncestor) {
|
|
50
|
+
// Visit children
|
|
51
|
+
Super::VisitVirtualText(node);
|
|
52
|
+
|
|
53
|
+
// Reset pressable descendant state if descendants are no longer pressable
|
|
54
|
+
if (m_pressableCount == initialCount) {
|
|
55
|
+
textNode->hasDescendantPressable = false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// If the target is null after target was found, set the target to the
|
|
59
|
+
// current view. This will set the target to the first virtual text
|
|
60
|
+
// ancestor of the target raw text node as well as handle when a descendant
|
|
61
|
+
// view manager sets `pointerEvents` to "none" or "box-none".
|
|
62
|
+
if (m_targetFound && !m_args.Target()) {
|
|
63
|
+
m_args.Target(node->GetView());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Invoke view manager OnPointerEvent method for `pointerEvents` behavior
|
|
67
|
+
if (m_args.Target()) {
|
|
68
|
+
node->GetViewManager()->OnPointerEvent(node, m_args);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Reset pressable ancestor state
|
|
73
|
+
m_hasPressableAncestor = hadPressableAncestor;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "TextVisitor.h"
|
|
7
|
+
|
|
8
|
+
namespace Microsoft::ReactNative {
|
|
9
|
+
|
|
10
|
+
class TextHitTestVisitor : public TextVisitor {
|
|
11
|
+
using Super = TextVisitor;
|
|
12
|
+
|
|
13
|
+
public:
|
|
14
|
+
TextHitTestVisitor(winrt::Microsoft::ReactNative::ReactPointerEventArgs const &args, winrt::Point const &point)
|
|
15
|
+
: Super(), m_args{args}, m_point{point} {}
|
|
16
|
+
|
|
17
|
+
protected:
|
|
18
|
+
void VisitCore(ShadowNodeBase *node) override;
|
|
19
|
+
|
|
20
|
+
void VisitRawText(ShadowNodeBase *node) override;
|
|
21
|
+
|
|
22
|
+
void VisitVirtualText(ShadowNodeBase *node) override;
|
|
23
|
+
|
|
24
|
+
private:
|
|
25
|
+
winrt::Microsoft::ReactNative::ReactPointerEventArgs const &m_args;
|
|
26
|
+
winrt::Point const &m_point;
|
|
27
|
+
bool m_hasPressableAncestor{false};
|
|
28
|
+
int m_pressableCount{0};
|
|
29
|
+
bool m_targetFound{false};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#include "TextParentVisitor.h"
|
|
5
|
+
|
|
6
|
+
namespace Microsoft::ReactNative {
|
|
7
|
+
|
|
8
|
+
void TextParentVisitor::VisitCore(ShadowNodeBase *node) {
|
|
9
|
+
Visit(GetShadowNode(node->m_parent));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "TextVisitor.h"
|
|
7
|
+
|
|
8
|
+
namespace Microsoft::ReactNative {
|
|
9
|
+
|
|
10
|
+
class TextParentVisitor : public TextVisitor {
|
|
11
|
+
using Super = TextVisitor;
|
|
12
|
+
|
|
13
|
+
protected:
|
|
14
|
+
void VisitCore(ShadowNodeBase *node) override;
|
|
15
|
+
|
|
16
|
+
void VisitText(ShadowNodeBase *node) override{};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#include "TextPropertyChangedParentVisitor.h"
|
|
5
|
+
#include <UI.Xaml.Automation.Peers.h>
|
|
6
|
+
#include <UI.Xaml.Automation.h>
|
|
7
|
+
#include <UI.Xaml.Controls.h>
|
|
8
|
+
#include <UI.Xaml.Documents.h>
|
|
9
|
+
#include <Utils/ShadowNodeTypeUtils.h>
|
|
10
|
+
#include <Views/TextViewManager.h>
|
|
11
|
+
#include <Views/VirtualTextViewManager.h>
|
|
12
|
+
|
|
13
|
+
namespace winrt {
|
|
14
|
+
using namespace xaml::Automation;
|
|
15
|
+
using namespace xaml::Automation::Peers;
|
|
16
|
+
using namespace xaml::Documents;
|
|
17
|
+
} // namespace winrt
|
|
18
|
+
|
|
19
|
+
namespace Microsoft::ReactNative {
|
|
20
|
+
void TextPropertyChangedParentVisitor::VisitCore(ShadowNodeBase *node) {
|
|
21
|
+
// Update nested flag fast text updates
|
|
22
|
+
m_isNested = !IsRawTextShadowNode(node);
|
|
23
|
+
Super::VisitCore(node);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void TextPropertyChangedParentVisitor::VisitText(ShadowNodeBase *node) {
|
|
27
|
+
// Raise LiveRegionChanged event
|
|
28
|
+
const auto isTextUpdate = HasPropertyChangeType(PropertyChangeType::Text);
|
|
29
|
+
if (isTextUpdate) {
|
|
30
|
+
const auto element = node->GetView().as<xaml::Controls::TextBlock>();
|
|
31
|
+
|
|
32
|
+
// If name is set, it's controlled by accessibilityLabel, and it's already
|
|
33
|
+
// handled in FrameworkElementViewManager. Here it only handles when name is
|
|
34
|
+
// not set.
|
|
35
|
+
if (xaml::Automation::AutomationProperties::GetLiveSetting(element) != winrt::AutomationLiveSetting::Off &&
|
|
36
|
+
xaml::Automation::AutomationProperties::GetName(element).empty() &&
|
|
37
|
+
xaml::Automation::AutomationProperties::GetAccessibilityView(element) != winrt::AccessibilityView::Raw) {
|
|
38
|
+
if (auto peer = xaml::Automation::Peers::FrameworkElementAutomationPeer::FromElement(element)) {
|
|
39
|
+
peer.RaiseAutomationEvent(winrt::AutomationEvents::LiveRegionChanged);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Update fast text content
|
|
44
|
+
if (!m_isNested && node->m_children.size() == 1) {
|
|
45
|
+
if (const auto childNode = GetShadowNode(node->m_children[0])) {
|
|
46
|
+
const auto run = static_cast<ShadowNodeBase *>(childNode)->GetView().as<winrt::Run>();
|
|
47
|
+
element.Text(run.Text());
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Refresh text highlighters
|
|
53
|
+
const auto isHighlightAdded = HasPropertyChangeType(PropertyChangeType::AddHighlight);
|
|
54
|
+
const auto isHighlightRemoved = HasPropertyChangeType(PropertyChangeType::RemoveHighlight);
|
|
55
|
+
if (isTextUpdate || isHighlightAdded || isHighlightRemoved) {
|
|
56
|
+
TextViewManager::UpdateTextHighlighters(node, isHighlightAdded);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Set pressable descendant
|
|
60
|
+
if (HasPropertyChangeType(PropertyChangeType::AddPressable)) {
|
|
61
|
+
TextViewManager::SetDescendantPressable(node);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
void TextPropertyChangedParentVisitor::VisitVirtualText(ShadowNodeBase *node) {
|
|
66
|
+
const auto textNode = static_cast<VirtualTextShadowNode *>(node);
|
|
67
|
+
// Update descendant text highlight flag
|
|
68
|
+
if (HasPropertyChangeType(PropertyChangeType::AddHighlight)) {
|
|
69
|
+
textNode->hasDescendantTextHighlighter = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Update pressable descendant flag
|
|
73
|
+
if (HasPropertyChangeType(PropertyChangeType::AddPressable)) {
|
|
74
|
+
textNode->hasDescendantPressable = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
Super::VisitVirtualText(node);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <Views/TextViewManager.h>
|
|
7
|
+
#include "TextParentVisitor.h"
|
|
8
|
+
|
|
9
|
+
namespace Microsoft::ReactNative {
|
|
10
|
+
|
|
11
|
+
enum class PropertyChangeType : std::uint_fast8_t {
|
|
12
|
+
None = 0,
|
|
13
|
+
Text = 1 << 0,
|
|
14
|
+
AddHighlight = 1 << 1,
|
|
15
|
+
RemoveHighlight = 1 << 2,
|
|
16
|
+
AddPressable = 1 << 3,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
DEFINE_ENUM_FLAG_OPERATORS(PropertyChangeType);
|
|
20
|
+
|
|
21
|
+
class TextPropertyChangedParentVisitor : public TextParentVisitor {
|
|
22
|
+
using Super = TextParentVisitor;
|
|
23
|
+
|
|
24
|
+
public:
|
|
25
|
+
TextPropertyChangedParentVisitor(PropertyChangeType type) : m_propertyChangeType{type} {}
|
|
26
|
+
|
|
27
|
+
protected:
|
|
28
|
+
void VisitCore(ShadowNodeBase *node) override;
|
|
29
|
+
|
|
30
|
+
void VisitText(ShadowNodeBase *node) override;
|
|
31
|
+
|
|
32
|
+
void VisitVirtualText(ShadowNodeBase *node) override;
|
|
33
|
+
|
|
34
|
+
private:
|
|
35
|
+
PropertyChangeType m_propertyChangeType;
|
|
36
|
+
bool m_isNested{false};
|
|
37
|
+
|
|
38
|
+
bool HasPropertyChangeType(PropertyChangeType type) {
|
|
39
|
+
return (m_propertyChangeType & type) == type;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#include "TextTransformParentVisitor.h"
|
|
5
|
+
#include <Views/TextViewManager.h>
|
|
6
|
+
#include <Views/VirtualTextViewManager.h>
|
|
7
|
+
|
|
8
|
+
namespace Microsoft::ReactNative {
|
|
9
|
+
|
|
10
|
+
void TextTransformParentVisitor::VisitText(ShadowNodeBase *node) {
|
|
11
|
+
textTransform = TextViewManager::GetTextTransformValue(node);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
void TextTransformParentVisitor::VisitVirtualText(ShadowNodeBase *node) {
|
|
15
|
+
textTransform = static_cast<VirtualTextShadowNode *>(node)->textTransform;
|
|
16
|
+
if (textTransform == TextTransform::Undefined) {
|
|
17
|
+
Super::VisitVirtualText(node);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <Utils/TextTransform.h>
|
|
7
|
+
#include "TextParentVisitor.h"
|
|
8
|
+
|
|
9
|
+
namespace Microsoft::ReactNative {
|
|
10
|
+
|
|
11
|
+
class TextTransformParentVisitor : public TextParentVisitor {
|
|
12
|
+
using Super = TextParentVisitor;
|
|
13
|
+
|
|
14
|
+
public:
|
|
15
|
+
TextTransform textTransform;
|
|
16
|
+
|
|
17
|
+
protected:
|
|
18
|
+
void VisitText(ShadowNodeBase *node) override;
|
|
19
|
+
|
|
20
|
+
void VisitVirtualText(ShadowNodeBase *node) override;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
} // namespace Microsoft::ReactNative
|