react-native-windows 0.78.1 → 0.78.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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(
@@ -204,6 +214,12 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
204
214
  AddRef();
205
215
  }
206
216
 
217
+ if (patternId == UIA_ScrollPatternId &&
218
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>()) {
219
+ *pRetVal = static_cast<IScrollProvider *>(this);
220
+ AddRef();
221
+ }
222
+
207
223
  if (patternId == UIA_ValuePatternId &&
208
224
  ((strongView
209
225
  .try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() &&
@@ -242,10 +258,21 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
242
258
  AddRef();
243
259
  }
244
260
 
261
+ if (patternId == UIA_TextPatternId &&
262
+ (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
263
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>())) {
264
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
265
+ }
266
+
267
+ if (patternId == UIA_TextPattern2Id &&
268
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>()) {
269
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
270
+ }
271
+
245
272
  return S_OK;
246
273
  }
247
274
 
248
- long GetControlType(const std::string &role) noexcept {
275
+ long GetControlTypeFromString(const std::string &role) noexcept {
249
276
  if (role == "adjustable") {
250
277
  return UIA_SliderControlTypeId;
251
278
  } else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
@@ -303,11 +330,103 @@ long GetControlType(const std::string &role) noexcept {
303
330
  return UIA_TreeControlTypeId;
304
331
  } else if (role == "treeitem") {
305
332
  return UIA_TreeItemControlTypeId;
333
+ } else if (role == "pane") {
334
+ return UIA_PaneControlTypeId;
306
335
  }
307
336
  assert(false);
308
337
  return UIA_GroupControlTypeId;
309
338
  }
310
339
 
340
+ long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
341
+ switch (role) {
342
+ case facebook::react::Role::Alert:
343
+ return UIA_TextControlTypeId;
344
+ case facebook::react::Role::Application:
345
+ return UIA_WindowControlTypeId;
346
+ case facebook::react::Role::Button:
347
+ return UIA_ButtonControlTypeId;
348
+ case facebook::react::Role::Checkbox:
349
+ return UIA_CheckBoxControlTypeId;
350
+ case facebook::react::Role::Columnheader:
351
+ return UIA_HeaderControlTypeId;
352
+ case facebook::react::Role::Combobox:
353
+ return UIA_ComboBoxControlTypeId;
354
+ case facebook::react::Role::Document:
355
+ return UIA_DocumentControlTypeId;
356
+ case facebook::react::Role::Grid:
357
+ return UIA_GroupControlTypeId;
358
+ case facebook::react::Role::Group:
359
+ return UIA_GroupControlTypeId;
360
+ case facebook::react::Role::Heading:
361
+ return UIA_TextControlTypeId;
362
+ case facebook::react::Role::Img:
363
+ return UIA_ImageControlTypeId;
364
+ case facebook::react::Role::Link:
365
+ return UIA_HyperlinkControlTypeId;
366
+ case facebook::react::Role::List:
367
+ return UIA_ListControlTypeId;
368
+ case facebook::react::Role::Listitem:
369
+ return UIA_ListItemControlTypeId;
370
+ case facebook::react::Role::Menu:
371
+ return UIA_MenuControlTypeId;
372
+ case facebook::react::Role::Menubar:
373
+ return UIA_MenuBarControlTypeId;
374
+ case facebook::react::Role::Menuitem:
375
+ return UIA_MenuItemControlTypeId;
376
+ case facebook::react::Role::None:
377
+ return UIA_GroupControlTypeId;
378
+ case facebook::react::Role::Presentation:
379
+ return UIA_GroupControlTypeId;
380
+ case facebook::react::Role::Progressbar:
381
+ return UIA_ProgressBarControlTypeId;
382
+ case facebook::react::Role::Radio:
383
+ return UIA_RadioButtonControlTypeId;
384
+ case facebook::react::Role::Radiogroup:
385
+ return UIA_GroupControlTypeId;
386
+ case facebook::react::Role::Rowgroup:
387
+ return UIA_GroupControlTypeId;
388
+ case facebook::react::Role::Rowheader:
389
+ return UIA_HeaderControlTypeId;
390
+ case facebook::react::Role::Scrollbar:
391
+ return UIA_ScrollBarControlTypeId;
392
+ case facebook::react::Role::Searchbox:
393
+ return UIA_EditControlTypeId;
394
+ case facebook::react::Role::Separator:
395
+ return UIA_SeparatorControlTypeId;
396
+ case facebook::react::Role::Slider:
397
+ return UIA_SliderControlTypeId;
398
+ case facebook::react::Role::Spinbutton:
399
+ return UIA_SpinnerControlTypeId;
400
+ case facebook::react::Role::Status:
401
+ return UIA_StatusBarControlTypeId;
402
+ case facebook::react::Role::Summary:
403
+ return UIA_GroupControlTypeId;
404
+ case facebook::react::Role::Switch:
405
+ return UIA_ButtonControlTypeId;
406
+ case facebook::react::Role::Tab:
407
+ return UIA_TabItemControlTypeId;
408
+ case facebook::react::Role::Table:
409
+ return UIA_TableControlTypeId;
410
+ case facebook::react::Role::Tablist:
411
+ return UIA_TabControlTypeId;
412
+ case facebook::react::Role::Tabpanel:
413
+ return UIA_TabControlTypeId;
414
+ case facebook::react::Role::Timer:
415
+ return UIA_ButtonControlTypeId;
416
+ case facebook::react::Role::Toolbar:
417
+ return UIA_ToolBarControlTypeId;
418
+ case facebook::react::Role::Tooltip:
419
+ return UIA_ToolTipControlTypeId;
420
+ case facebook::react::Role::Tree:
421
+ return UIA_TreeControlTypeId;
422
+ case facebook::react::Role::Treegrid:
423
+ return UIA_TreeControlTypeId;
424
+ case facebook::react::Role::Treeitem:
425
+ return UIA_TreeItemControlTypeId;
426
+ }
427
+ return UIA_GroupControlTypeId;
428
+ }
429
+
311
430
  HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pRetVal) {
312
431
  if (pRetVal == nullptr)
313
432
  return E_POINTER;
@@ -333,8 +452,10 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
333
452
  switch (propertyId) {
334
453
  case UIA_ControlTypePropertyId: {
335
454
  pRetVal->vt = VT_I4;
336
- auto role = props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole;
337
- pRetVal->lVal = GetControlType(role);
455
+ pRetVal->lVal = props->role == facebook::react::Role::None ? props->accessibilityRole.empty()
456
+ ? GetControlTypeFromString(compositionView->DefaultControlType())
457
+ : GetControlTypeFromString(props->accessibilityRole)
458
+ : GetControlTypeFromRole(props->role);
338
459
  break;
339
460
  }
340
461
  case UIA_AutomationIdPropertyId: {
@@ -374,12 +495,18 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
374
495
  }
375
496
  case UIA_IsContentElementPropertyId: {
376
497
  pRetVal->vt = VT_BOOL;
377
- pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
498
+ pRetVal->boolVal =
499
+ (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
500
+ ? VARIANT_TRUE
501
+ : VARIANT_FALSE;
378
502
  break;
379
503
  }
380
504
  case UIA_IsControlElementPropertyId: {
381
505
  pRetVal->vt = VT_BOOL;
382
- pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
506
+ pRetVal->boolVal =
507
+ (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
508
+ ? VARIANT_TRUE
509
+ : VARIANT_FALSE;
383
510
  break;
384
511
  }
385
512
  case UIA_IsOffscreenPropertyId: {
@@ -470,6 +597,156 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::ScrollIntoView() {
470
597
  return S_OK;
471
598
  }
472
599
 
600
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalScrollPercent(double *pRetVal) {
601
+ BOOL horizontallyScrollable;
602
+ auto hr = get_HorizontallyScrollable(&horizontallyScrollable);
603
+ if (!SUCCEEDED(hr)) {
604
+ return hr;
605
+ }
606
+ if (!horizontallyScrollable) {
607
+ *pRetVal = UIA_ScrollPatternNoScroll;
608
+ } else {
609
+ auto strongView = m_view.view();
610
+ auto scrollComponentView =
611
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
612
+ *pRetVal = scrollComponentView->getScrollPositionX();
613
+ }
614
+ return S_OK;
615
+ }
616
+
617
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalScrollPercent(double *pRetVal) {
618
+ BOOL verticallyScrollable;
619
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
620
+ if (!SUCCEEDED(hr)) {
621
+ return hr;
622
+ }
623
+ if (!verticallyScrollable) {
624
+ *pRetVal = UIA_ScrollPatternNoScroll;
625
+ } else {
626
+ auto strongView = m_view.view();
627
+ auto scrollComponentView =
628
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
629
+ *pRetVal = scrollComponentView->getScrollPositionY();
630
+ }
631
+ return S_OK;
632
+ }
633
+
634
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontalViewSize(double *pRetVal) {
635
+ BOOL horizontallyScrollable;
636
+ auto hr = get_HorizontallyScrollable(&horizontallyScrollable);
637
+ if (!SUCCEEDED(hr)) {
638
+ return hr;
639
+ }
640
+ if (!horizontallyScrollable) {
641
+ *pRetVal = 100;
642
+ } else {
643
+ auto strongView = m_view.view();
644
+ auto scrollComponentView =
645
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
646
+ *pRetVal = scrollComponentView->getHorizontalSize();
647
+ }
648
+ return S_OK;
649
+ }
650
+
651
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticalViewSize(double *pRetVal) {
652
+ BOOL verticallyScrollable;
653
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
654
+ if (!SUCCEEDED(hr)) {
655
+ return hr;
656
+ }
657
+ if (!verticallyScrollable) {
658
+ *pRetVal = 100;
659
+ } else {
660
+ auto strongView = m_view.view();
661
+ auto scrollComponentView =
662
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
663
+ *pRetVal = scrollComponentView->getVerticalSize();
664
+ }
665
+ return S_OK;
666
+ }
667
+
668
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_HorizontallyScrollable(BOOL *pRetVal) {
669
+ if (pRetVal == nullptr)
670
+ return E_POINTER;
671
+ auto strongView = m_view.view();
672
+
673
+ if (!strongView)
674
+ return UIA_E_ELEMENTNOTAVAILABLE;
675
+
676
+ auto props = std::static_pointer_cast<const facebook::react::ScrollViewProps>(
677
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
678
+ if (props == nullptr)
679
+ return UIA_E_ELEMENTNOTAVAILABLE;
680
+ *pRetVal = (props->horizontal && props->scrollEnabled);
681
+ return S_OK;
682
+ }
683
+
684
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_VerticallyScrollable(BOOL *pRetVal) {
685
+ if (pRetVal == nullptr)
686
+ return E_POINTER;
687
+ auto strongView = m_view.view();
688
+
689
+ if (!strongView)
690
+ return UIA_E_ELEMENTNOTAVAILABLE;
691
+
692
+ auto props = std::static_pointer_cast<const facebook::react::ScrollViewProps>(
693
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
694
+ if (props == nullptr)
695
+ return UIA_E_ELEMENTNOTAVAILABLE;
696
+ *pRetVal = (!props->horizontal && props->scrollEnabled);
697
+ return S_OK;
698
+ }
699
+
700
+ HRESULT __stdcall CompositionDynamicAutomationProvider::Scroll(
701
+ ScrollAmount horizontalAmount,
702
+ ScrollAmount verticalAmount) {
703
+ DispatchAccessibilityAction(m_view, "scroll");
704
+ auto strongView = m_view.view();
705
+ auto scrollComponentView =
706
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ScrollViewComponentView>();
707
+ BOOL verticallyScrollable;
708
+ BOOL horizontallyScrollable;
709
+ float vertical = 0.0f;
710
+ float horizontal = 0.0f;
711
+ auto hr = get_VerticallyScrollable(&verticallyScrollable);
712
+ if (!SUCCEEDED(hr)) {
713
+ return hr;
714
+ }
715
+ if (verticallyScrollable) {
716
+ if (verticalAmount == ScrollAmount_LargeIncrement) {
717
+ scrollComponentView->pageDown(true);
718
+ } else if (verticalAmount == ScrollAmount_LargeDecrement) {
719
+ scrollComponentView->pageUp(true);
720
+ } else if (verticalAmount == ScrollAmount_SmallIncrement) {
721
+ scrollComponentView->lineDown(true);
722
+ } else if (verticalAmount == ScrollAmount_SmallDecrement) {
723
+ scrollComponentView->lineUp(true);
724
+ }
725
+ }
726
+ hr = get_HorizontallyScrollable(&horizontallyScrollable);
727
+ if (!SUCCEEDED(hr)) {
728
+ return hr;
729
+ }
730
+ if (horizontallyScrollable) {
731
+ if (horizontalAmount == ScrollAmount_LargeIncrement) {
732
+ scrollComponentView->pageDown(true);
733
+ } else if (horizontalAmount == ScrollAmount_LargeDecrement) {
734
+ scrollComponentView->pageUp(true);
735
+ } else if (horizontalAmount == ScrollAmount_SmallIncrement) {
736
+ scrollComponentView->lineRight(true);
737
+ } else if (horizontalAmount == ScrollAmount_SmallDecrement) {
738
+ scrollComponentView->lineLeft(true);
739
+ }
740
+ }
741
+ return S_OK;
742
+ }
743
+
744
+ HRESULT __stdcall CompositionDynamicAutomationProvider::SetScrollPercent(
745
+ double horiztonalPercent,
746
+ double verticalPercent) {
747
+ return S_OK;
748
+ }
749
+
473
750
  BSTR StringToBSTR(const std::string &str) {
474
751
  // Calculate the required BSTR size in bytes
475
752
  int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
@@ -526,7 +803,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL *pRe
526
803
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
527
804
  if (props == nullptr)
528
805
  return UIA_E_ELEMENTNOTAVAILABLE;
529
- auto accessibilityRole = props->accessibilityRole;
530
806
  if (props->accessibilityState.has_value() && props->accessibilityState->readOnly.has_value()) {
531
807
  *pRetVal = props->accessibilityState->readOnly.value();
532
808
  } else {
@@ -15,6 +15,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
15
15
  IRawElementProviderSimple,
16
16
  IInvokeProvider,
17
17
  IScrollItemProvider,
18
+ IScrollProvider,
18
19
  IValueProvider,
19
20
  IRangeValueProvider,
20
21
  IToggleProvider,
@@ -46,6 +47,16 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
46
47
  // inherited via IScrollItemProvider
47
48
  HRESULT __stdcall ScrollIntoView() override;
48
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
+
49
60
  // inherited via IValueProvider
50
61
  virtual HRESULT __stdcall SetValue(LPCWSTR val) override;
51
62
  virtual HRESULT __stdcall get_Value(BSTR *pRetVal) override;
@@ -85,6 +96,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
85
96
 
86
97
  private:
87
98
  ::Microsoft::ReactNative::ReactTaggedView m_view;
99
+ winrt::com_ptr<ITextProvider2> m_textProvider;
88
100
  std::vector<winrt::com_ptr<IRawElementProviderSimple>> m_selectionItems;
89
101
  };
90
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