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
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
28
28
|
|
|
29
29
|
constexpr float c_scrollerLineDelta = 16.0f;
|
|
30
|
-
constexpr auto c_maxSnapPoints = 1000;
|
|
31
30
|
|
|
32
31
|
enum class ScrollbarHitRegion : int {
|
|
33
32
|
Unknown = -1,
|
|
@@ -741,15 +740,6 @@ void ScrollViewComponentView::updateBackgroundColor(const facebook::react::Share
|
|
|
741
740
|
}
|
|
742
741
|
}
|
|
743
742
|
|
|
744
|
-
winrt::Windows::Foundation::Collections::IVector<float> ScrollViewComponentView::CreateSnapToOffsets(
|
|
745
|
-
const std::vector<float> &offsets) {
|
|
746
|
-
auto snapToOffsets = winrt::single_threaded_vector<float>();
|
|
747
|
-
for (const auto &offset : offsets) {
|
|
748
|
-
snapToOffsets.Append(offset);
|
|
749
|
-
}
|
|
750
|
-
return snapToOffsets;
|
|
751
|
-
}
|
|
752
|
-
|
|
753
743
|
void ScrollViewComponentView::updateProps(
|
|
754
744
|
facebook::react::Props::Shared const &props,
|
|
755
745
|
facebook::react::Props::Shared const &oldProps) noexcept {
|
|
@@ -818,13 +808,11 @@ void ScrollViewComponentView::updateProps(
|
|
|
818
808
|
|
|
819
809
|
if (oldViewProps.snapToStart != newViewProps.snapToStart || oldViewProps.snapToEnd != newViewProps.snapToEnd ||
|
|
820
810
|
oldViewProps.snapToOffsets != newViewProps.snapToOffsets) {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const auto snapToOffsets = CreateSnapToOffsets(newViewProps.snapToOffsets);
|
|
825
|
-
m_scrollVisual.SetSnapPoints(
|
|
826
|
-
newViewProps.snapToStart, newViewProps.snapToEnd, snapToOffsets.GetView(), SnapAlignment::Center);
|
|
811
|
+
const auto snapToOffsets = winrt::single_threaded_vector<float>();
|
|
812
|
+
for (const auto &offset : newViewProps.snapToOffsets) {
|
|
813
|
+
snapToOffsets.Append(static_cast<float>(offset));
|
|
827
814
|
}
|
|
815
|
+
m_scrollVisual.SetSnapPoints(newViewProps.snapToStart, newViewProps.snapToEnd, snapToOffsets.GetView());
|
|
828
816
|
}
|
|
829
817
|
}
|
|
830
818
|
|
|
@@ -875,9 +863,6 @@ void ScrollViewComponentView::updateContentVisualSize() noexcept {
|
|
|
875
863
|
m_verticalScrollbarComponent->ContentSize(contentSize);
|
|
876
864
|
m_horizontalScrollbarComponent->ContentSize(contentSize);
|
|
877
865
|
m_scrollVisual.ContentSize(contentSize);
|
|
878
|
-
|
|
879
|
-
// Update snap points if snapToInterval is being used, as content size affects the number of snap points
|
|
880
|
-
updateSnapPoints();
|
|
881
866
|
}
|
|
882
867
|
|
|
883
868
|
void ScrollViewComponentView::prepareForRecycle() noexcept {}
|
|
@@ -1354,6 +1339,32 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
|
|
|
1354
1339
|
}
|
|
1355
1340
|
});
|
|
1356
1341
|
|
|
1342
|
+
m_scrollMomentumBeginRevoker = m_scrollVisual.ScrollMomentumBegin(
|
|
1343
|
+
winrt::auto_revoke,
|
|
1344
|
+
[this](
|
|
1345
|
+
winrt::IInspectable const & /*sender*/,
|
|
1346
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
|
|
1347
|
+
auto eventEmitter = GetEventEmitter();
|
|
1348
|
+
if (eventEmitter) {
|
|
1349
|
+
auto scrollMetrics = getScrollMetrics(eventEmitter, args);
|
|
1350
|
+
std::static_pointer_cast<facebook::react::ScrollViewEventEmitter const>(eventEmitter)
|
|
1351
|
+
->onMomentumScrollBegin(scrollMetrics);
|
|
1352
|
+
}
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
m_scrollMomentumEndRevoker = m_scrollVisual.ScrollMomentumEnd(
|
|
1356
|
+
winrt::auto_revoke,
|
|
1357
|
+
[this](
|
|
1358
|
+
winrt::IInspectable const & /*sender*/,
|
|
1359
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
|
|
1360
|
+
auto eventEmitter = GetEventEmitter();
|
|
1361
|
+
if (eventEmitter) {
|
|
1362
|
+
auto scrollMetrics = getScrollMetrics(eventEmitter, args);
|
|
1363
|
+
std::static_pointer_cast<facebook::react::ScrollViewEventEmitter const>(eventEmitter)
|
|
1364
|
+
->onMomentumScrollEnd(scrollMetrics);
|
|
1365
|
+
}
|
|
1366
|
+
});
|
|
1367
|
+
|
|
1357
1368
|
return visual;
|
|
1358
1369
|
}
|
|
1359
1370
|
|
|
@@ -1450,50 +1461,4 @@ void ScrollViewComponentView::updateShowsVerticalScrollIndicator(bool value) noe
|
|
|
1450
1461
|
void ScrollViewComponentView::updateDecelerationRate(float value) noexcept {
|
|
1451
1462
|
m_scrollVisual.SetDecelerationRate({value, value, value});
|
|
1452
1463
|
}
|
|
1453
|
-
|
|
1454
|
-
SnapAlignment ScrollViewComponentView::convertSnapToAlignment(
|
|
1455
|
-
facebook::react::ScrollViewSnapToAlignment alignment) noexcept {
|
|
1456
|
-
switch (alignment) {
|
|
1457
|
-
case facebook::react::ScrollViewSnapToAlignment::Center:
|
|
1458
|
-
return SnapAlignment::Center;
|
|
1459
|
-
case facebook::react::ScrollViewSnapToAlignment::End:
|
|
1460
|
-
return SnapAlignment::End;
|
|
1461
|
-
case facebook::react::ScrollViewSnapToAlignment::Start:
|
|
1462
|
-
default:
|
|
1463
|
-
return SnapAlignment::Start;
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
void ScrollViewComponentView::updateSnapPoints() noexcept {
|
|
1468
|
-
const auto &viewProps = *std::static_pointer_cast<const facebook::react::ScrollViewProps>(this->viewProps());
|
|
1469
|
-
const auto snapToOffsets = CreateSnapToOffsets(viewProps.snapToOffsets);
|
|
1470
|
-
// Typically used in combination with snapToAlignment and decelerationRate="fast"
|
|
1471
|
-
auto snapAlignment = SnapAlignment::Center;
|
|
1472
|
-
auto decelerationRate = viewProps.decelerationRate;
|
|
1473
|
-
|
|
1474
|
-
// snapToOffsets has priority over snapToInterval (matches React Native behavior)
|
|
1475
|
-
if (viewProps.snapToInterval > 0 && decelerationRate >= 0.99) {
|
|
1476
|
-
snapAlignment = convertSnapToAlignment(viewProps.snapToAlignment);
|
|
1477
|
-
// Generate snap points based on interval
|
|
1478
|
-
// Calculate the content size to determine how many intervals to create
|
|
1479
|
-
float contentLength = viewProps.horizontal
|
|
1480
|
-
? std::max(m_contentSize.width, m_layoutMetrics.frame.size.width) * m_layoutMetrics.pointScaleFactor
|
|
1481
|
-
: std::max(m_contentSize.height, m_layoutMetrics.frame.size.height) * m_layoutMetrics.pointScaleFactor;
|
|
1482
|
-
|
|
1483
|
-
float interval = static_cast<float>(viewProps.snapToInterval) * m_layoutMetrics.pointScaleFactor;
|
|
1484
|
-
|
|
1485
|
-
// Ensure we have a reasonable minimum interval to avoid infinite loops or excessive memory usage
|
|
1486
|
-
if (interval >= 1.0f && contentLength > 0) {
|
|
1487
|
-
// Generate offsets at each interval, but limit the number of snap points to avoid excessive memory usage
|
|
1488
|
-
int snapPointCount = 0;
|
|
1489
|
-
|
|
1490
|
-
for (float offset = 0; offset <= contentLength && snapPointCount < c_maxSnapPoints; offset += interval) {
|
|
1491
|
-
snapToOffsets.Append(offset);
|
|
1492
|
-
snapPointCount++;
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
m_scrollVisual.SetSnapPoints(viewProps.snapToStart, viewProps.snapToEnd, snapToOffsets.GetView(), snapAlignment);
|
|
1498
|
-
}
|
|
1499
1464
|
} // namespace winrt::Microsoft::ReactNative::Composition::implementation
|
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
|
|
19
19
|
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
20
20
|
|
|
21
|
-
using namespace Microsoft::ReactNative::Composition::Experimental;
|
|
22
|
-
|
|
23
21
|
struct ScrollBarComponent;
|
|
24
22
|
|
|
25
23
|
struct ScrollViewComponentView : ScrollViewComponentViewT<ScrollViewComponentView, ViewComponentView> {
|
|
@@ -123,7 +121,6 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
|
|
|
123
121
|
private:
|
|
124
122
|
void updateDecelerationRate(float value) noexcept;
|
|
125
123
|
void updateContentVisualSize() noexcept;
|
|
126
|
-
void updateSnapPoints() noexcept;
|
|
127
124
|
bool scrollToEnd(bool animate) noexcept;
|
|
128
125
|
bool scrollToStart(bool animate) noexcept;
|
|
129
126
|
bool scrollDown(float delta, bool animate) noexcept;
|
|
@@ -137,8 +134,6 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
|
|
|
137
134
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) noexcept;
|
|
138
135
|
void updateShowsHorizontalScrollIndicator(bool value) noexcept;
|
|
139
136
|
void updateShowsVerticalScrollIndicator(bool value) noexcept;
|
|
140
|
-
SnapAlignment convertSnapToAlignment(facebook::react::ScrollViewSnapToAlignment alignment) noexcept;
|
|
141
|
-
winrt::Windows::Foundation::Collections::IVector<float> CreateSnapToOffsets(const std::vector<float> &offsets);
|
|
142
137
|
|
|
143
138
|
facebook::react::Size m_contentSize;
|
|
144
139
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual m_scrollVisual{nullptr};
|
|
@@ -148,9 +143,12 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
|
|
|
148
143
|
m_scrollPositionChangedRevoker{};
|
|
149
144
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollBeginDrag_revoker
|
|
150
145
|
m_scrollBeginDragRevoker{};
|
|
151
|
-
|
|
152
146
|
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollEndDrag_revoker
|
|
153
147
|
m_scrollEndDragRevoker{};
|
|
148
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollMomentumBegin_revoker
|
|
149
|
+
m_scrollMomentumBeginRevoker{};
|
|
150
|
+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollMomentumEnd_revoker
|
|
151
|
+
m_scrollMomentumEndRevoker{};
|
|
154
152
|
|
|
155
153
|
float m_zoomFactor{1.0f};
|
|
156
154
|
bool m_isScrollingFromInertia = false;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#include <Fabric/AbiViewProps.h>
|
|
10
10
|
#include "CompositionDynamicAutomationProvider.h"
|
|
11
11
|
#include "RootComponentView.h"
|
|
12
|
+
#include "UiaHelpers.h"
|
|
12
13
|
|
|
13
14
|
namespace winrt::Microsoft::ReactNative::Composition::implementation {
|
|
14
15
|
|
|
@@ -80,6 +81,16 @@ void SwitchComponentView::updateProps(
|
|
|
80
81
|
m_visualUpdateRequired = true;
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
if (oldViewProps.value != newViewProps.value) {
|
|
85
|
+
if (UiaClientsAreListening()) {
|
|
86
|
+
winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
|
|
87
|
+
EnsureUiaProvider(),
|
|
88
|
+
UIA_ToggleToggleStatePropertyId,
|
|
89
|
+
oldViewProps.value ? ToggleState_On : ToggleState_Off,
|
|
90
|
+
newViewProps.value ? ToggleState_On : ToggleState_Off);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
83
94
|
Super::updateProps(props, oldProps);
|
|
84
95
|
}
|
|
85
96
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include "TextDrawing.h"
|
|
8
8
|
|
|
9
9
|
#include <AutoDraw.h>
|
|
10
|
+
#include <Fabric/platform/react/renderer/graphics/PlatformColorUtils.h>
|
|
10
11
|
#include <Utils/ValueUtils.h>
|
|
11
12
|
#include <unicode.h>
|
|
12
13
|
#include <windows.ui.composition.interop.h>
|
|
@@ -35,11 +36,27 @@ void RenderText(
|
|
|
35
36
|
// to cache and reuse a brush across all text elements instead, taking care to recreate
|
|
36
37
|
// it in the event of device removed.
|
|
37
38
|
winrt::com_ptr<ID2D1SolidColorBrush> brush;
|
|
39
|
+
|
|
40
|
+
// Check if we should use theme-aware default color instead of hardcoded black
|
|
41
|
+
bool useDefaultColor = false;
|
|
38
42
|
if (textAttributes.foregroundColor) {
|
|
43
|
+
auto &color = *textAttributes.foregroundColor;
|
|
44
|
+
// If it's black (or very dark) without explicit PlatformColor, use theme-aware color
|
|
45
|
+
if (color.m_platformColor.empty() && color.m_color.R <= 10 && color.m_color.G <= 10 && color.m_color.B <= 10) {
|
|
46
|
+
useDefaultColor = true;
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
useDefaultColor = true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (useDefaultColor) {
|
|
53
|
+
// Use theme-aware TextFillColorPrimary which adapts to light/dark mode
|
|
54
|
+
auto d2dColor = theme.D2DPlatformColor("TextFillColorPrimary");
|
|
55
|
+
winrt::check_hresult(deviceContext.CreateSolidColorBrush(d2dColor, brush.put()));
|
|
56
|
+
} else {
|
|
57
|
+
// User set explicit color or PlatformColor - use it
|
|
39
58
|
auto color = theme.D2DColor(*textAttributes.foregroundColor);
|
|
40
59
|
winrt::check_hresult(deviceContext.CreateSolidColorBrush(color, brush.put()));
|
|
41
|
-
} else {
|
|
42
|
-
winrt::check_hresult(deviceContext.CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0f), brush.put()));
|
|
43
60
|
}
|
|
44
61
|
|
|
45
62
|
if (textAttributes.textDecorationLineType) {
|
|
@@ -72,12 +89,27 @@ void RenderText(
|
|
|
72
89
|
(fragment.textAttributes.foregroundColor != textAttributes.foregroundColor) ||
|
|
73
90
|
!isnan(fragment.textAttributes.opacity)) {
|
|
74
91
|
winrt::com_ptr<ID2D1SolidColorBrush> fragmentBrush;
|
|
92
|
+
|
|
93
|
+
// Check if we should use theme-aware default color for this fragment
|
|
94
|
+
bool useFragmentDefaultColor = false;
|
|
75
95
|
if (fragment.textAttributes.foregroundColor) {
|
|
96
|
+
auto &color = *fragment.textAttributes.foregroundColor;
|
|
97
|
+
// If it's black (or very dark) without explicit PlatformColor, use theme-aware color
|
|
98
|
+
if (color.m_platformColor.empty() && color.m_color.R <= 10 && color.m_color.G <= 10 && color.m_color.B <= 10) {
|
|
99
|
+
useFragmentDefaultColor = true;
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
useFragmentDefaultColor = true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (useFragmentDefaultColor) {
|
|
106
|
+
// Use theme-aware TextFillColorPrimary which adapts to light/dark mode
|
|
107
|
+
auto d2dColor = theme.D2DPlatformColor("TextFillColorPrimary");
|
|
108
|
+
winrt::check_hresult(deviceContext.CreateSolidColorBrush(d2dColor, fragmentBrush.put()));
|
|
109
|
+
} else {
|
|
110
|
+
// User set explicit color or PlatformColor - use it
|
|
76
111
|
auto color = theme.D2DColor(*fragment.textAttributes.foregroundColor);
|
|
77
112
|
winrt::check_hresult(deviceContext.CreateSolidColorBrush(color, fragmentBrush.put()));
|
|
78
|
-
} else {
|
|
79
|
-
winrt::check_hresult(
|
|
80
|
-
deviceContext.CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black, 1.0f), fragmentBrush.put()));
|
|
81
113
|
}
|
|
82
114
|
|
|
83
115
|
if (fragment.textAttributes.textDecorationLineType) {
|
package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp
CHANGED
|
@@ -8,8 +8,11 @@
|
|
|
8
8
|
#include <AutoDraw.h>
|
|
9
9
|
#include <Fabric/Composition/CompositionDynamicAutomationProvider.h>
|
|
10
10
|
#include <Fabric/Composition/UiaHelpers.h>
|
|
11
|
+
#include <Fabric/platform/react/renderer/graphics/PlatformColorUtils.h>
|
|
12
|
+
#include <Utils/ThemeUtils.h>
|
|
11
13
|
#include <Utils/ValueUtils.h>
|
|
12
14
|
#include <react/renderer/components/textinput/TextInputState.h>
|
|
15
|
+
#include <react/renderer/graphics/HostPlatformColor.h>
|
|
13
16
|
#include <react/renderer/textlayoutmanager/WindowsTextLayoutManager.h>
|
|
14
17
|
#include <tom.h>
|
|
15
18
|
#include <unicode.h>
|
|
@@ -316,8 +319,10 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
316
319
|
|
|
317
320
|
switch (nIndex) {
|
|
318
321
|
case COLOR_WINDOWTEXT:
|
|
319
|
-
if (m_outer->windowsTextInputProps().textAttributes.foregroundColor)
|
|
320
|
-
|
|
322
|
+
if (m_outer->windowsTextInputProps().textAttributes.foregroundColor) {
|
|
323
|
+
auto color = m_outer->theme()->Color(*m_outer->windowsTextInputProps().textAttributes.foregroundColor);
|
|
324
|
+
return RGB(color.R, color.G, color.B);
|
|
325
|
+
}
|
|
321
326
|
// cr = 0x000000FF;
|
|
322
327
|
break;
|
|
323
328
|
case COLOR_WINDOW:
|
|
@@ -326,8 +331,10 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
326
331
|
break;
|
|
327
332
|
|
|
328
333
|
case COLOR_HIGHLIGHT:
|
|
329
|
-
if (m_outer->windowsTextInputProps().selectionColor)
|
|
330
|
-
|
|
334
|
+
if (m_outer->windowsTextInputProps().selectionColor) {
|
|
335
|
+
auto color = m_outer->theme()->Color(*m_outer->windowsTextInputProps().selectionColor);
|
|
336
|
+
return RGB(color.R, color.G, color.B);
|
|
337
|
+
}
|
|
331
338
|
break;
|
|
332
339
|
|
|
333
340
|
case COLOR_HIGHLIGHTTEXT:
|
|
@@ -340,8 +347,9 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
|
|
|
340
347
|
int r = GetRValue(selectionColor);
|
|
341
348
|
int g = GetGValue(selectionColor);
|
|
342
349
|
int b = GetBValue(selectionColor);
|
|
343
|
-
int brightness = (r
|
|
344
|
-
return brightness >
|
|
350
|
+
int brightness = ::Microsoft::ReactNative::CalculateColorBrightness(r, g, b);
|
|
351
|
+
return brightness > ::Microsoft::ReactNative::kCaretSelectionBrightnessThreshold ? RGB(0, 0, 0)
|
|
352
|
+
: RGB(255, 255, 255);
|
|
345
353
|
}
|
|
346
354
|
break;
|
|
347
355
|
|
|
@@ -1077,13 +1085,9 @@ std::string WindowsTextInputComponentView::DefaultHelpText() const noexcept {
|
|
|
1077
1085
|
void WindowsTextInputComponentView::updateCursorColor(
|
|
1078
1086
|
const facebook::react::SharedColor &cursorColor,
|
|
1079
1087
|
const facebook::react::SharedColor &foregroundColor) noexcept {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
m_caretVisual.Brush(theme()->Brush(*foregroundColor));
|
|
1084
|
-
} else {
|
|
1085
|
-
m_caretVisual.Brush(theme()->PlatformBrush("TextControlForeground"));
|
|
1086
|
-
}
|
|
1088
|
+
const auto &props = windowsTextInputProps();
|
|
1089
|
+
auto caretColor = ::Microsoft::ReactNative::GetCaretColor(cursorColor, foregroundColor, props.backgroundColor);
|
|
1090
|
+
m_caretVisual.Brush(theme()->Brush(*caretColor));
|
|
1087
1091
|
}
|
|
1088
1092
|
|
|
1089
1093
|
void WindowsTextInputComponentView::updateProps(
|
|
@@ -1595,6 +1599,8 @@ void WindowsTextInputComponentView::ensureDrawingSurface() noexcept {
|
|
|
1595
1599
|
|
|
1596
1600
|
void WindowsTextInputComponentView::ShowCaret(bool show) noexcept {
|
|
1597
1601
|
ensureVisual();
|
|
1602
|
+
const auto &props = windowsTextInputProps();
|
|
1603
|
+
updateCursorColor(props.cursorColor, props.textAttributes.foregroundColor);
|
|
1598
1604
|
m_caretVisual.IsVisible(show);
|
|
1599
1605
|
}
|
|
1600
1606
|
|
|
@@ -1689,8 +1695,20 @@ void WindowsTextInputComponentView::DrawText() noexcept {
|
|
|
1689
1695
|
auto color = theme()->D2DColor(*props.placeholderTextColor);
|
|
1690
1696
|
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, brush.put()));
|
|
1691
1697
|
} else {
|
|
1692
|
-
|
|
1693
|
-
|
|
1698
|
+
// Use theme-aware placeholder color based on focus state and background
|
|
1699
|
+
// Color selection follows Windows 11 design system semantic colors:
|
|
1700
|
+
// - High contrast: System GrayText for accessibility
|
|
1701
|
+
// - Light backgrounds: Darker grays for better contrast
|
|
1702
|
+
// - Dark backgrounds: Lighter grays for readability
|
|
1703
|
+
winrt::Windows::UI::Color backgroundColor = {};
|
|
1704
|
+
if (facebook::react::isColorMeaningful(props.backgroundColor)) {
|
|
1705
|
+
auto bgColor = (*props.backgroundColor).AsWindowsColor();
|
|
1706
|
+
backgroundColor = bgColor;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
auto placeholderColor = facebook::react::GetTextInputPlaceholderColor(m_hasFocus, backgroundColor);
|
|
1710
|
+
auto d2dColor = theme()->D2DColor(*placeholderColor);
|
|
1711
|
+
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(d2dColor, brush.put()));
|
|
1694
1712
|
}
|
|
1695
1713
|
|
|
1696
1714
|
// Create placeholder text layout
|
|
@@ -166,6 +166,24 @@ void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, bool old
|
|
|
166
166
|
UiaRaiseAutomationPropertyChangedEvent(spProviderSimple.get(), propId, CComVariant(oldValue), CComVariant(newValue));
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, int oldValue, int newValue) noexcept {
|
|
170
|
+
auto spProviderSimple = provider.try_as<IRawElementProviderSimple>();
|
|
171
|
+
|
|
172
|
+
if (spProviderSimple == nullptr || oldValue == newValue || !WasUiaPropertyAdvised(spProviderSimple, propId))
|
|
173
|
+
return;
|
|
174
|
+
|
|
175
|
+
UiaRaiseAutomationPropertyChangedEvent(spProviderSimple.get(), propId, CComVariant(oldValue), CComVariant(newValue));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, long oldValue, long newValue) noexcept {
|
|
179
|
+
auto spProviderSimple = provider.try_as<IRawElementProviderSimple>();
|
|
180
|
+
|
|
181
|
+
if (spProviderSimple == nullptr || oldValue == newValue || !WasUiaPropertyAdvised(spProviderSimple, propId))
|
|
182
|
+
return;
|
|
183
|
+
|
|
184
|
+
UiaRaiseAutomationPropertyChangedEvent(spProviderSimple.get(), propId, CComVariant(oldValue), CComVariant(newValue));
|
|
185
|
+
}
|
|
186
|
+
|
|
169
187
|
void UpdateUiaProperty(
|
|
170
188
|
winrt::IInspectable provider,
|
|
171
189
|
PROPERTYID propId,
|
|
@@ -190,6 +208,29 @@ void UpdateUiaProperty(
|
|
|
190
208
|
UpdateUiaProperty(provider, propId, oldData, newData);
|
|
191
209
|
}
|
|
192
210
|
|
|
211
|
+
void UpdateUiaPropertiesForAnnotation(
|
|
212
|
+
winrt::IInspectable provider,
|
|
213
|
+
const std::optional<facebook::react::AccessibilityAnnotation> &oldAnnotation,
|
|
214
|
+
const std::optional<facebook::react::AccessibilityAnnotation> &newAnnotation) noexcept {
|
|
215
|
+
// if no value fall back to a default value.
|
|
216
|
+
const auto &old_annotation = oldAnnotation.value_or(facebook::react::AccessibilityAnnotation());
|
|
217
|
+
const auto &new_annotation = newAnnotation.value_or(facebook::react::AccessibilityAnnotation());
|
|
218
|
+
|
|
219
|
+
// Update all annotation properties
|
|
220
|
+
UpdateUiaProperty(
|
|
221
|
+
provider,
|
|
222
|
+
UIA_AnnotationAnnotationTypeIdPropertyId,
|
|
223
|
+
GetAnnotationTypeId(old_annotation.typeID),
|
|
224
|
+
GetAnnotationTypeId(new_annotation.typeID));
|
|
225
|
+
|
|
226
|
+
UpdateUiaProperty(
|
|
227
|
+
provider, UIA_AnnotationAnnotationTypeNamePropertyId, old_annotation.typeName, new_annotation.typeName);
|
|
228
|
+
|
|
229
|
+
UpdateUiaProperty(provider, UIA_AnnotationAuthorPropertyId, old_annotation.author, new_annotation.author);
|
|
230
|
+
|
|
231
|
+
UpdateUiaProperty(provider, UIA_AnnotationDateTimePropertyId, old_annotation.dateTime, new_annotation.dateTime);
|
|
232
|
+
}
|
|
233
|
+
|
|
193
234
|
long GetLiveSetting(const std::string &liveRegion) noexcept {
|
|
194
235
|
if (liveRegion == "polite") {
|
|
195
236
|
return LiveSetting::Polite;
|
|
@@ -250,6 +291,190 @@ long GetAnnotationTypeId(const std::string &annotationType) noexcept {
|
|
|
250
291
|
return AnnotationType_Unknown;
|
|
251
292
|
}
|
|
252
293
|
|
|
294
|
+
long GetControlTypeFromString(const std::string &role) noexcept {
|
|
295
|
+
if (role == "adjustable") {
|
|
296
|
+
return UIA_SliderControlTypeId;
|
|
297
|
+
} else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
|
|
298
|
+
return UIA_GroupControlTypeId;
|
|
299
|
+
} else if (role == "button" || role == "imagebutton" || role == "switch" || role == "togglebutton") {
|
|
300
|
+
return UIA_ButtonControlTypeId;
|
|
301
|
+
} else if (role == "checkbox") {
|
|
302
|
+
return UIA_CheckBoxControlTypeId;
|
|
303
|
+
} else if (role == "combobox") {
|
|
304
|
+
return UIA_ComboBoxControlTypeId;
|
|
305
|
+
} else if (role == "alert" || role == "header" || role == "summary" || role == "text") {
|
|
306
|
+
return UIA_TextControlTypeId;
|
|
307
|
+
} else if (role == "image") {
|
|
308
|
+
return UIA_ImageControlTypeId;
|
|
309
|
+
} else if (role == "keyboardkey") {
|
|
310
|
+
return UIA_CustomControlTypeId;
|
|
311
|
+
} else if (role == "link") {
|
|
312
|
+
return UIA_HyperlinkControlTypeId;
|
|
313
|
+
}
|
|
314
|
+
// list and listitem were added by RNW to better support UIA Control Types
|
|
315
|
+
else if (role == "list") {
|
|
316
|
+
return UIA_ListControlTypeId;
|
|
317
|
+
} else if (role == "listitem") {
|
|
318
|
+
return UIA_ListItemControlTypeId;
|
|
319
|
+
} else if (role == "menu") {
|
|
320
|
+
return UIA_MenuControlTypeId;
|
|
321
|
+
} else if (role == "menubar") {
|
|
322
|
+
return UIA_MenuBarControlTypeId;
|
|
323
|
+
} else if (role == "menuitem") {
|
|
324
|
+
return UIA_MenuItemControlTypeId;
|
|
325
|
+
}
|
|
326
|
+
// If role is "none", remove the element from the control tree
|
|
327
|
+
// and expose it as a plain element would in the raw tree.
|
|
328
|
+
else if (role == "none") {
|
|
329
|
+
return UIA_GroupControlTypeId;
|
|
330
|
+
} else if (role == "progressbar") {
|
|
331
|
+
return UIA_ProgressBarControlTypeId;
|
|
332
|
+
} else if (role == "radio") {
|
|
333
|
+
return UIA_RadioButtonControlTypeId;
|
|
334
|
+
} else if (role == "scrollbar") {
|
|
335
|
+
return UIA_ScrollBarControlTypeId;
|
|
336
|
+
} else if (role == "spinbutton") {
|
|
337
|
+
return UIA_SpinnerControlTypeId;
|
|
338
|
+
} else if (role == "splitbutton") {
|
|
339
|
+
return UIA_SplitButtonControlTypeId;
|
|
340
|
+
} else if (role == "tab") {
|
|
341
|
+
return UIA_TabItemControlTypeId;
|
|
342
|
+
} else if (role == "tablist") {
|
|
343
|
+
return UIA_TabControlTypeId;
|
|
344
|
+
} else if (role == "textinput" || role == "searchbox") {
|
|
345
|
+
return UIA_EditControlTypeId;
|
|
346
|
+
} else if (role == "toolbar") {
|
|
347
|
+
return UIA_ToolBarControlTypeId;
|
|
348
|
+
} else if (role == "tree") {
|
|
349
|
+
return UIA_TreeControlTypeId;
|
|
350
|
+
} else if (role == "treeitem") {
|
|
351
|
+
return UIA_TreeItemControlTypeId;
|
|
352
|
+
} else if (role == "pane") {
|
|
353
|
+
return UIA_PaneControlTypeId;
|
|
354
|
+
}
|
|
355
|
+
assert(false);
|
|
356
|
+
return UIA_GroupControlTypeId;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
|
|
360
|
+
switch (role) {
|
|
361
|
+
case facebook::react::Role::Alert:
|
|
362
|
+
return UIA_TextControlTypeId;
|
|
363
|
+
case facebook::react::Role::Application:
|
|
364
|
+
return UIA_WindowControlTypeId;
|
|
365
|
+
case facebook::react::Role::Button:
|
|
366
|
+
return UIA_ButtonControlTypeId;
|
|
367
|
+
case facebook::react::Role::Checkbox:
|
|
368
|
+
return UIA_CheckBoxControlTypeId;
|
|
369
|
+
case facebook::react::Role::Columnheader:
|
|
370
|
+
return UIA_HeaderControlTypeId;
|
|
371
|
+
case facebook::react::Role::Combobox:
|
|
372
|
+
return UIA_ComboBoxControlTypeId;
|
|
373
|
+
case facebook::react::Role::Document:
|
|
374
|
+
return UIA_DocumentControlTypeId;
|
|
375
|
+
case facebook::react::Role::Grid:
|
|
376
|
+
return UIA_GroupControlTypeId;
|
|
377
|
+
case facebook::react::Role::Group:
|
|
378
|
+
return UIA_GroupControlTypeId;
|
|
379
|
+
case facebook::react::Role::Heading:
|
|
380
|
+
return UIA_TextControlTypeId;
|
|
381
|
+
case facebook::react::Role::Img:
|
|
382
|
+
return UIA_ImageControlTypeId;
|
|
383
|
+
case facebook::react::Role::Link:
|
|
384
|
+
return UIA_HyperlinkControlTypeId;
|
|
385
|
+
case facebook::react::Role::List:
|
|
386
|
+
return UIA_ListControlTypeId;
|
|
387
|
+
case facebook::react::Role::Listitem:
|
|
388
|
+
return UIA_ListItemControlTypeId;
|
|
389
|
+
case facebook::react::Role::Menu:
|
|
390
|
+
return UIA_MenuControlTypeId;
|
|
391
|
+
case facebook::react::Role::Menubar:
|
|
392
|
+
return UIA_MenuBarControlTypeId;
|
|
393
|
+
case facebook::react::Role::Menuitem:
|
|
394
|
+
return UIA_MenuItemControlTypeId;
|
|
395
|
+
case facebook::react::Role::None:
|
|
396
|
+
return UIA_GroupControlTypeId;
|
|
397
|
+
case facebook::react::Role::Presentation:
|
|
398
|
+
return UIA_GroupControlTypeId;
|
|
399
|
+
case facebook::react::Role::Progressbar:
|
|
400
|
+
return UIA_ProgressBarControlTypeId;
|
|
401
|
+
case facebook::react::Role::Radio:
|
|
402
|
+
return UIA_RadioButtonControlTypeId;
|
|
403
|
+
case facebook::react::Role::Radiogroup:
|
|
404
|
+
return UIA_GroupControlTypeId;
|
|
405
|
+
case facebook::react::Role::Rowgroup:
|
|
406
|
+
return UIA_GroupControlTypeId;
|
|
407
|
+
case facebook::react::Role::Rowheader:
|
|
408
|
+
return UIA_HeaderControlTypeId;
|
|
409
|
+
case facebook::react::Role::Scrollbar:
|
|
410
|
+
return UIA_ScrollBarControlTypeId;
|
|
411
|
+
case facebook::react::Role::Searchbox:
|
|
412
|
+
return UIA_EditControlTypeId;
|
|
413
|
+
case facebook::react::Role::Separator:
|
|
414
|
+
return UIA_SeparatorControlTypeId;
|
|
415
|
+
case facebook::react::Role::Slider:
|
|
416
|
+
return UIA_SliderControlTypeId;
|
|
417
|
+
case facebook::react::Role::Spinbutton:
|
|
418
|
+
return UIA_SpinnerControlTypeId;
|
|
419
|
+
case facebook::react::Role::Status:
|
|
420
|
+
return UIA_StatusBarControlTypeId;
|
|
421
|
+
case facebook::react::Role::Summary:
|
|
422
|
+
return UIA_GroupControlTypeId;
|
|
423
|
+
case facebook::react::Role::Switch:
|
|
424
|
+
return UIA_ButtonControlTypeId;
|
|
425
|
+
case facebook::react::Role::Tab:
|
|
426
|
+
return UIA_TabItemControlTypeId;
|
|
427
|
+
case facebook::react::Role::Table:
|
|
428
|
+
return UIA_TableControlTypeId;
|
|
429
|
+
case facebook::react::Role::Tablist:
|
|
430
|
+
return UIA_TabControlTypeId;
|
|
431
|
+
case facebook::react::Role::Tabpanel:
|
|
432
|
+
return UIA_TabControlTypeId;
|
|
433
|
+
case facebook::react::Role::Timer:
|
|
434
|
+
return UIA_ButtonControlTypeId;
|
|
435
|
+
case facebook::react::Role::Toolbar:
|
|
436
|
+
return UIA_ToolBarControlTypeId;
|
|
437
|
+
case facebook::react::Role::Tooltip:
|
|
438
|
+
return UIA_ToolTipControlTypeId;
|
|
439
|
+
case facebook::react::Role::Tree:
|
|
440
|
+
return UIA_TreeControlTypeId;
|
|
441
|
+
case facebook::react::Role::Treegrid:
|
|
442
|
+
return UIA_TreeControlTypeId;
|
|
443
|
+
case facebook::react::Role::Treeitem:
|
|
444
|
+
return UIA_TreeItemControlTypeId;
|
|
445
|
+
}
|
|
446
|
+
return UIA_GroupControlTypeId;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
long GetHeadingLevel(int headingLevel, const std::string &strRole, const facebook::react::Role &role) noexcept {
|
|
450
|
+
if (strRole != "header" && role != facebook::react::Role::Heading) {
|
|
451
|
+
return HeadingLevel_None;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
switch (headingLevel) {
|
|
455
|
+
case 1:
|
|
456
|
+
return HeadingLevel1;
|
|
457
|
+
case 2:
|
|
458
|
+
return HeadingLevel2;
|
|
459
|
+
case 3:
|
|
460
|
+
return HeadingLevel3;
|
|
461
|
+
case 4:
|
|
462
|
+
return HeadingLevel4;
|
|
463
|
+
case 5:
|
|
464
|
+
return HeadingLevel5;
|
|
465
|
+
case 6:
|
|
466
|
+
return HeadingLevel6;
|
|
467
|
+
case 7:
|
|
468
|
+
return HeadingLevel7;
|
|
469
|
+
case 8:
|
|
470
|
+
return HeadingLevel8;
|
|
471
|
+
case 9:
|
|
472
|
+
return HeadingLevel9;
|
|
473
|
+
default:
|
|
474
|
+
return HeadingLevel_None;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
253
478
|
bool accessibilityAnnotationHasValue(
|
|
254
479
|
const std::optional<facebook::react::AccessibilityAnnotation> &annotation) noexcept {
|
|
255
480
|
return annotation.has_value() &&
|
|
@@ -29,6 +29,18 @@ void UpdateUiaProperty(
|
|
|
29
29
|
bool oldValue,
|
|
30
30
|
bool newValue) noexcept;
|
|
31
31
|
|
|
32
|
+
void UpdateUiaProperty(
|
|
33
|
+
winrt::Windows::Foundation::IInspectable provider,
|
|
34
|
+
PROPERTYID propId,
|
|
35
|
+
int oldValue,
|
|
36
|
+
int newValue) noexcept;
|
|
37
|
+
|
|
38
|
+
void UpdateUiaProperty(
|
|
39
|
+
winrt::Windows::Foundation::IInspectable provider,
|
|
40
|
+
PROPERTYID propId,
|
|
41
|
+
long oldValue,
|
|
42
|
+
long newValue) noexcept;
|
|
43
|
+
|
|
32
44
|
void UpdateUiaProperty(
|
|
33
45
|
winrt::Windows::Foundation::IInspectable provider,
|
|
34
46
|
PROPERTYID propId,
|
|
@@ -41,10 +53,21 @@ void UpdateUiaProperty(
|
|
|
41
53
|
const std::optional<std::string> &oldValue,
|
|
42
54
|
const std::optional<std::string> &newValue) noexcept;
|
|
43
55
|
|
|
56
|
+
void UpdateUiaPropertiesForAnnotation(
|
|
57
|
+
winrt::Windows::Foundation::IInspectable provider,
|
|
58
|
+
const std::optional<facebook::react::AccessibilityAnnotation> &oldAnnotation,
|
|
59
|
+
const std::optional<facebook::react::AccessibilityAnnotation> &newAnnotation) noexcept;
|
|
60
|
+
|
|
44
61
|
long GetLiveSetting(const std::string &liveRegion) noexcept;
|
|
45
62
|
|
|
46
63
|
long GetAnnotationTypeId(const std::string &annotationType) noexcept;
|
|
47
64
|
|
|
65
|
+
long GetControlTypeFromRole(const facebook::react::Role &role) noexcept;
|
|
66
|
+
|
|
67
|
+
long GetControlTypeFromString(const std::string &role) noexcept;
|
|
68
|
+
|
|
69
|
+
long GetHeadingLevel(int headingLevel, const std::string &strRole, const facebook::react::Role &role) noexcept;
|
|
70
|
+
|
|
48
71
|
bool accessibilityAnnotationHasValue(
|
|
49
72
|
const std::optional<facebook::react::AccessibilityAnnotation> &annotation) noexcept;
|
|
50
73
|
|
|
@@ -66,7 +66,8 @@ FabricUIManager::~FabricUIManager() {
|
|
|
66
66
|
void FabricUIManager::installFabricUIManager() noexcept {
|
|
67
67
|
std::lock_guard<std::mutex> schedulerLock(m_schedulerMutex);
|
|
68
68
|
|
|
69
|
-
facebook::react::ContextContainer
|
|
69
|
+
std::shared_ptr<const facebook::react::ContextContainer> contextContainer =
|
|
70
|
+
std::make_shared<facebook::react::ContextContainer>();
|
|
70
71
|
|
|
71
72
|
// This allows access to our ReactContext from the contextContainer thats passed around the fabric codebase
|
|
72
73
|
contextContainer->insert("MSRN.ReactContext", m_context);
|
|
@@ -97,8 +98,9 @@ void FabricUIManager::installFabricUIManager() noexcept {
|
|
|
97
98
|
};
|
|
98
99
|
|
|
99
100
|
toolbox.contextContainer = contextContainer;
|
|
100
|
-
toolbox.componentRegistryFactory =
|
|
101
|
-
|
|
101
|
+
toolbox.componentRegistryFactory =
|
|
102
|
+
[](facebook::react::EventDispatcher::Weak const &eventDispatcher,
|
|
103
|
+
std::shared_ptr<const facebook::react::ContextContainer> const &contextContainer)
|
|
102
104
|
-> facebook::react::ComponentDescriptorRegistry::Shared {
|
|
103
105
|
auto providerRegistry =
|
|
104
106
|
WindowsComponentDescriptorRegistry::FromProperties(
|