ia2AccessibleTextSelectionContainer.cpp (3869B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:expandtab:shiftwidth=2:tabstop=2: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "ia2AccessibleTextSelectionContainer.h" 9 10 #include "AccessibleTextSelectionContainer_i.c" 11 #include "ia2AccessibleHypertext.h" 12 #include "mozilla/a11y/HyperTextAccessibleBase.h" 13 #include "TextRange.h" 14 #include "TextLeafRange.h" 15 16 using namespace mozilla::a11y; 17 18 // IAccessibleTextSelectionContainer 19 20 STDMETHODIMP 21 ia2AccessibleTextSelectionContainer::get_selections( 22 IA2TextSelection** selections, long* nSelections) { 23 if (!selections || !nSelections) { 24 return E_INVALIDARG; 25 } 26 *nSelections = 0; 27 HyperTextAccessibleBase* text = TextAcc(); 28 if (!text) { 29 return CO_E_OBJNOTCONNECTED; 30 } 31 AutoTArray<TextRange, 1> ranges; 32 text->CroppedSelectionRanges(ranges); 33 *nSelections = ranges.Length(); 34 *selections = static_cast<IA2TextSelection*>( 35 ::CoTaskMemAlloc(sizeof(IA2TextSelection) * *nSelections)); 36 if (!*selections) { 37 return E_OUTOFMEMORY; 38 } 39 for (uint32_t idx = 0; idx < static_cast<uint32_t>(*nSelections); idx++) { 40 RefPtr<IAccessibleText> startObj = 41 GetIATextFrom(ranges[idx].StartContainer()); 42 startObj.forget(&(*selections)[idx].startObj); 43 (*selections)[idx].startOffset = ranges[idx].StartOffset(); 44 RefPtr<IAccessibleText> endObj = GetIATextFrom(ranges[idx].EndContainer()); 45 endObj.forget(&(*selections)[idx].endObj); 46 (*selections)[idx].endOffset = ranges[idx].EndOffset(); 47 // XXX Expose this properly somehow. 48 (*selections)[idx].startIsActive = true; 49 } 50 return S_OK; 51 } 52 53 STDMETHODIMP 54 ia2AccessibleTextSelectionContainer::setSelections( 55 long nSelections, IA2TextSelection* selections) { 56 if (nSelections < 0 || !selections) { 57 return E_INVALIDARG; 58 } 59 HyperTextAccessibleBase* text = TextAcc(); 60 if (!text) { 61 return CO_E_OBJNOTCONNECTED; 62 } 63 if (nSelections == 0) { 64 text->RemoveFromSelection(TextLeafRange::kRemoveAllExistingSelectedRanges); 65 return S_OK; 66 } 67 // Build and validate new selection ranges. 68 AutoTArray<TextLeafRange, 1> newRanges; 69 newRanges.SetCapacity(nSelections); 70 for (long r = 0; r < nSelections; ++r) { 71 TextLeafRange range( 72 GetTextLeafPointFrom(selections[r].startObj, selections[r].startOffset), 73 GetTextLeafPointFrom(selections[r].endObj, selections[r].endOffset)); 74 if (!range) { 75 return E_INVALIDARG; 76 } 77 newRanges.AppendElement(range); 78 } 79 // Set the new selections. 80 newRanges[0].SetSelection(TextLeafRange::kRemoveAllExistingSelectedRanges); 81 for (long r = 1; r < nSelections; ++r) { 82 newRanges[r].SetSelection(r); 83 } 84 return S_OK; 85 } 86 87 // ia2AccessibleTextSelectionContainer 88 89 HyperTextAccessibleBase* ia2AccessibleTextSelectionContainer::TextAcc() { 90 auto hyp = static_cast<ia2AccessibleHypertext*>(this); 91 Accessible* acc = hyp->Acc(); 92 return acc ? acc->AsHyperTextBase() : nullptr; 93 } 94 95 /* static */ 96 RefPtr<IAccessibleText> ia2AccessibleTextSelectionContainer::GetIATextFrom( 97 Accessible* aAcc) { 98 MsaaAccessible* msaa = MsaaAccessible::GetFrom(aAcc); 99 MOZ_ASSERT(msaa); 100 RefPtr<IAccessibleText> text; 101 msaa->QueryInterface(IID_IAccessibleText, getter_AddRefs(text)); 102 MOZ_ASSERT(text); 103 return text; 104 } 105 106 /* static */ 107 TextLeafPoint ia2AccessibleTextSelectionContainer::GetTextLeafPointFrom( 108 IAccessibleText* aText, long aOffset) { 109 if (!aText) { 110 return TextLeafPoint(); 111 } 112 Accessible* acc = MsaaAccessible::GetAccessibleFrom(aText); 113 if (!acc) { 114 return TextLeafPoint(); 115 } 116 HyperTextAccessibleBase* hyp = acc->AsHyperTextBase(); 117 if (!hyp) { 118 return TextLeafPoint(); 119 } 120 return hyp->ToTextLeafPoint(aOffset); 121 }