react-native-windows 0.74.46 → 0.74.47

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.
Files changed (41) hide show
  1. package/Libraries/Components/View/View.windows.js +13 -5
  2. package/Libraries/Components/View/ViewAccessibility.d.ts +67 -0
  3. package/Libraries/Components/View/ViewPropTypes.windows.js +2 -0
  4. package/Libraries/NativeComponent/BaseViewConfig.windows.js +4 -0
  5. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +1 -1
  6. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +47 -0
  7. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +1 -0
  8. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +81 -94
  9. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +1 -1
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp +115 -0
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h +41 -0
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +319 -0
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h +59 -0
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +47 -0
  15. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +43 -34
  16. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +11 -0
  17. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +149 -17
  18. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +5 -0
  19. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp +2 -1
  20. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h +2 -1
  21. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +43 -1
  22. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +27 -2
  23. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +22 -4
  24. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h +16 -3
  25. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +24 -0
  26. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +4 -0
  27. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h +20 -0
  28. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +133 -32
  29. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +12 -0
  30. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +1 -3
  31. package/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj +1 -1
  32. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml +1 -1
  33. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml +1 -1
  34. package/Microsoft.ReactNative.Managed.CodeGen/packages.lock.json +3 -3
  35. package/PropertySheets/External/Microsoft.ReactNative.WindowsSdk.Default.props +4 -4
  36. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  37. package/Scripts/Tfs/Start-TestServers.ps1 +2 -1
  38. package/Scripts/rnw-dependencies.ps1 +38 -25
  39. package/Shared/Shared.vcxitems +6 -0
  40. package/Shared/Shared.vcxitems.filters +8 -0
  41. package/package.json +3 -3
@@ -64,6 +64,14 @@ void ParagraphComponentView::updateProps(
64
64
  updateTextAlignment(newViewProps.textAttributes.alignment);
65
65
  }
66
66
 
67
+ if (oldViewProps.paragraphAttributes.ellipsizeMode != newViewProps.paragraphAttributes.ellipsizeMode) {
68
+ m_textLayout = nullptr;
69
+ }
70
+
71
+ if (oldViewProps.paragraphAttributes.adjustsFontSizeToFit != newViewProps.paragraphAttributes.adjustsFontSizeToFit) {
72
+ m_textLayout = nullptr;
73
+ }
74
+
67
75
  Super::updateProps(props, oldProps);
68
76
  }
69
77
 
@@ -73,7 +81,7 @@ void ParagraphComponentView::updateState(
73
81
  const auto &newState = *std::static_pointer_cast<facebook::react::ParagraphShadowNode::ConcreteState const>(state);
74
82
 
75
83
  m_attributedStringBox = facebook::react::AttributedStringBox(newState.getData().attributedString);
76
- m_paragraphAttributes = {}; // TODO
84
+ m_paragraphAttributes = facebook::react::ParagraphAttributes(newState.getData().paragraphAttributes);
77
85
 
78
86
  m_textLayout = nullptr;
79
87
  }
