react-native-windows 0.80.0-preview.1 → 0.80.0-preview.10
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/Directory.Build.props +6 -0
- package/Folly/TEMP_UntilFollyUpdate/json/json.cpp +1 -1
- package/Microsoft.ReactNative/CompositionSwitcher.idl +3 -8
- package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +73 -27
- package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +21 -156
- package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +30 -9
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +24 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +22 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +3 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +30 -65
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +4 -6
- package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +11 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.cpp +37 -5
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +33 -15
- package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +225 -0
- package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +23 -0
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +5 -3
- package/Microsoft.ReactNative/Fabric/ImageManager.cpp +1 -1
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp +64 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.h +11 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +2 -2
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.h +1 -1
- package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +29 -0
- package/Microsoft.ReactNative/Utils/ThemeUtils.cpp +49 -0
- package/Microsoft.ReactNative/Utils/ThemeUtils.h +31 -0
- package/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj +1 -1
- package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml +1 -1
- package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml +1 -1
- package/PropertySheets/Generated/PackageVersion.g.props +2 -2
- package/PropertySheets/JSEngine.props +1 -1
- package/PropertySheets/Warnings.props +45 -0
- package/README.md +4 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +1 -1
- package/Scripts/rnw-dependencies.ps1 +18 -5
- package/package.json +2 -2
- package/templates/cpp-app/template.config.js +2 -1
- package/templates/cpp-lib/example/metro.config.js +1 -1
- package/templates/old/generateWrapper.js +1 -1
- package/templates/old/uwp-cpp-app/template.config.js +1 -1
package/Directory.Build.props
CHANGED
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
-->
|
|
20
20
|
<EnableSourceLink Condition="'$(EnableSourceLink)' == '' AND '$(BuildingInRnwRepo)' == 'true'">true</EnableSourceLink>
|
|
21
21
|
<EnableSourceLink Condition="'$(EnableSourceLink)' == ''">false</EnableSourceLink>
|
|
22
|
+
|
|
23
|
+
<!-- Symbol Publishing Compliance (Work Item 59264834) - Generate PDB files for Release builds -->
|
|
24
|
+
<DebugSymbols Condition="'$(Configuration)' == 'Release'">true</DebugSymbols>
|
|
25
|
+
<DebugType Condition="'$(Configuration)' == 'Release'">pdbonly</DebugType>
|
|
26
|
+
<IncludeSymbols Condition="'$(Configuration)' == 'Release'">true</IncludeSymbols>
|
|
27
|
+
<IncludeSource Condition="'$(Configuration)' == 'Release'">false</IncludeSource>
|
|
22
28
|
<!-- When bumping the Folly version, be sure to bump the git hash of that version's commit, find the matching fastfloat dependency and build Folly.vcxproj (to update its cgmanifest.json) too. -->
|
|
23
29
|
<FollyVersion>2024.10.14.00</FollyVersion>
|
|
24
30
|
<FastFloatVersion>6.1.4</FastFloatVersion>
|
|
@@ -908,7 +908,7 @@ void escapeStringImpl(
|
|
|
908
908
|
|
|
909
909
|
if (encodeUnicode) {
|
|
910
910
|
// note that this if condition captures utf8 chars
|
|
911
|
-
// with value > 127, so size > 1 byte (or they are
|
|
911
|
+
// with value > 127, so size > 1 byte (or they are allowlisted for
|
|
912
912
|
// Unicode encoding).
|
|
913
913
|
// NOTE: char32_t / char16_t are both unsigned.
|
|
914
914
|
char32_t cp = utf8ToCodePoint(p, e, opts.skip_invalid_utf8);
|
|
@@ -31,13 +31,6 @@ namespace Microsoft.ReactNative.Composition.Experimental
|
|
|
31
31
|
SwitchThumb,
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
enum SnapAlignment
|
|
35
|
-
{
|
|
36
|
-
Start,
|
|
37
|
-
Center,
|
|
38
|
-
End,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
34
|
[webhosthidden]
|
|
42
35
|
[uuid("172def51-9e1a-4e3c-841a-e5a470065acc")] // uuid needed for empty interfaces
|
|
43
36
|
[version(0)]
|
|
@@ -118,6 +111,8 @@ namespace Microsoft.ReactNative.Composition.Experimental
|
|
|
118
111
|
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollPositionChanged;
|
|
119
112
|
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollBeginDrag;
|
|
120
113
|
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollEndDrag;
|
|
114
|
+
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumBegin;
|
|
115
|
+
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumEnd;
|
|
121
116
|
void ContentSize(Windows.Foundation.Numerics.Vector2 size);
|
|
122
117
|
Windows.Foundation.Numerics.Vector3 ScrollPosition { get; };
|
|
123
118
|
void ScrollBy(Windows.Foundation.Numerics.Vector3 offset, Boolean animate);
|
|
@@ -127,7 +122,7 @@ namespace Microsoft.ReactNative.Composition.Experimental
|
|
|
127
122
|
void SetMaximumZoomScale(Single maximumZoomScale);
|
|
128
123
|
void SetMinimumZoomScale(Single minimumZoomScale);
|
|
129
124
|
Boolean Horizontal;
|
|
130
|
-
void SetSnapPoints(Boolean snapToStart, Boolean snapToEnd, Windows.Foundation.Collections.IVectorView<Single> offsets
|
|
125
|
+
void SetSnapPoints(Boolean snapToStart, Boolean snapToEnd, Windows.Foundation.Collections.IVectorView<Single> offsets);
|
|
131
126
|
}
|
|
132
127
|
|
|
133
128
|
[webhosthidden]
|
|
@@ -27,8 +27,6 @@
|
|
|
27
27
|
|
|
28
28
|
namespace Microsoft::ReactNative::Composition::Experimental {
|
|
29
29
|
|
|
30
|
-
using namespace winrt::Microsoft::ReactNative::Composition::Experimental;
|
|
31
|
-
|
|
32
30
|
template <typename TSpriteVisual>
|
|
33
31
|
struct CompositionTypeTraits {};
|
|
34
32
|
|
|
@@ -711,8 +709,23 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
711
709
|
void IdleStateEntered(
|
|
712
710
|
typename TTypeRedirects::InteractionTracker sender,
|
|
713
711
|
typename TTypeRedirects::InteractionTrackerIdleStateEnteredArgs args) noexcept {
|
|
712
|
+
// If we were in inertia and are now idle, momentum has ended
|
|
713
|
+
if (m_outer->m_inertia) {
|
|
714
|
+
m_outer->FireScrollMomentumEnd({sender.Position().x, sender.Position().y});
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// If we were interacting but never entered inertia (Interacting -> Idle),
|
|
718
|
+
// and the interaction was user-driven (requestId == 0), fire end-drag here.
|
|
719
|
+
// Note: if the interactionRequestId was non-zero it was caused by a Try* call
|
|
720
|
+
// (programmatic), so we should not fire onScrollEndDrag.
|
|
721
|
+
if (m_outer->m_interacting && args.RequestId() == 0) {
|
|
722
|
+
m_outer->FireScrollEndDrag({sender.Position().x, sender.Position().y});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Clear state flags
|
|
714
726
|
m_outer->m_custom = false;
|
|
715
727
|
m_outer->m_inertia = false;
|
|
728
|
+
m_outer->m_interacting = false;
|
|
716
729
|
}
|
|
717
730
|
void InertiaStateEntered(
|
|
718
731
|
typename TTypeRedirects::InteractionTracker sender,
|
|
@@ -720,15 +733,26 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
720
733
|
m_outer->m_custom = false;
|
|
721
734
|
m_outer->m_inertia = true;
|
|
722
735
|
m_outer->m_currentPosition = args.NaturalRestingPosition();
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
736
|
+
|
|
737
|
+
if (!m_outer->m_interacting && args.RequestId() == 0) {
|
|
738
|
+
m_outer->FireScrollBeginDrag({args.NaturalRestingPosition().x, args.NaturalRestingPosition().y});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// If interaction was user-driven (requestId == 0),
|
|
742
|
+
// fire ScrollEndDrag here (Interacting -> Inertia caused by user lift).
|
|
743
|
+
if (m_outer->m_interacting && args.RequestId() == 0) {
|
|
744
|
+
m_outer->FireScrollEndDrag({args.NaturalRestingPosition().x, args.NaturalRestingPosition().y});
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Fire momentum scroll begin when we enter inertia (user or programmatic)
|
|
748
|
+
m_outer->FireScrollMomentumBegin({args.NaturalRestingPosition().x, args.NaturalRestingPosition().y});
|
|
728
749
|
}
|
|
729
750
|
void InteractingStateEntered(
|
|
730
751
|
typename TTypeRedirects::InteractionTracker sender,
|
|
731
752
|
typename TTypeRedirects::InteractionTrackerInteractingStateEnteredArgs args) noexcept {
|
|
753
|
+
// Mark that we're now interacting and remember the requestId (user manipulations => 0)
|
|
754
|
+
m_outer->m_interacting = true;
|
|
755
|
+
|
|
732
756
|
// Fire when the user starts dragging the object
|
|
733
757
|
m_outer->FireScrollBeginDrag({sender.Position().x, sender.Position().y});
|
|
734
758
|
}
|
|
@@ -738,6 +762,10 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
738
762
|
void ValuesChanged(
|
|
739
763
|
typename TTypeRedirects::InteractionTracker sender,
|
|
740
764
|
typename TTypeRedirects::InteractionTrackerValuesChangedArgs args) noexcept {
|
|
765
|
+
if (!m_outer->m_interacting && args.RequestId() == 0) {
|
|
766
|
+
m_outer->FireScrollBeginDrag({args.Position().x, args.Position().y});
|
|
767
|
+
}
|
|
768
|
+
m_outer->m_interacting = true;
|
|
741
769
|
m_outer->m_currentPosition = args.Position();
|
|
742
770
|
m_outer->FireScrollPositionChanged({args.Position().x, args.Position().y});
|
|
743
771
|
}
|
|
@@ -873,11 +901,9 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
873
901
|
void SetSnapPoints(
|
|
874
902
|
bool snapToStart,
|
|
875
903
|
bool snapToEnd,
|
|
876
|
-
winrt::Windows::Foundation::Collections::IVectorView<float> const &offsets
|
|
877
|
-
SnapAlignment snapToAlignment) noexcept {
|
|
904
|
+
winrt::Windows::Foundation::Collections::IVectorView<float> const &offsets) noexcept {
|
|
878
905
|
m_snapToStart = snapToStart;
|
|
879
906
|
m_snapToEnd = snapToEnd;
|
|
880
|
-
m_snapToAlignment = snapToAlignment;
|
|
881
907
|
m_snapToOffsets.clear();
|
|
882
908
|
if (offsets) {
|
|
883
909
|
for (auto const &offset : offsets) {
|
|
@@ -985,6 +1011,20 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
985
1011
|
return m_scrollEndDragEvent.add(handler);
|
|
986
1012
|
}
|
|
987
1013
|
|
|
1014
|
+
winrt::event_token ScrollMomentumBegin(
|
|
1015
|
+
winrt::Windows::Foundation::EventHandler<
|
|
1016
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs> const
|
|
1017
|
+
&handler) noexcept {
|
|
1018
|
+
return m_scrollMomentumBeginEvent.add(handler);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
winrt::event_token ScrollMomentumEnd(
|
|
1022
|
+
winrt::Windows::Foundation::EventHandler<
|
|
1023
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs> const
|
|
1024
|
+
&handler) noexcept {
|
|
1025
|
+
return m_scrollMomentumEndEvent.add(handler);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
988
1028
|
void ScrollPositionChanged(winrt::event_token const &token) noexcept {
|
|
989
1029
|
m_scrollPositionChangedEvent.remove(token);
|
|
990
1030
|
}
|
|
@@ -997,6 +1037,14 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
997
1037
|
m_scrollEndDragEvent.remove(token);
|
|
998
1038
|
}
|
|
999
1039
|
|
|
1040
|
+
void ScrollMomentumBegin(winrt::event_token const &token) noexcept {
|
|
1041
|
+
m_scrollMomentumBeginEvent.remove(token);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
void ScrollMomentumEnd(winrt::event_token const &token) noexcept {
|
|
1045
|
+
m_scrollMomentumEndEvent.remove(token);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1000
1048
|
void ContentSize(winrt::Windows::Foundation::Numerics::float2 const &size) noexcept {
|
|
1001
1049
|
m_contentSize = size;
|
|
1002
1050
|
m_contentVisual.Size(size);
|
|
@@ -1075,6 +1123,14 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
1075
1123
|
m_scrollEndDragEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
|
|
1076
1124
|
}
|
|
1077
1125
|
|
|
1126
|
+
void FireScrollMomentumBegin(winrt::Windows::Foundation::Numerics::float2 position) noexcept {
|
|
1127
|
+
m_scrollMomentumBeginEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
void FireScrollMomentumEnd(winrt::Windows::Foundation::Numerics::float2 position) noexcept {
|
|
1131
|
+
m_scrollMomentumEndEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1078
1134
|
void UpdateMaxPosition() noexcept {
|
|
1079
1135
|
m_interactionTracker.MaxPosition(
|
|
1080
1136
|
{std::max<float>(m_contentSize.x - m_visualSize.x, 0),
|
|
@@ -1104,22 +1160,6 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
1104
1160
|
}
|
|
1105
1161
|
|
|
1106
1162
|
snapPositions.insert(snapPositions.end(), m_snapToOffsets.begin(), m_snapToOffsets.end());
|
|
1107
|
-
|
|
1108
|
-
// Adjust snap positions based on alignment
|
|
1109
|
-
const float viewportSize = m_horizontal ? visualSize.x : visualSize.y;
|
|
1110
|
-
if (m_snapToAlignment == SnapAlignment::Center) {
|
|
1111
|
-
// For center alignment, offset snap positions by half the viewport size
|
|
1112
|
-
for (auto &position : snapPositions) {
|
|
1113
|
-
position = std::max(0.0f, position - viewportSize / 2.0f);
|
|
1114
|
-
}
|
|
1115
|
-
} else if (m_snapToAlignment == SnapAlignment::End) {
|
|
1116
|
-
// For end alignment, offset snap positions by the full viewport size
|
|
1117
|
-
for (auto &position : snapPositions) {
|
|
1118
|
-
position = std::max(0.0f, position - viewportSize);
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
// For Start alignment, no adjustment needed
|
|
1122
|
-
|
|
1123
1163
|
std::sort(snapPositions.begin(), snapPositions.end());
|
|
1124
1164
|
snapPositions.erase(std::unique(snapPositions.begin(), snapPositions.end()), snapPositions.end());
|
|
1125
1165
|
|
|
@@ -1247,9 +1287,9 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
1247
1287
|
bool m_snapToStart{true};
|
|
1248
1288
|
bool m_snapToEnd{true};
|
|
1249
1289
|
std::vector<float> m_snapToOffsets;
|
|
1250
|
-
SnapAlignment m_snapToAlignment{SnapAlignment::Start};
|
|
1251
1290
|
bool m_inertia{false};
|
|
1252
1291
|
bool m_custom{false};
|
|
1292
|
+
bool m_interacting{false};
|
|
1253
1293
|
winrt::Windows::Foundation::Numerics::float3 m_targetPosition;
|
|
1254
1294
|
winrt::Windows::Foundation::Numerics::float3 m_currentPosition;
|
|
1255
1295
|
winrt::Windows::Foundation::Numerics::float2 m_contentSize{0};
|
|
@@ -1263,6 +1303,12 @@ struct CompScrollerVisual : winrt::implements<
|
|
|
1263
1303
|
winrt::event<winrt::Windows::Foundation::EventHandler<
|
|
1264
1304
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
|
|
1265
1305
|
m_scrollEndDragEvent;
|
|
1306
|
+
winrt::event<winrt::Windows::Foundation::EventHandler<
|
|
1307
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
|
|
1308
|
+
m_scrollMomentumBeginEvent;
|
|
1309
|
+
winrt::event<winrt::Windows::Foundation::EventHandler<
|
|
1310
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
|
|
1311
|
+
m_scrollMomentumEndEvent;
|
|
1266
1312
|
typename TTypeRedirects::SpriteVisual m_visual{nullptr};
|
|
1267
1313
|
typename TTypeRedirects::SpriteVisual m_contentVisual{nullptr};
|
|
1268
1314
|
typename TTypeRedirects::InteractionTracker m_interactionTracker{nullptr};
|
|
@@ -313,161 +313,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
|
|
|
313
313
|
return S_OK;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
long GetControlTypeFromString(const std::string &role) noexcept {
|
|
317
|
-
if (role == "adjustable") {
|
|
318
|
-
return UIA_SliderControlTypeId;
|
|
319
|
-
} else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
|
|
320
|
-
return UIA_GroupControlTypeId;
|
|
321
|
-
} else if (role == "button" || role == "imagebutton" || role == "switch" || role == "togglebutton") {
|
|
322
|
-
return UIA_ButtonControlTypeId;
|
|
323
|
-
} else if (role == "checkbox") {
|
|
324
|
-
return UIA_CheckBoxControlTypeId;
|
|
325
|
-
} else if (role == "combobox") {
|
|
326
|
-
return UIA_ComboBoxControlTypeId;
|
|
327
|
-
} else if (role == "alert" || role == "header" || role == "summary" || role == "text") {
|
|
328
|
-
return UIA_TextControlTypeId;
|
|
329
|
-
} else if (role == "image") {
|
|
330
|
-
return UIA_ImageControlTypeId;
|
|
331
|
-
} else if (role == "keyboardkey") {
|
|
332
|
-
return UIA_CustomControlTypeId;
|
|
333
|
-
} else if (role == "link") {
|
|
334
|
-
return UIA_HyperlinkControlTypeId;
|
|
335
|
-
}
|
|
336
|
-
// list and listitem were added by RNW to better support UIA Control Types
|
|
337
|
-
else if (role == "list") {
|
|
338
|
-
return UIA_ListControlTypeId;
|
|
339
|
-
} else if (role == "listitem") {
|
|
340
|
-
return UIA_ListItemControlTypeId;
|
|
341
|
-
} else if (role == "menu") {
|
|
342
|
-
return UIA_MenuControlTypeId;
|
|
343
|
-
} else if (role == "menubar") {
|
|
344
|
-
return UIA_MenuBarControlTypeId;
|
|
345
|
-
} else if (role == "menuitem") {
|
|
346
|
-
return UIA_MenuItemControlTypeId;
|
|
347
|
-
}
|
|
348
|
-
// If role is "none", remove the element from the control tree
|
|
349
|
-
// and expose it as a plain element would in the raw tree.
|
|
350
|
-
else if (role == "none") {
|
|
351
|
-
return UIA_GroupControlTypeId;
|
|
352
|
-
} else if (role == "progressbar") {
|
|
353
|
-
return UIA_ProgressBarControlTypeId;
|
|
354
|
-
} else if (role == "radio") {
|
|
355
|
-
return UIA_RadioButtonControlTypeId;
|
|
356
|
-
} else if (role == "scrollbar") {
|
|
357
|
-
return UIA_ScrollBarControlTypeId;
|
|
358
|
-
} else if (role == "spinbutton") {
|
|
359
|
-
return UIA_SpinnerControlTypeId;
|
|
360
|
-
} else if (role == "splitbutton") {
|
|
361
|
-
return UIA_SplitButtonControlTypeId;
|
|
362
|
-
} else if (role == "tab") {
|
|
363
|
-
return UIA_TabItemControlTypeId;
|
|
364
|
-
} else if (role == "tablist") {
|
|
365
|
-
return UIA_TabControlTypeId;
|
|
366
|
-
} else if (role == "textinput" || role == "searchbox") {
|
|
367
|
-
return UIA_EditControlTypeId;
|
|
368
|
-
} else if (role == "toolbar") {
|
|
369
|
-
return UIA_ToolBarControlTypeId;
|
|
370
|
-
} else if (role == "tree") {
|
|
371
|
-
return UIA_TreeControlTypeId;
|
|
372
|
-
} else if (role == "treeitem") {
|
|
373
|
-
return UIA_TreeItemControlTypeId;
|
|
374
|
-
} else if (role == "pane") {
|
|
375
|
-
return UIA_PaneControlTypeId;
|
|
376
|
-
}
|
|
377
|
-
assert(false);
|
|
378
|
-
return UIA_GroupControlTypeId;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
|
|
382
|
-
switch (role) {
|
|
383
|
-
case facebook::react::Role::Alert:
|
|
384
|
-
return UIA_TextControlTypeId;
|
|
385
|
-
case facebook::react::Role::Application:
|
|
386
|
-
return UIA_WindowControlTypeId;
|
|
387
|
-
case facebook::react::Role::Button:
|
|
388
|
-
return UIA_ButtonControlTypeId;
|
|
389
|
-
case facebook::react::Role::Checkbox:
|
|
390
|
-
return UIA_CheckBoxControlTypeId;
|
|
391
|
-
case facebook::react::Role::Columnheader:
|
|
392
|
-
return UIA_HeaderControlTypeId;
|
|
393
|
-
case facebook::react::Role::Combobox:
|
|
394
|
-
return UIA_ComboBoxControlTypeId;
|
|
395
|
-
case facebook::react::Role::Document:
|
|
396
|
-
return UIA_DocumentControlTypeId;
|
|
397
|
-
case facebook::react::Role::Grid:
|
|
398
|
-
return UIA_GroupControlTypeId;
|
|
399
|
-
case facebook::react::Role::Group:
|
|
400
|
-
return UIA_GroupControlTypeId;
|
|
401
|
-
case facebook::react::Role::Heading:
|
|
402
|
-
return UIA_TextControlTypeId;
|
|
403
|
-
case facebook::react::Role::Img:
|
|
404
|
-
return UIA_ImageControlTypeId;
|
|
405
|
-
case facebook::react::Role::Link:
|
|
406
|
-
return UIA_HyperlinkControlTypeId;
|
|
407
|
-
case facebook::react::Role::List:
|
|
408
|
-
return UIA_ListControlTypeId;
|
|
409
|
-
case facebook::react::Role::Listitem:
|
|
410
|
-
return UIA_ListItemControlTypeId;
|
|
411
|
-
case facebook::react::Role::Menu:
|
|
412
|
-
return UIA_MenuControlTypeId;
|
|
413
|
-
case facebook::react::Role::Menubar:
|
|
414
|
-
return UIA_MenuBarControlTypeId;
|
|
415
|
-
case facebook::react::Role::Menuitem:
|
|
416
|
-
return UIA_MenuItemControlTypeId;
|
|
417
|
-
case facebook::react::Role::None:
|
|
418
|
-
return UIA_GroupControlTypeId;
|
|
419
|
-
case facebook::react::Role::Presentation:
|
|
420
|
-
return UIA_GroupControlTypeId;
|
|
421
|
-
case facebook::react::Role::Progressbar:
|
|
422
|
-
return UIA_ProgressBarControlTypeId;
|
|
423
|
-
case facebook::react::Role::Radio:
|
|
424
|
-
return UIA_RadioButtonControlTypeId;
|
|
425
|
-
case facebook::react::Role::Radiogroup:
|
|
426
|
-
return UIA_GroupControlTypeId;
|
|
427
|
-
case facebook::react::Role::Rowgroup:
|
|
428
|
-
return UIA_GroupControlTypeId;
|
|
429
|
-
case facebook::react::Role::Rowheader:
|
|
430
|
-
return UIA_HeaderControlTypeId;
|
|
431
|
-
case facebook::react::Role::Scrollbar:
|
|
432
|
-
return UIA_ScrollBarControlTypeId;
|
|
433
|
-
case facebook::react::Role::Searchbox:
|
|
434
|
-
return UIA_EditControlTypeId;
|
|
435
|
-
case facebook::react::Role::Separator:
|
|
436
|
-
return UIA_SeparatorControlTypeId;
|
|
437
|
-
case facebook::react::Role::Slider:
|
|
438
|
-
return UIA_SliderControlTypeId;
|
|
439
|
-
case facebook::react::Role::Spinbutton:
|
|
440
|
-
return UIA_SpinnerControlTypeId;
|
|
441
|
-
case facebook::react::Role::Status:
|
|
442
|
-
return UIA_StatusBarControlTypeId;
|
|
443
|
-
case facebook::react::Role::Summary:
|
|
444
|
-
return UIA_GroupControlTypeId;
|
|
445
|
-
case facebook::react::Role::Switch:
|
|
446
|
-
return UIA_ButtonControlTypeId;
|
|
447
|
-
case facebook::react::Role::Tab:
|
|
448
|
-
return UIA_TabItemControlTypeId;
|
|
449
|
-
case facebook::react::Role::Table:
|
|
450
|
-
return UIA_TableControlTypeId;
|
|
451
|
-
case facebook::react::Role::Tablist:
|
|
452
|
-
return UIA_TabControlTypeId;
|
|
453
|
-
case facebook::react::Role::Tabpanel:
|
|
454
|
-
return UIA_TabControlTypeId;
|
|
455
|
-
case facebook::react::Role::Timer:
|
|
456
|
-
return UIA_ButtonControlTypeId;
|
|
457
|
-
case facebook::react::Role::Toolbar:
|
|
458
|
-
return UIA_ToolBarControlTypeId;
|
|
459
|
-
case facebook::react::Role::Tooltip:
|
|
460
|
-
return UIA_ToolTipControlTypeId;
|
|
461
|
-
case facebook::react::Role::Tree:
|
|
462
|
-
return UIA_TreeControlTypeId;
|
|
463
|
-
case facebook::react::Role::Treegrid:
|
|
464
|
-
return UIA_TreeControlTypeId;
|
|
465
|
-
case facebook::react::Role::Treeitem:
|
|
466
|
-
return UIA_TreeItemControlTypeId;
|
|
467
|
-
}
|
|
468
|
-
return UIA_GroupControlTypeId;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
316
|
HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pRetVal) {
|
|
472
317
|
if (pRetVal == nullptr)
|
|
473
318
|
return E_POINTER;
|
|
@@ -561,7 +406,18 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
|
|
|
561
406
|
}
|
|
562
407
|
case UIA_IsOffscreenPropertyId: {
|
|
563
408
|
pRetVal->vt = VT_BOOL;
|
|
564
|
-
|
|
409
|
+
|
|
410
|
+
// Check if element is offscreen - consider modal content special case
|
|
411
|
+
bool isOffscreen = (compositionView->getClipState() == ClipState::FullyClipped);
|
|
412
|
+
|
|
413
|
+
// Modal content may appear clipped but is visible in its own window
|
|
414
|
+
if (isOffscreen) {
|
|
415
|
+
if (const auto hwnd = compositionView->GetHwndForParenting()) {
|
|
416
|
+
isOffscreen = !(IsWindowVisible(hwnd) && !IsIconic(hwnd));
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
pRetVal->boolVal = isOffscreen ? VARIANT_TRUE : VARIANT_FALSE;
|
|
565
421
|
break;
|
|
566
422
|
}
|
|
567
423
|
case UIA_HelpTextPropertyId: {
|
|
@@ -618,6 +474,11 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
|
|
|
618
474
|
pRetVal->bstrVal = SysAllocString(desc.c_str());
|
|
619
475
|
break;
|
|
620
476
|
}
|
|
477
|
+
case UIA_HeadingLevelPropertyId: {
|
|
478
|
+
pRetVal->vt = VT_I4;
|
|
479
|
+
pRetVal->lVal = GetHeadingLevel(props->accessibilityLevel, props->accessibilityRole, props->role);
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
621
482
|
}
|
|
622
483
|
return hr;
|
|
623
484
|
}
|
|
@@ -1009,7 +870,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Expand() {
|
|
|
1009
870
|
|
|
1010
871
|
if (!strongView)
|
|
1011
872
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
873
|
+
|
|
1012
874
|
DispatchAccessibilityAction(m_view, "expand");
|
|
875
|
+
|
|
1013
876
|
return S_OK;
|
|
1014
877
|
}
|
|
1015
878
|
|
|
@@ -1018,7 +881,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Collapse() {
|
|
|
1018
881
|
|
|
1019
882
|
if (!strongView)
|
|
1020
883
|
return UIA_E_ELEMENTNOTAVAILABLE;
|
|
884
|
+
|
|
1021
885
|
DispatchAccessibilityAction(m_view, "collapse");
|
|
886
|
+
|
|
1022
887
|
return S_OK;
|
|
1023
888
|
}
|
|
1024
889
|
|
|
@@ -18,14 +18,30 @@ CompositionTextRangeProvider::CompositionTextRangeProvider(
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
HRESULT __stdcall CompositionTextRangeProvider::Clone(ITextRangeProvider **pRetVal) {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
if (pRetVal == nullptr)
|
|
22
|
+
return E_POINTER;
|
|
23
|
+
|
|
24
|
+
auto clone = winrt::make<winrt::Microsoft::ReactNative::implementation::CompositionTextRangeProvider>(
|
|
25
|
+
m_view.view().as<winrt::Microsoft::ReactNative::Composition::ComponentView>(), m_parentProvider.get());
|
|
26
|
+
*pRetVal = clone.detach();
|
|
23
27
|
return S_OK;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
HRESULT __stdcall CompositionTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *pRetVal) {
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
if (pRetVal == nullptr)
|
|
32
|
+
return E_POINTER;
|
|
33
|
+
if (range == nullptr) {
|
|
34
|
+
*pRetVal = FALSE;
|
|
35
|
+
return S_OK;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Try to cast to our type , considering provider only supports a single range per view
|
|
39
|
+
auto other = dynamic_cast<CompositionTextRangeProvider *>(range);
|
|
40
|
+
if (other && other->m_view.view() == m_view.view()) {
|
|
41
|
+
*pRetVal = TRUE;
|
|
42
|
+
} else {
|
|
43
|
+
*pRetVal = FALSE;
|
|
44
|
+
}
|
|
29
45
|
return S_OK;
|
|
30
46
|
}
|
|
31
47
|
|
|
@@ -34,7 +50,10 @@ HRESULT __stdcall CompositionTextRangeProvider::CompareEndpoints(
|
|
|
34
50
|
ITextRangeProvider *targetRange,
|
|
35
51
|
TextPatternRangeEndpoint targetEndpoint,
|
|
36
52
|
int *pRetVal) {
|
|
37
|
-
|
|
53
|
+
if (pRetVal == nullptr)
|
|
54
|
+
return E_POINTER;
|
|
55
|
+
|
|
56
|
+
// For a single-range provider, always equal:
|
|
38
57
|
*pRetVal = 0;
|
|
39
58
|
return S_OK;
|
|
40
59
|
}
|
|
@@ -98,13 +117,13 @@ HRESULT __stdcall CompositionTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEI
|
|
|
98
117
|
textTransform = props->textAttributes.textTransform.value();
|
|
99
118
|
}
|
|
100
119
|
if (fontVariant == facebook::react::FontVariant::SmallCaps) {
|
|
101
|
-
|
|
120
|
+
pRetVal->lVal = CapStyle_SmallCap;
|
|
102
121
|
} else if (textTransform == facebook::react::TextTransform::Capitalize) {
|
|
103
|
-
|
|
122
|
+
pRetVal->lVal = CapStyle_Titling;
|
|
104
123
|
} else if (textTransform == facebook::react::TextTransform::Lowercase) {
|
|
105
|
-
|
|
124
|
+
pRetVal->lVal = CapStyle_None;
|
|
106
125
|
} else if (textTransform == facebook::react::TextTransform::Uppercase) {
|
|
107
|
-
|
|
126
|
+
pRetVal->lVal = CapStyle_AllCap;
|
|
108
127
|
}
|
|
109
128
|
} else if (attributeId == UIA_FontNameAttributeId) {
|
|
110
129
|
pRetVal->vt = VT_BSTR;
|
|
@@ -282,6 +301,8 @@ HRESULT __stdcall CompositionTextRangeProvider::ScrollIntoView(BOOL alignToTop)
|
|
|
282
301
|
return S_OK;
|
|
283
302
|
}
|
|
284
303
|
|
|
304
|
+
// All the below methods should be implemented once the selection comes for paragraph and TextInput
|
|
305
|
+
|
|
285
306
|
HRESULT __stdcall CompositionTextRangeProvider::AddToSelection() {
|
|
286
307
|
// no-op
|
|
287
308
|
return S_OK;
|
|
@@ -831,6 +831,30 @@ void ComponentView::updateAccessibilityProps(
|
|
|
831
831
|
oldViewProps.accessibilityValue.text,
|
|
832
832
|
newViewProps.accessibilityValue.text);
|
|
833
833
|
|
|
834
|
+
// Handle annotation properties with single call
|
|
835
|
+
winrt::Microsoft::ReactNative::implementation::UpdateUiaPropertiesForAnnotation(
|
|
836
|
+
EnsureUiaProvider(), oldViewProps.accessibilityAnnotation, newViewProps.accessibilityAnnotation);
|
|
837
|
+
|
|
838
|
+
// Handle expand/collapse state changes
|
|
839
|
+
if (oldViewProps.accessibilityState.has_value() != newViewProps.accessibilityState.has_value() ||
|
|
840
|
+
(oldViewProps.accessibilityState.has_value() && newViewProps.accessibilityState.has_value() &&
|
|
841
|
+
oldViewProps.accessibilityState->expanded != newViewProps.accessibilityState->expanded)) {
|
|
842
|
+
auto oldExpanded =
|
|
843
|
+
oldViewProps.accessibilityState.has_value() && oldViewProps.accessibilityState->expanded.has_value()
|
|
844
|
+
? oldViewProps.accessibilityState->expanded.value()
|
|
845
|
+
: false;
|
|
846
|
+
auto newExpanded =
|
|
847
|
+
newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->expanded.has_value()
|
|
848
|
+
? newViewProps.accessibilityState->expanded.value()
|
|
849
|
+
: false;
|
|
850
|
+
|
|
851
|
+
winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
|
|
852
|
+
EnsureUiaProvider(),
|
|
853
|
+
UIA_ExpandCollapseExpandCollapseStatePropertyId,
|
|
854
|
+
static_cast<int>(winrt::Microsoft::ReactNative::implementation::GetExpandCollapseState(oldExpanded)),
|
|
855
|
+
static_cast<int>(winrt::Microsoft::ReactNative::implementation::GetExpandCollapseState(newExpanded)));
|
|
856
|
+
}
|
|
857
|
+
|
|
834
858
|
if ((oldViewProps.accessibilityState.has_value() && oldViewProps.accessibilityState->selected.has_value()) !=
|
|
835
859
|
((newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->selected.has_value()))) {
|
|
836
860
|
auto compProvider =
|
|
@@ -40,6 +40,14 @@
|
|
|
40
40
|
|
|
41
41
|
namespace winrt::Microsoft::ReactNative::implementation {
|
|
42
42
|
|
|
43
|
+
ReactPropertyId<winrt::Microsoft::ReactNative::ReactNonAbiValue<
|
|
44
|
+
winrt::weak_ref<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>>>
|
|
45
|
+
ReactNativeIsland::LastFocusedReactNativeIslandProperty() noexcept {
|
|
46
|
+
static const ReactPropertyId<winrt::Microsoft::ReactNative::ReactNonAbiValue<
|
|
47
|
+
winrt::weak_ref<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>>>
|
|
48
|
+
prop{L"ReactNative.Composition", L"ReactNativeIsland"};
|
|
49
|
+
return prop;
|
|
50
|
+
}
|
|
43
51
|
constexpr float loadingActivitySize = 12.0f;
|
|
44
52
|
constexpr float loadingActivityHorizontalOffset = 16.0f;
|
|
45
53
|
constexpr float loadingBarHeight = 36.0f;
|
|
@@ -861,6 +869,20 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
|
|
|
861
869
|
}
|
|
862
870
|
}
|
|
863
871
|
});
|
|
872
|
+
focusController.GotFocus(
|
|
873
|
+
[weakThis = get_weak()](const auto &sender, const winrt::Microsoft::UI::Input::FocusChangedEventArgs &args) {
|
|
874
|
+
if (auto pThis = weakThis.get()) {
|
|
875
|
+
// Set the island to React context so it can be accessed by native modules
|
|
876
|
+
if (pThis->m_context && pThis->m_island) {
|
|
877
|
+
auto properties = pThis->m_context.Properties();
|
|
878
|
+
properties.Set(
|
|
879
|
+
ReactNativeIsland::LastFocusedReactNativeIslandProperty(),
|
|
880
|
+
winrt::Microsoft::ReactNative::ReactNonAbiValue<
|
|
881
|
+
winrt::weak_ref<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>>{
|
|
882
|
+
std::in_place, weakThis});
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
});
|
|
864
886
|
|
|
865
887
|
// ContentIsland does not support weak_ref, so we cannot use auto_revoke for these events
|
|
866
888
|
m_islandAutomationProviderRequestedToken = m_island.AutomationProviderRequested(
|
|
@@ -49,6 +49,9 @@ struct ReactNativeIsland
|
|
|
49
49
|
~ReactNativeIsland() noexcept;
|
|
50
50
|
|
|
51
51
|
ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept;
|
|
52
|
+
static ReactPropertyId<winrt::Microsoft::ReactNative::ReactNonAbiValue<
|
|
53
|
+
winrt::weak_ref<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>>>
|
|
54
|
+
LastFocusedReactNativeIslandProperty() noexcept;
|
|
52
55
|
ReactNativeIsland(const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portal) noexcept;
|
|
53
56
|
|
|
54
57
|
static winrt::Microsoft::ReactNative::ReactNativeIsland CreatePortal(
|