react-native-windows 0.77.3 → 0.77.5

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 (38) hide show
  1. package/Libraries/Components/Button.windows.js +3 -0
  2. package/Libraries/Components/Pressable/Pressable.windows.js +3 -0
  3. package/Libraries/Components/ScrollView/ScrollView.windows.js +1920 -0
  4. package/Libraries/Components/TextInput/TextInput.windows.js +3 -0
  5. package/Libraries/Components/Touchable/TouchableBounce.windows.js +2 -0
  6. package/Libraries/Components/Touchable/TouchableNativeFeedback.windows.js +2 -0
  7. package/Libraries/Components/Touchable/TouchableOpacity.windows.js +2 -0
  8. package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +2 -0
  9. package/Libraries/Components/View/View.windows.js +3 -0
  10. package/Libraries/Components/View/ViewAccessibility.d.ts +7 -2
  11. package/Libraries/Components/View/ViewAccessibility.windows.js +1 -0
  12. package/Libraries/Components/View/ViewPropTypes.windows.js +1 -0
  13. package/Libraries/Core/ReactNativeVersion.js +1 -1
  14. package/Libraries/Core/setUpDeveloperTools.js +2 -3
  15. package/Libraries/Image/Image.windows.js +2 -0
  16. package/Libraries/Text/Text.windows.js +4 -0
  17. package/Libraries/Text/TextProps.windows.js +1 -0
  18. package/Libraries/Utilities/HMRClient.js +0 -28
  19. package/Libraries/Utilities/HMRClientProdShim.js +0 -1
  20. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +374 -21
  21. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +21 -0
  22. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp +115 -0
  23. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h +41 -0
  24. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +298 -0
  25. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h +59 -0
  26. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +1 -2
  27. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +24 -2
  28. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +5 -0
  29. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +14 -10
  30. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +3 -2
  31. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  32. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityPrimitives.h +1 -0
  33. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/accessibilityPropsConversions.h +4 -0
  34. package/Shared/Networking/WinRTWebSocketResource.cpp +369 -7
  35. package/Shared/Networking/WinRTWebSocketResource.h +118 -0
  36. package/Shared/Shared.vcxitems +6 -0
  37. package/Shared/Shared.vcxitems.filters +8 -0
  38. package/package.json +9 -9
@@ -1,6 +1,9 @@
1
1
  #include "pch.h"
2
2
  #include "CompositionDynamicAutomationProvider.h"
3
3
  #include <Fabric/ComponentView.h>
4
+ #include <Fabric/Composition/CompositionTextRangeProvider.h>
5
+ #include <Fabric/Composition/ParagraphComponentView.h>
6
+ #include <Fabric/Composition/ScrollViewComponentView.h>
4
7
  #include <Fabric/Composition/SwitchComponentView.h>
5
8
  #include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
6
9
  #include <Unicode.h>
@@ -25,6 +28,13 @@ CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
25
28
  if (props->accessibilityState.has_value() && props->accessibilityState->selected.has_value()) {
26
29
  AddSelectionItemsToContainer(this);
27
30
  }
31
+
32
+ if (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
33
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>()) {
34
+ m_textProvider = winrt::make<CompositionTextProvider>(
35
+ strongView.as<winrt::Microsoft::ReactNative::Composition::ComponentView>(), this)
36
+ .try_as<ITextProvider2>();
37
+ }
28
38
  }
29
39
 