@@ -97,7 +105,7 @@ void ParagraphComponentView::FinalizeUpdates(
97
105
 
98
106
  facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPoint(
99
107
  facebook::react::Point pt) noexcept {
100
- if (m_attributedStringBox.getValue().getFragments().size()) {
108
+ if (m_attributedStringBox.getValue().getFragments().size() && m_textLayout) {
101
109
  BOOL isTrailingHit = false;
102
110
  BOOL isInside = false;
103
111
  DWRITE_HIT_TEST_METRICS metrics;
@@ -120,35 +128,8 @@ facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPo
120
128
 
121
129
  void ParagraphComponentView::updateTextAlignment(
122
130
  const std::optional<facebook::react::TextAlignment> &fbAlignment) noexcept {
131
+ // Reset text layout to force recreation with new alignment
123
132
  m_textLayout = nullptr;
124
- if (!m_textLayout)
125
- return;
126
-
127
- DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
128
- if (fbAlignment) {
129
- switch (*fbAlignment) {
130
- case facebook::react::TextAlignment::Center:
131
- alignment = DWRITE_TEXT_ALIGNMENT_CENTER;
132
- break;
133
- case facebook::react::TextAlignment::Justified:
134
- alignment = DWRITE_TEXT_ALIGNMENT_JUSTIFIED;
135
- break;
136
- case facebook::react::TextAlignment::Left:
137
- alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
138
- break;
139
- case facebook::react::TextAlignment::Right:
140
- alignment = DWRITE_TEXT_ALIGNMENT_TRAILING;
141
- break;
142
- // TODO use LTR values
143
- case facebook::react::TextAlignment::Natural:
144
- alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
145
- break;
146
- default:
147
- assert(false);
148
- }
149
- }
150
- // TODO
151
- // m_textFormat->SetTextAlignment(alignment);
152
133
  }
153
134
 
154
135
  void ParagraphComponentView::OnRenderingDeviceLost() noexcept {
@@ -160,7 +141,6 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
160
141
 
161
142
  // TODO
162
143
  // updateTextAlignment(paragraphProps.textAttributes.alignment);
163
-
164
144
  if (!m_textLayout) {
165
145
  facebook::react::LayoutConstraints constraints;
166
146
  constraints.maximumSize.width =
@@ -168,7 +148,38 @@ void ParagraphComponentView::updateVisualBrush() noexcept {
168
148
  constraints.maximumSize.height =
169
149
  m_layoutMetrics.frame.size.height - m_layoutMetrics.contentInsets.top - m_layoutMetrics.contentInsets.bottom;
170
150
 
171
- facebook::react::TextLayoutManager::GetTextLayout(m_attributedStringBox, {} /*TODO*/, constraints, m_textLayout);
151
+ facebook::react::TextLayoutManager::GetTextLayout(
152
+ m_attributedStringBox, m_paragraphAttributes, constraints, m_textLayout);
153
+
154
+ // Apply text alignment after creating the text layout
155
+ if (m_textLayout) {
156
+ const auto &props = paragraphProps();
157
+ DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
158
+ if (props.textAttributes.alignment) {
159
+ switch (*props.textAttributes.alignment) {
160
+ case facebook::react::TextAlignment::Center:
161
+ alignment = DWRITE_TEXT_ALIGNMENT_CENTER;
162
+ break;
163
+ case facebook::react::TextAlignment::Justified:
164
+ alignment = DWRITE_TEXT_ALIGNMENT_JUSTIFIED;
165
+ break;
166
+ case facebook::react::TextAlignment::Left:
167
+ alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
168
+ break;
169
+ case facebook::react::TextAlignment::Right:
170
+ alignment = DWRITE_TEXT_ALIGNMENT_TRAILING;
171
+ break;
172
+ case facebook::react::TextAlignment::Natural:
173
+ alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
174
+ break;
175
+ default:
176
+ alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
177
+ break;
178
+ }
179
+ }
180
+ winrt::check_hresult(m_textLayout->SetTextAlignment(alignment));
181
+ }
182
+
172
183
  requireNewBrush = true;
173
184
  }
174
185
 
@@ -270,9 +281,7 @@ void ParagraphComponentView::DrawText() noexcept {
270
281
  d2dDeviceContext->Clear(
271
282
  viewProps()->backgroundColor ? theme()->D2DColor(*viewProps()->backgroundColor)
272
283
  : D2D1::ColorF(D2D1::ColorF::Black, 0.0f));
273
-
274
284
  const auto &props = paragraphProps();
275
-
276
285
  RenderText(
277
286
  *d2dDeviceContext,
278
287
  *m_textLayout,
@@ -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
 
@@ -14,6 +14,7 @@
14
14
  #include <winrt/Microsoft.UI.Input.h>
15
15
  #include <winrt/Windows.System.h>
16
16
  #include <winrt/Windows.UI.h>
17
+ #include "../Composition.Input.h"
17
18
  #include "../CompositionHelpers.h"
18
19
  #include "../RootComponentView.h"
19
20
  #include "JSValueReader.h"
@@ -212,15 +213,14 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
212
213
 
213
214
  //@cmember Get mouse capture
214
215
  void TxSetCapture(BOOL fCapture) override {
215
- // assert(false);
216
- // TODO capture?
217
- /*
216
+ auto mousePointer = winrt::make<winrt::Microsoft::ReactNative::Composition::Input::implementation::Pointer>(
217
+ winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Mouse, 1 /* 1 is Mouse PointerId*/);
218
+
218
219
  if (fCapture) {
219
- ::SetCapture(m_hwndHost);
220
+ m_outer->CapturePointer(mousePointer);
220
221
  } else {
221
- ::ReleaseCapture();
222
+ m_outer->ReleasePointerCapture(mousePointer);
222
223
  }
223
- */
224
224
  }
225
225
 
226
226
  //@cmember Set the focus to the text window
@@ -319,20 +319,30 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
319
319
  return (*m_outer->windowsTextInputProps().textAttributes.foregroundColor).AsColorRefNoAlpha();
320
320
  // cr = 0x000000FF;
321
321
  break;
322
-
323
322
  case COLOR_WINDOW:
324
323
  if (m_outer->viewProps()->backgroundColor)
325
324
  return (*m_outer->viewProps()->backgroundColor).AsColorRefNoAlpha();
326
325
  break;
327
- // case COLOR_HIGHLIGHT:
328
- // cr = RGB(0, 0, 255);
329
- // cr = 0x0000ffFF;
330
- // break;
331
326
 
332
- // case COLOR_HIGHLIGHTTEXT:
333
- // cr = RGB(255, 0, 0);
334
- // cr = 0xFFFFFFFF;
335
- // break;
327
+ case COLOR_HIGHLIGHT:
328
+ if (m_outer->windowsTextInputProps().selectionColor)
329
+ return (*m_outer->windowsTextInputProps().selectionColor).AsColorRefNoAlpha();
330
+ break;
331
+
332
+ case COLOR_HIGHLIGHTTEXT:
333
+ // For selected text color, we use the same color as the selection background
334
+ // or the text color if selection color is not specified
335
+ if (m_outer->windowsTextInputProps().selectionColor) {
336
+ // Calculate appropriate text color based on selection background
337
+ auto selectionColor = (*m_outer->windowsTextInputProps().selectionColor).AsColorRefNoAlpha();
338
+ // Use white text for dark selection, black text for light selection
339
+ int r = GetRValue(selectionColor);
340
+ int g = GetGValue(selectionColor);
341
+ int b = GetBValue(selectionColor);
342
+ int brightness = (r * 299 + g * 587 + b * 114) / 1000;
343
+ return brightness > 125 ? RGB(0, 0, 0) : RGB(255, 255, 255);
344
+ }
345
+ break;
336
346
 
337
347
  // case COLOR_GRAYTEXT:
338
348
  // cr = RGB(128, 128, 128);
@@ -463,6 +473,13 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
463
473
  WindowsTextInputComponentView *m_outer;
464
474
  };
465
475
 
476
+ int WINAPI
477
+ AutoCorrectOffCallback(LANGID langid, const WCHAR *pszBefore, WCHAR *pszAfter, LONG cchAfter, LONG *pcchReplaced) {
478
+ wcsncpy_s(pszAfter, cchAfter, pszBefore, _TRUNCATE);
479
+ *pcchReplaced = static_cast<LONG>(wcslen(pszAfter));
480
+ return ATP_CHANGE;
481
+ }
482
+
466
483
  facebook::react::AttributedString WindowsTextInputComponentView::getAttributedString() const {
467
484
  // Use BaseTextShadowNode to get attributed string from children
468
485
 
@@ -986,7 +1003,10 @@ void WindowsTextInputComponentView::updateProps(
986
1003
  if (!facebook::react::floatEquality(
987
1004
  oldTextInputProps.textAttributes.fontSize, newTextInputProps.textAttributes.fontSize) ||
988
1005
  (oldTextInputProps.textAttributes.allowFontScaling != newTextInputProps.textAttributes.allowFontScaling) ||
989
- oldTextInputProps.textAttributes.fontWeight != newTextInputProps.textAttributes.fontWeight) {
1006
+ oldTextInputProps.textAttributes.fontWeight != newTextInputProps.textAttributes.fontWeight ||
1007
+ !facebook::react::floatEquality(
1008
+ oldTextInputProps.textAttributes.letterSpacing, newTextInputProps.textAttributes.letterSpacing) ||
1009
+ oldTextInputProps.textAttributes.fontFamily != newTextInputProps.textAttributes.fontFamily) {
990
1010
  m_propBitsMask |= TXTBIT_CHARFORMATCHANGE;
991
1011
  m_propBits |= TXTBIT_CHARFORMATCHANGE;
992
1012
  }
@@ -1051,6 +1071,23 @@ void WindowsTextInputComponentView::updateProps(
1051
1071
  m_propBits |= TXTBIT_PARAFORMATCHANGE;
1052
1072
  }
1053
1073
 
1074
+ // Please note: spellcheck performs both red lines and autocorrect as per windows behaviour
1075
+ bool shouldUpdateSpellCheck =
1076
+ (!oldProps || (oldTextInputProps.spellCheck != newTextInputProps.spellCheck) ||
1077
+ (oldTextInputProps.autoCorrect != newTextInputProps.autoCorrect));
1078
+
1079
+ if (shouldUpdateSpellCheck) {
1080
+ bool effectiveSpellCheck = newTextInputProps.spellCheck || newTextInputProps.autoCorrect;
1081
+ updateSpellCheck(effectiveSpellCheck);
1082
+ }
1083
+ if (!oldProps || oldTextInputProps.autoCorrect != newTextInputProps.autoCorrect) {
1084
+ updateAutoCorrect(newTextInputProps.autoCorrect);
1085
+ }
1086
+
1087
+ if (oldTextInputProps.selectionColor != newTextInputProps.selectionColor) {
1088
+ m_needsRedraw = true;
1089
+ }
1090
+
1054
1091
  UpdatePropertyBits();
1055
1092
  }
1056
1093
 
@@ -1136,6 +1173,49 @@ void WindowsTextInputComponentView::updateLayoutMetrics(
1136
1173
  m_imgHeight = newHeight;
1137
1174
  }
1138
1175
 
1176
+ std::pair<float, float> WindowsTextInputComponentView::GetContentSize() const noexcept {
1177
+ if (!m_textServices)
1178
+ return {0.0f, 0.0f};
1179
+
1180
+ // Get a device context for measurement
1181
+ HDC hdc = GetDC(nullptr);
1182
+ if (!hdc)
1183
+ return {0.0f, 0.0f};
1184
+
1185
+ // Use the layout width as the constraint (always multiline)
1186
+ float availableWidth = m_layoutMetrics.frame.size.width;
1187
+ float scale = m_layoutMetrics.pointScaleFactor;
1188
+ float dpi = m_layoutMetrics.pointScaleFactor * GetDpiForSystem();
1189
+ constexpr float HIMETRIC_PER_INCH = 2540.0f;
1190
+
1191
+ SIZE extentHimetric = {
1192
+ static_cast<LONG>(availableWidth * scale * HIMETRIC_PER_INCH / dpi),
1193
+ static_cast<LONG>(std::numeric_limits<LONG>::max() * HIMETRIC_PER_INCH / dpi)};
1194
+
1195
+ SIZE naturalSize = {0, 0};
1196
+
1197
+ HRESULT hr = m_textServices->TxGetNaturalSize(
1198
+ DVASPECT_CONTENT,
1199
+ hdc,
1200
+ nullptr,
1201
+ nullptr,
1202
+ static_cast<DWORD>(TXTNS_FITTOCONTENTWSP),
1203
+ reinterpret_cast<SIZEL *>(&extentHimetric),
1204
+ &naturalSize.cx,
1205
+ &naturalSize.cy);
1206
+
1207
+ ReleaseDC(nullptr, hdc);
1208
+
1209
+ if (FAILED(hr)) {
1210
+ return {0.0f, 0.0f};
1211
+ }
1212
+
1213
+ float contentWidth = static_cast<float>(naturalSize.cx) / scale;
1214
+ float contentHeight = static_cast<float>(naturalSize.cy) / scale;
1215
+
1216
+ return {contentWidth, contentHeight};
1217
+ }
1218
+
1139
1219
  // When we are notified by RichEdit that the text changed, we need to notify JS
1140
1220
  void WindowsTextInputComponentView::OnTextUpdated() noexcept {
1141
1221
  auto data = m_state->getData();
@@ -1154,6 +1234,13 @@ void WindowsTextInputComponentView::OnTextUpdated() noexcept {
1154
1234
  onChangeArgs.text = GetTextFromRichEdit();
1155
1235
  onChangeArgs.eventCount = ++m_nativeEventCount;
1156
1236
  emitter->onChange(onChangeArgs);
1237
+ if (windowsTextInputProps().multiline) {
1238
+ auto [contentWidth, contentHeight] = GetContentSize();
1239
+ facebook::react::WindowsTextInputEventEmitter::OnContentSizeChange onContentSizeChangeArgs;
1240
+ onContentSizeChangeArgs.contentSize.width = contentWidth;
1241
+ onContentSizeChangeArgs.contentSize.height = contentHeight;
1242
+ emitter->onContentSizeChange(onContentSizeChangeArgs);
1243
+ }
1157
1244
  }
1158
1245
 
1159
1246
  if (m_uiaProvider) {
@@ -1228,6 +1315,13 @@ void WindowsTextInputComponentView::onMounted() noexcept {
1228
1315
  m_propBits |= TXTBIT_CHARFORMATCHANGE;
1229
1316
  }
1230
1317
  InternalFinalize();
1318
+
1319
+ // Handle autoFocus property - focus the component when mounted if autoFocus is true
1320
+ if (windowsTextInputProps().autoFocus) {
1321
+ if (auto root = rootComponentView()) {
1322
+ root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
1323
+ }
1324
+ }
1231
1325
  }
1232
1326
 
1233
1327
  std::optional<std::string> WindowsTextInputComponentView::getAccessiblityValue() noexcept {
@@ -1272,9 +1366,12 @@ void WindowsTextInputComponentView::UpdateCharFormat() noexcept {
1272
1366
 
1273
1367
  // set font size -- 15 to convert twips to pt
1274
1368
  const auto &props = windowsTextInputProps();
1275
- float fontSize = m_fontSizeMultiplier *
1369
+ float fontSize =
1276
1370
  (std::isnan(props.textAttributes.fontSize) ? facebook::react::TextAttributes::defaultTextAttributes().fontSize
1277
1371
  : props.textAttributes.fontSize);
1372
+
1373
+ fontSize *= m_fontSizeMultiplier;
1374
+
1278
1375
  // TODO get fontSize from props.textAttributes, or defaultTextAttributes, or fragment?
1279
1376
  cfNew.dwMask |= CFM_SIZE;
1280
1377
  cfNew.yHeight = static_cast<LONG>(fontSize * 15);
@@ -1545,4 +1642,39 @@ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
1545
1642
  }
1546
1643
  }
1547
1644
 
1645
+ void WindowsTextInputComponentView::updateLetterSpacing(float letterSpacing) noexcept {
1646
+ CHARFORMAT2W cf = {};
1647
+ cf.cbSize = sizeof(CHARFORMAT2W);
1648
+ cf.dwMask = CFM_SPACING;
1649
+ cf.sSpacing = static_cast<SHORT>(letterSpacing * 20); // Convert to TWIPS
1650
+
1651
+ LRESULT res;
1652
+
1653
+ // Apply to all existing text like placeholder
1654
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_ALL, reinterpret_cast<LPARAM>(&cf), &res));
1655
+
1656
+ // Apply to future text input
1657
+ winrt::check_hresult(
1658
+ m_textServices->TxSendMessage(EM_SETCHARFORMAT, SCF_SELECTION, reinterpret_cast<LPARAM>(&cf), &res));
1659
+ }
1660
+
1661
+ void WindowsTextInputComponentView::updateAutoCorrect(bool enable) noexcept {
1662
+ LRESULT lresult;
1663
+ winrt::check_hresult(m_textServices->TxSendMessage(
1664
+ EM_SETAUTOCORRECTPROC, enable ? 0 : reinterpret_cast<WPARAM>(AutoCorrectOffCallback), 0, &lresult));
1665
+ }
1666
+
1667
+ void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
1668
+ LRESULT currentLangOptions;
1669
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_GETLANGOPTIONS, 0, 0, &currentLangOptions));
1670
+
1671
+ DWORD newLangOptions = static_cast<DWORD>(currentLangOptions);
1672
+ if (enable) {
1673
+ newLangOptions |= IMF_SPELLCHECKING;
1674
+ }
1675
+
1676
+ LRESULT lresult;
1677
+ winrt::check_hresult(
1678
+ m_textServices->TxSendMessage(EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0, &lresult));
1679
+ }
1548
1680
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -97,6 +97,7 @@ struct WindowsTextInputComponentView
97
97
  void UpdateText(const std::string &str) noexcept;
98
98
  void OnTextUpdated() noexcept;
99
99
  void OnSelectionChanged(LONG start, LONG end) noexcept;
100
+ std::pair<float, float> GetContentSize() const noexcept;
100
101
  std::string GetTextFromRichEdit() const noexcept;
101
102
  void updateCursorColor(
102
103
  const facebook::react::SharedColor &cursorColor,
@@ -110,6 +111,10 @@ struct WindowsTextInputComponentView
110
111
  const std::string &previousCapitalizationType,
111
112
  const std::string &newcapitalizationType) noexcept;
112
113
 
114
+ void updateLetterSpacing(float letterSpacing) noexcept;
115
+ void updateAutoCorrect(bool value) noexcept;
116
+ void updateSpellCheck(bool value) noexcept;
117
+
113
118
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
114
119
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
115
120
  winrt::Microsoft::ReactNative::Composition::Experimental::IDrawingSurfaceBrush m_drawingSurface{nullptr};
@@ -24,6 +24,7 @@ WindowsTextInputProps::WindowsTextInputProps(
24
24
  */
25
25
 
26
26
  allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
27
+ autoCorrect(convertRawProp(context, rawProps, "autoCorrect", sourceProps.autoCorrect, {true})),
27
28
  clearTextOnFocus(convertRawProp(context, rawProps, "clearTextOnFocus", sourceProps.clearTextOnFocus, {false})),
28
29
  editable(convertRawProp(context, rawProps, "editable", sourceProps.editable, {true})),
29
30
  maxLength(convertRawProp(context, rawProps, "maxLength", sourceProps.maxLength, {0})),
@@ -36,7 +37,7 @@ WindowsTextInputProps::WindowsTextInputProps(
36
37
  selection(convertRawProp(context, rawProps, "selection", sourceProps.selection, {})),
37
38
  selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
38
39
  selectTextOnFocus(convertRawProp(context, rawProps, "selectTextOnFocus", sourceProps.selectTextOnFocus, {false})),
39
- spellCheck(convertRawProp(context, rawProps, "spellCheck", sourceProps.spellCheck, {false})),
40
+ spellCheck(convertRawProp(context, rawProps, "spellCheck", sourceProps.spellCheck, {true})),
40
41
  text(convertRawProp(context, rawProps, "text", sourceProps.text, {})),
41
42
  mostRecentEventCount(
42
43
  convertRawProp(context, rawProps, "mostRecentEventCount", sourceProps.mostRecentEventCount, {0})),
@@ -97,6 +97,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
97
97
  setProp(const PropsParserContext &context, RawPropsPropNameHash hash, const char *propName, RawValue const &value);
98
98
 
99
99
  bool allowFontScaling{true};
100
+ bool autoCorrect{true};
100
101
  bool clearTextOnFocus{false};
101
102
  bool editable{true};
102
103
  int maxLength{0};
@@ -108,7 +109,7 @@ class WindowsTextInputProps final : public ViewProps, public BaseTextProps {
108
109
  CompWindowsTextInputSelectionStruct selection{};
109
110
  SharedColor selectionColor{};
110
111
  bool selectTextOnFocus{false};
111
- bool spellCheck{false};
112
+ bool spellCheck{true};
112
113
  std::string text{};
113
114
  int mostRecentEventCount{0};
114
115
  bool secureTextEntry{false};
@@ -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,
@@ -180,6 +198,16 @@ void UpdateUiaProperty(
180
198
  spProviderSimple.get(), propId, CComVariant(oldValue.c_str()), CComVariant(newValue.c_str()));
181
199
  }
182
200
 
201
+ void UpdateUiaProperty(
202
+ winrt::IInspectable provider,
203
+ PROPERTYID propId,
204
+ const std::optional<std::string> &oldValue,
205
+ const std::optional<std::string> &newValue) noexcept {
206
+ std::string oldData = oldValue.value_or("");
207
+ std::string newData = newValue.value_or("");
208
+ UpdateUiaProperty(provider, propId, oldData, newData);
209
+ }
210
+
183
211
  long GetLiveSetting(const std::string &liveRegion) noexcept {
184
212
  if (liveRegion == "polite") {
185
213
  return LiveSetting::Polite;
@@ -254,4 +282,18 @@ ToggleState GetToggleState(const std::optional<facebook::react::AccessibilitySta
254
282
  return ToggleState::ToggleState_Off;
255
283
  }
256
284
 
257
- } // namespace winrt::Microsoft::ReactNative::implementation
285
+ TextDecorationLineStyle GetTextDecorationLineStyle(facebook::react::TextDecorationStyle style) noexcept {
286
+ if (style == facebook::react::TextDecorationStyle::Dashed) {
287
+ return TextDecorationLineStyle_Dash;
288
+ } else if (style == facebook::react::TextDecorationStyle::Dotted) {
289
+ return TextDecorationLineStyle_Dot;
290
+ } else if (style == facebook::react::TextDecorationStyle::Double) {
291
+ return TextDecorationLineStyle_Double;
292
+ } else if (style == facebook::react::TextDecorationStyle::Solid) {
293
+ return TextDecorationLineStyle_Single;
294
+ } else {
295
+ return TextDecorationLineStyle_Single;
296
+ }
297
+ }
298
+
299
+ } // namespace winrt::Microsoft::ReactNative::implementation
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include <Fabric/ComponentView.h>
4
4
  #include <Fabric/Composition/CompositionDynamicAutomationProvider.h>
5
+ #include <Fabric/Composition/ParagraphComponentView.h>
5
6
  #include <Fabric/ReactTaggedView.h>
6
7
  #include <UIAutomation.h>
7
8
 
@@ -22,14 +23,36 @@ HRESULT UiaGetBoundingRectangleHelper(::Microsoft::ReactNative::ReactTaggedView
22
23
 
23
24
  HRESULT UiaSetFocusHelper(::Microsoft::ReactNative::ReactTaggedView &view) noexcept;
24
25
 
25
- void UpdateUiaProperty(winrt::IInspectable provider, PROPERTYID propId, bool oldValue, bool newValue) noexcept;
26
+ void UpdateUiaProperty(
27
+ winrt::Windows::Foundation::IInspectable provider,
28
+ PROPERTYID propId,
29
+ bool oldValue,
30
+ bool newValue) noexcept;
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;
26
43
 
27
44
  void UpdateUiaProperty(
28
- winrt::IInspectable provider,
45
+ winrt::Windows::Foundation::IInspectable provider,
29
46
  PROPERTYID propId,
30
47
  const std::string &oldValue,
31
48
  const std::string &newValue) noexcept;
32
49
 
50
+ void UpdateUiaProperty(
51
+ winrt::Windows::Foundation::IInspectable provider,
52
+ PROPERTYID propId,
53
+ const std::optional<std::string> &oldValue,
54
+ const std::optional<std::string> &newValue) noexcept;
55
+
33
56
  long GetLiveSetting(const std::string &liveRegion) noexcept;
34
57
 
35
58
  void DispatchAccessibilityAction(::Microsoft::ReactNative::ReactTaggedView &view, const std::string &action) noexcept;
@@ -41,4 +64,6 @@ void AddSelectionItemsToContainer(CompositionDynamicAutomationProvider *provider
41
64
  void RemoveSelectionItemsFromContainer(CompositionDynamicAutomationProvider *provider) noexcept;
42
65
 
43
66
  ToggleState GetToggleState(const std::optional<facebook::react::AccessibilityState> &state) noexcept;
67
+
68
+ TextDecorationLineStyle GetTextDecorationLineStyle(facebook::react::TextDecorationStyle style) noexcept;
44
69
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -38,20 +38,38 @@ void HostPlatformViewEventEmitter::onBlur() const {
38
38
 
39
39
  #pragma mark - Mouse Events
40
40
 
41
- void HostPlatformViewEventEmitter::onMouseEnter(PointerEvent const &pointerEvent) const {
41
+ void HostPlatformViewEventEmitter::onMouseEnter(MouseEvent const &pointerEvent) const {
42
42
  dispatchEvent(
43
43
  "mouseEnter",
44
- std::make_shared<PointerEvent>(pointerEvent),
44
+ std::make_shared<MouseEvent>(pointerEvent),
45
45
  EventPriority::AsynchronousBatched,
46
46
  RawEvent::Category::ContinuousStart);
47
47
  }
48
48
 
49
- void HostPlatformViewEventEmitter::onMouseLeave(PointerEvent const &pointerEvent) const {
49
+ void HostPlatformViewEventEmitter::onMouseLeave(MouseEvent const &pointerEvent) const {
50
50
  dispatchEvent(
51
51
  "mouseLeave",
52
- std::make_shared<PointerEvent>(pointerEvent),
52
+ std::make_shared<MouseEvent>(pointerEvent),
53
53
  EventPriority::AsynchronousBatched,
54
54
  RawEvent::Category::ContinuousStart);
55
55
  }
56
56
 
57
+ #pragma mark - Touch Events
58
+
59
+ void HostPlatformViewEventEmitter::onPressIn(GestureResponderEvent event) const {
60
+ dispatchEvent("pressIn", [event](jsi::Runtime &runtime) {
61
+ auto payload = jsi::Object(runtime);
62
+ auto nativeEvent = jsi::Object(runtime);
63
+ nativeEvent.setProperty(runtime, "target", static_cast<double>(event.target));
64
+ nativeEvent.setProperty(runtime, "pageX", event.pagePoint.x);
65
+ nativeEvent.setProperty(runtime, "pageY", event.pagePoint.y);
66
+ nativeEvent.setProperty(runtime, "locationX", event.offsetPoint.x);
67
+ nativeEvent.setProperty(runtime, "locationY", event.offsetPoint.y);
68
+ nativeEvent.setProperty(runtime, "timestamp", event.timestamp);
69
+ nativeEvent.setProperty(runtime, "identifier", event.identifier);
70
+ payload.setProperty(runtime, "nativeEvent", nativeEvent);
71
+ return payload;
72
+ });
73
+ }
74
+
57
75
  } // namespace facebook::react
@@ -5,9 +5,18 @@
5
5
 
6
6
  #include <react/renderer/components/view/BaseViewEventEmitter.h>
7
7
  #include "KeyEvent.h"
8
+ #include "MouseEvent.h"
8
9
 
9
10
  namespace facebook::react {
10
11
 
12
+ struct GestureResponderEvent {
13
+ Tag target;
14
+ Point pagePoint;
15
+ Point offsetPoint;
16
+ double timestamp;
17
+ int identifier;
18
+ };
19
+
11
20
  class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
12
21
  public:
13
22
  using BaseViewEventEmitter::BaseViewEventEmitter;
@@ -24,8 +33,12 @@ class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
24
33
 
25
34
  #pragma mark - Mouse Events
26
35
 
27
- void onMouseEnter(PointerEvent const &pointerEvent) const;
28
- void onMouseLeave(PointerEvent const &pointerEvent) const;
36
+ void onMouseEnter(MouseEvent const &pointerEvent) const;
37
+ void onMouseLeave(MouseEvent const &pointerEvent) const;
38
+
39
+ #pragma mark - Touch Events
40
+
41
+ virtual void onPressIn(GestureResponderEvent event) const;
29
42
  };
30
43
 
31
- } // namespace facebook::react
44
+ } // namespace facebook::react