121 lines
3.8 KiB
C++
121 lines
3.8 KiB
C++
/* -*- 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 || !selections) {
|
|
return E_INVALIDARG;
|
|
}
|
|
HyperTextAccessibleBase* text = TextAcc();
|
|
if (!text) {
|
|
return CO_E_OBJNOTCONNECTED;
|
|
}
|
|
if (nSelections == 0) {
|
|
text->RemoveFromSelection(TextLeafRange::kRemoveAllExistingSelectedRanges);
|
|
return S_OK;
|
|
}
|
|
// 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),
|
|
GetTextLeafPointFrom(selections[r].endObj, selections[r].endOffset));
|
|
if (!range) {
|
|
return E_INVALIDARG;
|
|
}
|
|
newRanges.AppendElement(range);
|
|
}
|
|
// Set the new selections.
|
|
newRanges[0].SetSelection(TextLeafRange::kRemoveAllExistingSelectedRanges);
|
|
for (long r = 1; r < nSelections; ++r) {
|
|
newRanges[r].SetSelection(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) {
|
|
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);
|
|
}
|