30
40
  HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate(
@@ -141,8 +151,12 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_ProviderOptions(Prov
141
151
  return S_OK;
142
152
  }
143
153
 
144
- bool accessibilityValueHasValue(const facebook::react::AccessibilityValue &value) {
145
- return (value.min.has_value() && value.max.has_value()) || value.now.has_value() || value.text.has_value();
154
+ bool accessibilityValueHasTextValue(const facebook::react::AccessibilityValue &value) {
155
+ return value.text.has_value();
156
+ }
157
+
158
+ bool accessibilityValueHasNumericValue(const facebook::react::AccessibilityValue &value) {
159
+ return (value.min.has_value() && value.max.has_value() && value.now.has_value());
146
160
  }
147
161
 
148
162
  bool expandableControl(const facebook::react::SharedViewProps props) {
@@ -202,9 +216,22 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
202
216
  AddRef();
203
217
  }
204
218
 
219
+ if (patternId == UIA_ScrollPatternId &&
220
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>()) {
221
+ *pRetVal = static_cast<IScrollProvider *>(this);
222
+ AddRef();
223
+ }
224
+
205
225
  if (patternId == UIA_ValuePatternId &&
206
- (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
207
- accessibilityValueHasValue(props->accessibilityValue))) {
226
+ ((strongView
227
+ .try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() &&
228
+ !accessibilityValueHasNumericValue(props->accessibilityValue)) ||
229
+ accessibilityValueHasTextValue(props->accessibilityValue))) {
230
+ *pRetVal = static_cast<IValueProvider *>(this);
231
+ AddRef();
232
+ }
233
+
234
+ if (patternId == UIA_RangeValuePatternId && accessibilityValueHasNumericValue(props->accessibilityValue)) {
208
235
  *pRetVal = static_cast<IValueProvider *>(this);
209
236
  AddRef();
210
237
  }
@@ -233,10 +260,21 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
233
260
  AddRef();
234
261
  }
235
262
 
263
+ if (patternId == UIA_TextPatternId &&
264
+ (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
265
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>())) {
266
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
267
+ }
268
+
269
+ if (patternId == UIA_TextPattern2Id &&
270
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>()) {
271
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
272
+ }
273
+
236
274
  return S_OK;
237
275
  }
238
276
 
