diff options
Diffstat (limited to 'accessible/windows/ia2/ia2AccessibleTextSelectionContainer.cpp')
-rw-r--r-- | accessible/windows/ia2/ia2AccessibleTextSelectionContainer.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/accessible/windows/ia2/ia2AccessibleTextSelectionContainer.cpp b/accessible/windows/ia2/ia2AccessibleTextSelectionContainer.cpp new file mode 100644 index 0000000000..0360cc2028 --- /dev/null +++ b/accessible/windows/ia2/ia2AccessibleTextSelectionContainer.cpp @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:expandtab:shiftwidth=2:tabstop=2: + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ia2AccessibleTextSelectionContainer.h" + +#include "AccessibleTextSelectionContainer_i.c" +#include "ia2AccessibleHypertext.h" +#include "mozilla/a11y/HyperTextAccessibleBase.h" +#include "TextRange.h" +#include "TextLeafRange.h" + +using namespace mozilla::a11y; + +// IAccessibleTextSelectionContainer + +STDMETHODIMP +ia2AccessibleTextSelectionContainer::get_selections( + IA2TextSelection** selections, long* nSelections) { + if (!selections || !nSelections) { + return E_INVALIDARG; + } + *nSelections = 0; + HyperTextAccessibleBase* text = TextAcc(); + if (!text) { + return CO_E_OBJNOTCONNECTED; + } + AutoTArray<TextRange, 1> ranges; + text->CroppedSelectionRanges(ranges); + *nSelections = ranges.Length(); + *selections = static_cast<IA2TextSelection*>( + ::CoTaskMemAlloc(sizeof(IA2TextSelection) * *nSelections)); + if (!*selections) { + return E_OUTOFMEMORY; + } + for (uint32_t idx = 0; idx < static_cast<uint32_t>(*nSelections); idx++) { + RefPtr<IAccessibleText> startObj = + GetIATextFrom(ranges[idx].StartContainer()); + startObj.forget(&(*selections)[idx].startObj); + (*selections)[idx].startOffset = ranges[idx].StartOffset(); + RefPtr<IAccessibleText> endObj = GetIATextFrom(ranges[idx].EndContainer()); + endObj.forget(&(*selections)[idx].endObj); + (*selections)[idx].endOffset = ranges[idx].EndOffset(); + // XXX Expose this properly somehow. + (*selections)[idx].startIsActive = true; + } + return S_OK; +} + +STDMETHODIMP +ia2AccessibleTextSelectionContainer::setSelections( + long nSelections, IA2TextSelection* selections) { + if (nSelections < 0 || (nSelections > 0 && !selections)) { + return E_INVALIDARG; + } + HyperTextAccessibleBase* text = TextAcc(); + if (!text) { + return CO_E_OBJNOTCONNECTED; + } + // Build and validate new selection ranges. + AutoTArray<TextLeafRange, 1> newRanges; + newRanges.SetCapacity(nSelections); + for (long r = 0; r < nSelections; ++r) { + TextLeafRange range(GetTextLeafPointFrom(selections[r].startObj, + selections[r].startOffset, false), + GetTextLeafPointFrom(selections[r].endObj, + selections[r].endOffset, true)); + if (!range) { + return E_INVALIDARG; + } + newRanges.AppendElement(range); + } + // Get the number of existing selections. We use SelectionRanges rather than + // SelectionCount because SelectionCount is restricted to this Accessible, + // whereas we want all selections within the control/document. + AutoTArray<TextRange, 1> oldRanges; + text->SelectionRanges(&oldRanges); + // Set the new selections. + for (long r = 0; r < nSelections; ++r) { + newRanges[r].SetSelection(r); + } + // Remove any remaining old selections if there were more than nSelections. + for (long r = nSelections; r < static_cast<long>(oldRanges.Length()); ++r) { + text->RemoveFromSelection(r); + } + return S_OK; +} + +// ia2AccessibleTextSelectionContainer + +HyperTextAccessibleBase* ia2AccessibleTextSelectionContainer::TextAcc() { + auto hyp = static_cast<ia2AccessibleHypertext*>(this); + Accessible* acc = hyp->Acc(); + return acc ? acc->AsHyperTextBase() : nullptr; +} + +/* static */ +RefPtr<IAccessibleText> ia2AccessibleTextSelectionContainer::GetIATextFrom( + Accessible* aAcc) { + MsaaAccessible* msaa = MsaaAccessible::GetFrom(aAcc); + MOZ_ASSERT(msaa); + RefPtr<IAccessibleText> text; + msaa->QueryInterface(IID_IAccessibleText, getter_AddRefs(text)); + MOZ_ASSERT(text); + return text; +} + +/* static */ +TextLeafPoint ia2AccessibleTextSelectionContainer::GetTextLeafPointFrom( + IAccessibleText* aText, long aOffset, bool aDescendToEnd) { + if (!aText) { + return TextLeafPoint(); + } + Accessible* acc = MsaaAccessible::GetAccessibleFrom(aText); + if (!acc) { + return TextLeafPoint(); + } + HyperTextAccessibleBase* hyp = acc->AsHyperTextBase(); + if (!hyp) { + return TextLeafPoint(); + } + return hyp->ToTextLeafPoint(aOffset, aDescendToEnd); +} |