239
- long GetControlType(const std::string &role) noexcept {
277
+ long GetControlTypeFromString(const std::string &role) noexcept {
240
278
  if (role == "adjustable") {
241
279
  return UIA_SliderControlTypeId;
242
280
  } else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
@@ -294,11 +332,103 @@ long GetControlType(const std::string &role) noexcept {
294
332
  return UIA_TreeControlTypeId;
295
333
  } else if (role == "treeitem") {
296
334
  return UIA_TreeItemControlTypeId;
335
+ } else if (role == "pane") {
336
+ return UIA_PaneControlTypeId;
297
337
  }
298
338
  assert(false);
299
339
  return UIA_GroupControlTypeId;
300
340
  }
301
341
 
342
+ long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
343
+ switch (role) {
344
+ case facebook::react::Role::Alert:
345
+ return UIA_TextControlTypeId;
346
+ case facebook::react::Role::Application:
347
+ return UIA_WindowControlTypeId;
348
+ case facebook::react::Role::Button:
349
+ return UIA_ButtonControlTypeId;
350
+ case facebook::react::Role::Checkbox:
351
+ return UIA_CheckBoxControlTypeId;
352
+ case facebook::react::Role::Columnheader:
353
+ return UIA_HeaderControlTypeId;
354
+ case facebook::react::Role::Combobox:
355
+ return UIA_ComboBoxControlTypeId;
356
+ case facebook::react::Role::Document:
357
+ return UIA_DocumentControlTypeId;
358
+ case facebook::react::Role::Grid:
359
+ return UIA_GroupControlTypeId;
360
+ case facebook::react::Role::Group:
361
+ return UIA_GroupControlTypeId;
362
+ case facebook::react::Role::Heading:
363
+ return UIA_TextControlTypeId;
364
+ case facebook::react::Role::Img:
365
+ return UIA_ImageControlTypeId;
366
+ case facebook::react::Role::Link:
367
+ return UIA_HyperlinkControlTypeId;
368
+ case facebook::react::Role::List:
369
+ return UIA_ListControlTypeId;
370
+ case facebook::react::Role::Listitem:
371
+ return UIA_ListItemControlTypeId;
372
+ case facebook::react::Role::Menu:
373
+ return UIA_MenuControlTypeId;
374
+ case facebook::react::Role::Menubar:
375
+ return UIA_MenuBarControlTypeId;
376
+ case facebook::react::Role::Menuitem:
377
+ return UIA_MenuItemControlTypeId;
378
+ case facebook::react::Role::None:
379
+ return UIA_GroupControlTypeId;
380
+ case facebook::react::Role::Presentation:
381
+ return UIA_GroupControlTypeId;
382
+ case facebook::react::Role::Progressbar:
383
+ return UIA_ProgressBarControlTypeId;
384
+ case facebook::react::Role::Radio:
385
+ return UIA_RadioButtonControlTypeId;
386
+ case facebook::react::Role::Radiogroup:
387
+ return UIA_GroupControlTypeId;
388
+ case facebook::react::Role::Rowgroup:
389
+ return UIA_GroupControlTypeId;
390
+ case facebook::react::Role::Rowheader:
391
+ return UIA_HeaderControlTypeId;
392
+ case facebook::react::Role::Scrollbar:
393
+ return UIA_ScrollBarControlTypeId;
394
+ case facebook::react::Role::Searchbox:
395
+ return UIA_EditControlTypeId;
396
+ case facebook::react::Role::Separator:
397
+ return UIA_SeparatorControlTypeId;
398
+ case facebook::react::Role::Slider:
399
+ return UIA_SliderControlTypeId;
400
+ case facebook::react::Role::Spinbutton:
401
+ return UIA_SpinnerControlTypeId;
402
+ case facebook::react::Role::Status:
403
+ return UIA_StatusBarControlTypeId;
404
+ case facebook::react::Role::Summary:
405
+ return UIA_GroupControlTypeId;
406
+ case facebook::react::Role::Switch:
407
+ return UIA_ButtonControlTypeId;
408
+ case facebook::react::Role::Tab:
409
+ return UIA_TabItemControlTypeId;
410
+ case facebook::react::Role::Table:
411
+ return UIA_TableControlTypeId;
412
+ case facebook::react::Role::Tablist:
413
+ return UIA_TabControlTypeId;
414
+ case facebook::react::Role::Tabpanel:
415
+ return UIA_TabControlTypeId;
416
+ case facebook::react::Role::Timer:
417
+ return UIA_ButtonControlTypeId;
418
+ case facebook::react::Role::Toolbar:
419
+ return UIA_ToolBarControlTypeId;
420
+ case facebook::react::Role::Tooltip:
421
+ return UIA_ToolTipControlTypeId;
422
+ case facebook::react::Role::Tree:
423
+ return UIA_TreeControlTypeId;
424
+ case facebook::react::Role::Treegrid:
425
+ return UIA_TreeControlTypeId;
426
+ case facebook::react::Role::Treeitem:
427
+ return UIA_TreeItemControlTypeId;
428
+ }
429
+ return UIA_GroupControlTypeId;
430
+ }
431
+
302
432
  HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pRetVal) {
303
433
  if (pRetVal == nullptr)
304
434
  return E_POINTER;
@@ -324,8 +454,10 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
324
454
  switch (propertyId) {
325
455
  case UIA_ControlTypePropertyId: {
326
456
  pRetVal->vt = VT_I4;
327
- auto role = props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole;
328
- pRetVal->lVal = GetControlType(role);
457
+ pRetVal->lVal = props->role == facebook::react::Role::None ? props->accessibilityRole.empty()
458
+ ? GetControlTypeFromString(compositionView->DefaultControlType())
459
+ : GetControlTypeFromString(props->accessibilityRole)
460
+ : GetControlTypeFromRole(props->role);
329
461
  break;
330
462
  }
331
463
  case UIA_AutomationIdPropertyId: {
@@ -365,12 +497,18 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
365
497
  }
366
498
  case UIA_IsContentElementPropertyId: {
367
499
  pRetVal->vt = VT_BOOL;
368
- pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
500
+ pRetVal->boolVal =
501
+ (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
502
+ ? VARIANT_TRUE
503
+ : VARIANT_FALSE;
369
504
  break;
370
505
  }
371
506
  case UIA_IsControlElementPropertyId: {
372
507
  pRetVal->vt = VT_BOOL;
373
- pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
508
+ pRetVal->boolVal =
509
+ (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
510
+ ? VARIANT_TRUE
511
+ : VARIANT_FALSE;
374
512
  break;
375
513
  }
376
514
  case UIA_IsOffscreenPropertyId: {
@@ -461,6 +599,156 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::ScrollIntoView() {
461
599
  return S_OK;
462
600
  }
463
601
 
602
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalScrollPercent(double *pRetVal) {
603
+ BOOL horizontallyScrollable;
604
+ auto hr = get_HorizontallyScrollable(&horizontallyScrollable);
605
+ if (!SUCCEEDED(hr)) {
606
+ return hr;
607
+ }
608
+ if (!horizontallyScrollable) {
609
+ *pRetVal = UIA_ScrollPatternNoScroll;
610
+ } else {
611
+ auto strongView = m_view.view();
612
+ auto scrollComponentView =
613
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
614
+ *pRetVal = scrollComponentView->getScrollPositionX();
615
+ }
616
+ return S_OK;
617
+ }
618
+
619
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalScrollPercent(double *pRetVal) {
620
+ BOOL verticallyScrollable;
621
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
622
+ if (!SUCCEEDED(hr)) {
623
+ return hr;
624
+ }
625
+ if (!verticallyScrollable) {
626
+ *pRetVal = UIA_ScrollPatternNoScroll;
627
+ } else {
628
+ auto strongView = m_view.view();
629
+ auto scrollComponentView =
630
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
631
+ *pRetVal = scrollComponentView->getScrollPositionY();
632
+ }
633
+ return S_OK;
634
+ }
635
+
636
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalViewSize(double *pRetVal) {
637
+ BOOL horizontallyScrollable;
638
+ auto hr = get_HorizontallyScrollable(&horizontallyScrollable);
639
+ if (!SUCCEEDED(hr)) {
640
+ return hr;
641
+ }
642
+ if (!horizontallyScrollable) {
643
+ *pRetVal = 100;
644
+ } else {
645
+ auto strongView = m_view.view();
646
+ auto scrollComponentView =
647
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
648
+ *pRetVal = scrollComponentView->getHorizontalSize();
649
+ }
650
+ return S_OK;
651
+ }
652
+
653
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalViewSize(double *pRetVal) {
654
+ BOOL verticallyScrollable;
655
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
656
+ if (!SUCCEEDED(hr)) {
657
+ return hr;
658
+ }
659
+ if (!verticallyScrollable) {
660
+ *pRetVal = 100;
661
+ } else {
662
+ auto strongView = m_view.view();
663
+ auto scrollComponentView =
664
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
665
+ *pRetVal = scrollComponentView->getVerticalSize();
666
+ }
667
+ return S_OK;
668
+ }
669
+
670
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontallyScrollable(BOOL *pRetVal) {
671
+ if (pRetVal == nullptr)
672
+ return E_POINTER;
673
+ auto strongView = m_view.view();
674
+
675
+ if (!strongView)
676
+ return UIA_E_ELEMENTNOTAVAILABLE;
677
+
678
+ auto props = std::static_pointer_cast<const facebook::react::ScrollViewProps>(
679
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
680
+ if (props == nullptr)
681
+ return UIA_E_ELEMENTNOTAVAILABLE;
682
+ *pRetVal = (props->horizontal && props->scrollEnabled);
683
+ return S_OK;
684
+ }
685
+
686
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticallyScrollable(BOOL *pRetVal) {
687
+ if (pRetVal == nullptr)
688
+ return E_POINTER;
689
+ auto strongView = m_view.view();
690
+
691
+ if (!strongView)
692
+ return UIA_E_ELEMENTNOTAVAILABLE;
693
+
694
+ auto props = std::static_pointer_cast<const facebook::react::ScrollViewProps>(
695
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
696
+ if (props == nullptr)
697
+ return UIA_E_ELEMENTNOTAVAILABLE;
698
+ *pRetVal = (!props->horizontal && props->scrollEnabled);
699
+ return S_OK;
700
+ }
701
+
702
+ HRESULT __stdcall CompositionDynamicAutomationProvider::Scroll(
703
+ ScrollAmount horizontalAmount,
704
+ ScrollAmount verticalAmount) {
705
+ DispatchAccessibilityAction(m_view, "scroll");
706
+ auto strongView = m_view.view();
707
+ auto scrollComponentView =
708
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
709
+ BOOL verticallyScrollable;
710
+ BOOL horizontallyScrollable;
711
+ float vertical = 0.0f;
712
+ float horizontal = 0.0f;
713
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
714
+ if (!SUCCEEDED(hr)) {
715
+ return hr;
716
+ }
717
+ if (verticallyScrollable) {
718
+ if (verticalAmount == ScrollAmount_LargeIncrement) {
719
+ scrollComponentView->pageDown(true);
720
+ } else if (verticalAmount == ScrollAmount_LargeDecrement) {
721
+ scrollComponentView->pageUp(true);
722
+ } else if (verticalAmount == ScrollAmount_SmallIncrement) {
723
+ scrollComponentView->lineDown(true);
724
+ } else if (verticalAmount == ScrollAmount_SmallDecrement) {
725
+ scrollComponentView->lineUp(true);
726
+ }
727
+ }
728
+ hr = get_HorizontallyScrollable(&horizontallyScrollable);
729
+ if (!SUCCEEDED(hr)) {
730
+ return hr;
731
+ }
732
+ if (horizontallyScrollable) {
733
+ if (horizontalAmount == ScrollAmount_LargeIncrement) {
734
+ scrollComponentView->pageDown(true);
735
+ } else if (horizontalAmount == ScrollAmount_LargeDecrement) {
736
+ scrollComponentView->pageUp(true);
737
+ } else if (horizontalAmount == ScrollAmount_SmallIncrement) {
738
+ scrollComponentView->lineRight(true);
739
+ } else if (horizontalAmount == ScrollAmount_SmallDecrement) {
740
+ scrollComponentView->lineLeft(true);
741
+ }
742
+ }
743
+ return S_OK;
744
+ }
745
+
746
+ HRESULT __stdcall CompositionDynamicAutomationProvider::SetScrollPercent(
747
+ double horiztonalPercent,
748
+ double verticalPercent) {
749
+ return S_OK;
750
+ }
751
+
464
752
  BSTR StringToBSTR(const std::string &str) {
465
753
  // Calculate the required BSTR size in bytes
466
754
  int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
@@ -485,6 +773,8 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(LPCWSTR val) {
485
773
 
486
774
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
487
775
  ->setAcccessiblityValue(winrt::to_string(val));
776
+ // TODO: Edit once/if onAccessibilityAction props supports returning UIA event data. See
777
+ // https://github.com/react-native-community/discussions-and-proposals/issues/843.
488
778
  DispatchAccessibilityAction(m_view, "setValue");
489
779
  return S_OK;
490
780
  }
@@ -515,23 +805,86 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL *pRe
515
805
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
516
806
  if (props == nullptr)
517
807
  return UIA_E_ELEMENTNOTAVAILABLE;
518
- auto accessibilityRole = props->accessibilityRole;
519
- if (accessibilityRole.empty()) {
520
- // Control is using default control type. Use default IsReadOnly value.
521
- *pRetVal = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
522
- ->getAcccessiblityIsReadOnly();
523
- } else if (
524
- accessibilityRole == "textinput" || accessibilityRole == "searchbox" || accessibilityRole == "adjustable" ||
525
- accessibilityRole == "spinbutton" || accessibilityRole == "combobox") {
526
- // Control is using customized control type which should not be IsReadOnly for value pattern.
527
- *pRetVal = false;
808
+ if (props->accessibilityState.has_value() && props->accessibilityState->readOnly.has_value()) {
809
+ *pRetVal = props->accessibilityState->readOnly.value();
528
810
  } else {
529
- // Control is using customized control type which should be IsReadOnly for value pattern.
530
- *pRetVal = true;
811
+ // Use default IsReadOnly value.
812
+ *pRetVal = false;
531
813
  }
532
814
  return S_OK;
533
815
  }
534
816
 
817
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_LargeChange(double *pRetVal) {
818
+ // no-op
819
+ return S_OK;
820
+ }
821
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_Maximum(double *pRetVal) {
822
+ if (pRetVal == nullptr)
823
+ return E_POINTER;
824
+ auto strongView = m_view.view();
825
+
826
+ if (!strongView)
827
+ return UIA_E_ELEMENTNOTAVAILABLE;
828
+
829
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
830
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
831
+
832
+ if (props == nullptr)
833
+ return UIA_E_ELEMENTNOTAVAILABLE;
834
+
835
+ *pRetVal = props->accessibilityValue.max.value();
836
+ return S_OK;
837
+ }
838
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_Minimum(double *pRetVal) {
839
+ if (pRetVal == nullptr)
840
+ return E_POINTER;
841
+ auto strongView = m_view.view();
842
+
843
+ if (!strongView)
844
+ return UIA_E_ELEMENTNOTAVAILABLE;
845
+
846
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
847
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
848
+
849
+ if (props == nullptr)
850
+ return UIA_E_ELEMENTNOTAVAILABLE;
851
+
852
+ *pRetVal = props->accessibilityValue.min.value();
853
+ return S_OK;
854
+ }
855
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_SmallChange(double *pRetVal) {
856
+ // no-op
857
+ return S_OK;
858
+ }
859
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_Value(double *pRetVal) {
860
+ if (pRetVal == nullptr)
861
+ return E_POINTER;
862
+ auto strongView = m_view.view();
863
+
864
+ if (!strongView)
865
+ return UIA_E_ELEMENTNOTAVAILABLE;
866
+
867
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
868
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
869
+
870
+ if (props == nullptr)
871
+ return UIA_E_ELEMENTNOTAVAILABLE;
872
+
873
+ *pRetVal = props->accessibilityValue.now.value();
874
+ return S_OK;
875
+ }
876
+ HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(double val) {
877
+ auto strongView = m_view.view();
878
+
879
+ if (!strongView)
880
+ return UIA_E_ELEMENTNOTAVAILABLE;
881
+
882
+ // TODO: Edit once/if onAccessibilityAction props supports returning UIA event data. See
883
+ // https://github.com/react-native-community/discussions-and-proposals/issues/843.
884
+ DispatchAccessibilityAction(m_view, "setValue");
885
+ return S_OK;
886
+ }
887
+
535
888
  HRESULT __stdcall CompositionDynamicAutomationProvider::get_ToggleState(ToggleState *pRetVal) {
536
889
  if (pRetVal == nullptr)
537
890
  return E_POINTER;
@@ -15,7 +15,9 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
15
15
  IRawElementProviderSimple,
16
16
  IInvokeProvider,
17
17
  IScrollItemProvider,
18
+ IScrollProvider,
18
19
  IValueProvider,
20
+ IRangeValueProvider,
19
21
  IToggleProvider,
20
22
  IExpandCollapseProvider,
21
23
  ISelectionProvider,
@@ -45,11 +47,29 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
45
47
  // inherited via IScrollItemProvider
46
48
  HRESULT __stdcall ScrollIntoView() override;
47
49
 
50
+ // inherited via IScrollProvider
51
+ HRESULT __stdcall get_HorizontalScrollPercent(double *pRetVal) override;
52
+ HRESULT __stdcall get_VerticalScrollPercent(double *pRetVal) override;
53
+ HRESULT __stdcall get_HorizontalViewSize(double *pRetVal) override;
54
+ HRESULT __stdcall get_VerticalViewSize(double *pRetVal) override;
55
+ HRESULT __stdcall get_HorizontallyScrollable(BOOL *pRetVal) override;
56
+ HRESULT __stdcall get_VerticallyScrollable(BOOL *pRetVal) override;
57
+ HRESULT __stdcall Scroll(ScrollAmount horizontalAmount, ScrollAmount verticalAmount) override;
58
+ HRESULT __stdcall SetScrollPercent(double horiztonalPercent, double verticalPercent) override;
59
+
48
60
  // inherited via IValueProvider
49
61
  virtual HRESULT __stdcall SetValue(LPCWSTR val) override;
50
62
  virtual HRESULT __stdcall get_Value(BSTR *pRetVal) override;
51
63
  virtual HRESULT __stdcall get_IsReadOnly(BOOL *pRetVal) override;
52
64
 
65
+ // inherited via IRangeValueProvider
66
+ virtual HRESULT __stdcall get_LargeChange(double *pRetVal) override;
67
+ virtual HRESULT __stdcall get_Maximum(double *pRetVal) override;
68
+ virtual HRESULT __stdcall get_Minimum(double *pRetVal) override;
69
+ virtual HRESULT __stdcall get_SmallChange(double *pRetVal) override;
70
+ virtual HRESULT __stdcall get_Value(double *pRetVal) override;
71
+ virtual HRESULT __stdcall SetValue(double val) override;
72
+
53
73
  // inherited via IToggleProvider
54
74
  virtual HRESULT __stdcall get_ToggleState(ToggleState *pRetVal) override;
55
75
  virtual HRESULT __stdcall Toggle() override;
@@ -76,6 +96,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
76
96
 
77
97
  private:
78
98
  ::Microsoft::ReactNative::ReactTaggedView m_view;
99
+ winrt::com_ptr<ITextProvider2> m_textProvider;
79
100
  std::vector<winrt::com_ptr<IRawElementProviderSimple>> m_selectionItems;
80
101
  };
81
102
 
@@ -0,0 +1,115 @@
1
+ #include "pch.h"
2
+ #include <Fabric/ComponentView.h>
3
+ #include <Fabric/Composition/ParagraphComponentView.h>
4
+ #include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
5
+ #include <Unicode.h>
6
+ #include "CompositionTextRangeProvider.h"
7
+ #include "RootComponentView.h"
8
+ #include "UiaHelpers.h"
9
+
10
+ namespace winrt::Microsoft::ReactNative::implementation {
11
+
12
+ CompositionTextProvider::CompositionTextProvider(
13
+ const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
14
+ CompositionDynamicAutomationProvider *parentProvider) noexcept
15
+ : m_view{componentView} {
16
+ m_parentProvider.copy_from(parentProvider);
17
+ EnsureTextRangeProvider();
18
+ }
19
+
20
+ void CompositionTextProvider::EnsureTextRangeProvider() {
21
+ auto strongView = m_view.view();
22
+
23
+ if (!strongView)
24
+ return;
25
+
26
+ if (!m_textRangeProvider) {
27
+ m_textRangeProvider =
28
+ winrt::make<CompositionTextRangeProvider>(
29
+ strongView.as<winrt::Microsoft::ReactNative::Composition::ComponentView>(), m_parentProvider.get())
30
+ .try_as<ITextRangeProvider>();
31
+ }
32
+ }
33
+
34
+ HRESULT __stdcall CompositionTextProvider::get_DocumentRange(ITextRangeProvider **pRetVal) {
35
+ if (pRetVal == nullptr)
36
+ return E_POINTER;
37
+ auto strongView = m_view.view();
38
+
39
+ if (!strongView)
40
+ return UIA_E_ELEMENTNOTAVAILABLE;
41
+
42
+ if (m_textRangeProvider == nullptr)
43
+ return UIA_E_ELEMENTNOTAVAILABLE;
44
+
45
+ m_textRangeProvider.copy_to(pRetVal);
46
+ return S_OK;
47
+ }
48
+
49
+ HRESULT __stdcall CompositionTextProvider::get_SupportedTextSelection(SupportedTextSelection *pRetVal) {
50
+ if (pRetVal == nullptr)
51
+ return E_POINTER;
52
+ auto strongView = m_view.view();
53
+
54
+ if (!strongView)
55
+ return UIA_E_ELEMENTNOTAVAILABLE;
56
+
57
+ if (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>()) {
58
+ *pRetVal = SupportedTextSelection_Single;
59
+ } else if (
60
+ auto textView =
61
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>()) {
62
+ auto props = std::static_pointer_cast<const facebook::react::ParagraphProps>(textView->props());
63
+ if (props == nullptr)
64
+ return UIA_E_ELEMENTNOTAVAILABLE;
65
+ *pRetVal = props->isSelectable ? SupportedTextSelection_Single : SupportedTextSelection_None;
66
+ } else {
67
+ *pRetVal = SupportedTextSelection_None;
68
+ }
69
+
70
+ return S_OK;
71
+ }
72
+
73
+ HRESULT __stdcall CompositionTextProvider::GetSelection(SAFEARRAY **pRetVal) {
74
+ // no-op
75
+ *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0);
76
+ return S_OK;
77
+ }
78
+
79
+ HRESULT __stdcall CompositionTextProvider::GetVisibleRanges(SAFEARRAY **pRetVal) {
80
+ *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
81
+ if (m_textRangeProvider == nullptr)
82
+ return UIA_E_ELEMENTNOTAVAILABLE;
83
+ LONG pos = 0;
84
+ return SafeArrayPutElement(*pRetVal, &pos, m_textRangeProvider.get());
85
+ }
86
+
87
+ HRESULT __stdcall CompositionTextProvider::RangeFromChild(
88
+ IRawElementProviderSimple *childElement,
89
+ ITextRangeProvider **pRetVal) {
90
+ // no-op
91
+ *pRetVal = nullptr;
92
+ return S_OK;
93
+ }
94
+
95
+ HRESULT __stdcall CompositionTextProvider::RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) {
96
+ // no-op
97
+ if (m_textRangeProvider == nullptr)
98
+ return UIA_E_ELEMENTNOTAVAILABLE;
99
+ m_textRangeProvider.copy_to(pRetVal);
100
+ return S_OK;
101
+ }
102
+ HRESULT __stdcall CompositionTextProvider::GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) {
103
+ // no-op
104
+ *pRetVal = nullptr;
105
+ return S_OK;
106
+ }
107
+
108
+ HRESULT __stdcall CompositionTextProvider::RangeFromAnnotation(
109
+ IRawElementProviderSimple *annotationElement,
110
+ ITextRangeProvider **pRetVal) {
111
+ // no-op
112
+ *pRetVal = nullptr;
113
+ return S_OK;
114
+ }
115
+ } // namespace winrt::Microsoft::ReactNative::implementation
@@ -0,0 +1,41 @@
1
+ #pragma once
2
+
3
+ #include <Fabric/Composition/CompositionDynamicAutomationProvider.h>
4
+ #include <Fabric/Composition/CompositionViewComponentView.h>
5
+ #include <Fabric/ReactTaggedView.h>
6
+ #include <UIAutomation.h>
7
+ #include <inspectable.h>
8
+ #include <uiautomationcore.h>
9
+
10
+ namespace winrt::Microsoft::ReactNative::implementation {
11
+
12
+ class CompositionTextProvider : public winrt::implements<CompositionTextProvider, ITextProvider, ITextProvider2> {
13
+ public:
14
+ CompositionTextProvider(
15
+ const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
16
+ CompositionDynamicAutomationProvider *parentProvider) noexcept;
17
+
18
+ // inherited via ITextProvider
19
+ virtual HRESULT __stdcall get_DocumentRange(ITextRangeProvider **pRetVal) override;
20
+ virtual HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *pRetVal) override;
21
+ virtual HRESULT __stdcall GetSelection(SAFEARRAY **pRetVal) override;
22
+ virtual HRESULT __stdcall GetVisibleRanges(SAFEARRAY **pRetVal) override;
23
+ virtual HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal)
24
+ override;
25
+ virtual HRESULT __stdcall RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) override;
26
+
27
+ // inherited via ITextProvider2
28
+ virtual HRESULT __stdcall GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) override;
29
+ virtual HRESULT __stdcall RangeFromAnnotation(
30
+ IRawElementProviderSimple *annotationElement,
31
+ ITextRangeProvider **pRetVal) override;
32
+
33
+ void EnsureTextRangeProvider();
34
+
35
+ private:
36
+ ::Microsoft::ReactNative::ReactTaggedView m_view;
37
+ winrt::com_ptr<ITextRangeProvider> m_textRangeProvider;
38
+ winrt::com_ptr<CompositionDynamicAutomationProvider> m_parentProvider;
39
+ };
40
+
41
+ } // namespace winrt::Microsoft::ReactNative::implementation