Bug 1821965 - P2: Remove sync IPC extension messages for text operations. r=morgan,ipc-reviewers,mccr8

We can get rid the entire local HyperTextAccessible-based implementation as well!

Depends on D178717

Differential Revision: https://phabricator.services.mozilla.com/D178718
This commit is contained in:
Eitan Isaacson 2023-05-26 22:17:13 +00:00
Родитель 19ab04b63e
Коммит 9b58fed3a9
10 изменённых файлов: 1 добавлений и 1340 удалений

Просмотреть файл

@ -1,256 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 "DocAccessiblePlatformExtChild.h"
#include "AccAttributes.h"
#include "DocAccessibleChild.h"
#include "HyperTextAccessibleWrap.h"
#include "nsAccUtils.h"
#define UNIQUE_ID(acc) \
!acc || acc->Document() == acc ? 0 \
: reinterpret_cast<uint64_t>(acc->UniqueID())
namespace mozilla {
namespace a11y {
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvRangeAt(
const uint64_t& aID, const int32_t& aOffset, const EWhichRange& aRangeType,
uint64_t* aStartContainer, int32_t* aStartOffset, uint64_t* aEndContainer,
int32_t* aEndOffset) {
*aStartContainer = 0;
*aStartOffset = 0;
*aEndContainer = 0;
*aEndOffset = 0;
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
if (!acc) {
return IPC_OK();
}
HyperTextAccessible* startContainer = nullptr;
HyperTextAccessible* endContainer = nullptr;
acc->RangeAt(aOffset, aRangeType, &startContainer, aStartOffset,
&endContainer, aEndOffset);
MOZ_ASSERT(!startContainer || startContainer->Document() == acc->Document());
MOZ_ASSERT(!endContainer || endContainer->Document() == acc->Document());
*aStartContainer = UNIQUE_ID(startContainer);
*aEndContainer = UNIQUE_ID(endContainer);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvNextClusterAt(
const uint64_t& aID, const int32_t& aOffset, uint64_t* aNextContainer,
int32_t* aNextOffset) {
*aNextContainer = 0;
*aNextOffset = 0;
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
if (!acc) {
return IPC_OK();
}
HyperTextAccessible* nextContainer = nullptr;
acc->NextClusterAt(aOffset, &nextContainer, aNextOffset);
MOZ_ASSERT(!nextContainer || nextContainer->Document() == acc->Document());
*aNextContainer = UNIQUE_ID(nextContainer);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvPreviousClusterAt(
const uint64_t& aID, const int32_t& aOffset, uint64_t* aPrevContainer,
int32_t* aPrevOffset) {
*aPrevContainer = 0;
*aPrevOffset = 0;
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
if (!acc) {
return IPC_OK();
}
HyperTextAccessible* prevContainer = nullptr;
acc->PreviousClusterAt(aOffset, &prevContainer, aPrevOffset);
MOZ_ASSERT(!prevContainer || prevContainer->Document() == acc->Document());
*aPrevContainer = UNIQUE_ID(prevContainer);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvTextForRange(
const uint64_t& aID, const int32_t& aStartOffset,
const uint64_t& aEndContainer, const int32_t& aEndOffset, nsString* aText) {
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
HyperTextAccessibleWrap* endContainer =
IdToHyperTextAccessibleWrap(aEndContainer);
if (!acc || !endContainer) {
return IPC_OK();
}
acc->TextForRange(*aText, aStartOffset, endContainer, aEndOffset);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvBoundsForRange(
const uint64_t& aID, const int32_t& aStartOffset,
const uint64_t& aEndContainer, const int32_t& aEndOffset,
LayoutDeviceIntRect* aBounds) {
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
HyperTextAccessibleWrap* endContainer =
IdToHyperTextAccessibleWrap(aEndContainer);
if (!acc || !endContainer) {
*aBounds = LayoutDeviceIntRect();
return IPC_OK();
}
*aBounds = acc->BoundsForRange(aStartOffset, endContainer, aEndOffset);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvLengthForRange(
const uint64_t& aID, const int32_t& aStartOffset,
const uint64_t& aEndContainer, const int32_t& aEndOffset,
int32_t* aLength) {
*aLength = 0;
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
HyperTextAccessibleWrap* endContainer =
IdToHyperTextAccessibleWrap(aEndContainer);
if (!acc || !endContainer) {
return IPC_OK();
}
*aLength = acc->LengthForRange(aStartOffset, endContainer, aEndOffset);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvOffsetAtIndex(
const uint64_t& aID, const int32_t& aIndex, uint64_t* aContainer,
int32_t* aOffset) {
*aContainer = 0;
*aOffset = 0;
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
if (!acc) {
return IPC_OK();
}
HyperTextAccessible* container = nullptr;
acc->OffsetAtIndex(aIndex, &container, aOffset);
MOZ_ASSERT(!container || container->Document() == acc->Document());
*aContainer = UNIQUE_ID(container);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvRangeOfChild(
const uint64_t& aID, const uint64_t& aChild, int32_t* aStartOffset,
int32_t* aEndOffset) {
*aStartOffset = 0;
*aEndOffset = 0;
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
LocalAccessible* child =
static_cast<DocAccessibleChild*>(Manager())->IdToAccessible(aChild);
if (!acc || !child) {
return IPC_OK();
}
acc->RangeOfChild(child, aStartOffset, aEndOffset);
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvLeafAtOffset(
const uint64_t& aID, const int32_t& aOffset, uint64_t* aLeaf) {
*aLeaf = 0;
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
if (!acc) {
return IPC_OK();
}
LocalAccessible* leaf = acc->LeafAtOffset(aOffset);
MOZ_ASSERT(!leaf || leaf->Document() == acc->Document());
*aLeaf = UNIQUE_ID(leaf);
return IPC_OK();
}
mozilla::ipc::IPCResult
DocAccessiblePlatformExtChild::RecvAttributedTextForRange(
const uint64_t& aID, const int32_t& aStartOffset,
const uint64_t& aEndContainer, const int32_t& aEndOffset,
nsTArray<TextAttributesRun>* aAttributes) {
HyperTextAccessibleWrap* acc = IdToHyperTextAccessibleWrap(aID);
HyperTextAccessibleWrap* endContainer =
IdToHyperTextAccessibleWrap(aEndContainer);
if (!acc || !endContainer) {
return IPC_OK();
}
nsTArray<nsString> texts;
nsTArray<LocalAccessible*> containers;
nsTArray<RefPtr<AccAttributes>> props;
acc->AttributedTextForRange(texts, props, containers, aStartOffset,
endContainer, aEndOffset);
MOZ_ASSERT(texts.Length() == props.Length() &&
texts.Length() == containers.Length());
for (size_t i = 0; i < texts.Length(); i++) {
aAttributes->AppendElement(TextAttributesRun(
texts.ElementAt(i), UNIQUE_ID(containers.ElementAt(i)),
props.ElementAt(i)));
}
return IPC_OK();
}
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvSelectRange(
const uint64_t& aID, const int32_t& aStartOffset,
const uint64_t& aEndContainer, const int32_t& aEndOffset) {
RefPtr<HyperTextAccessibleWrap> acc = IdToHyperTextAccessibleWrap(aID);
RefPtr<HyperTextAccessibleWrap> endContainer =
IdToHyperTextAccessibleWrap(aEndContainer);
if (!acc || !endContainer) {
return IPC_OK();
}
acc->SelectRange(aStartOffset, endContainer, aEndOffset);
return IPC_OK();
}
HyperTextAccessibleWrap*
DocAccessiblePlatformExtChild::IdToHyperTextAccessibleWrap(
const uint64_t& aID) const {
return static_cast<HyperTextAccessibleWrap*>(
static_cast<DocAccessibleChild*>(Manager())->IdToHyperTextAccessible(
aID));
}
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -1,82 +0,0 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_a11y_DocAccessiblePlatformExtChild_h
#define mozilla_a11y_DocAccessiblePlatformExtChild_h
#include "mozilla/a11y/PDocAccessiblePlatformExtChild.h"
namespace mozilla {
namespace a11y {
class HyperTextAccessibleWrap;
class DocAccessibleChild;
class DocAccessiblePlatformExtChild : public PDocAccessiblePlatformExtChild {
public:
mozilla::ipc::IPCResult RecvRangeAt(
const uint64_t& aID, const int32_t& aOffset,
const EWhichRange& aRangeType, uint64_t* aStartContainer,
int32_t* aStartOffset, uint64_t* aEndContainer, int32_t* aEndOffset);
mozilla::ipc::IPCResult RecvNextClusterAt(const uint64_t& aID,
const int32_t& aOffset,
uint64_t* aNextContainer,
int32_t* aNextOffset);
mozilla::ipc::IPCResult RecvPreviousClusterAt(const uint64_t& aID,
const int32_t& aOffset,
uint64_t* aPrevContainer,
int32_t* aPrevOffset);
mozilla::ipc::IPCResult RecvTextForRange(const uint64_t& aID,
const int32_t& aStartOffset,
const uint64_t& aEndContainer,
const int32_t& aEndOffset,
nsString* aText);
mozilla::ipc::IPCResult RecvBoundsForRange(const uint64_t& aID,
const int32_t& aStartOffset,
const uint64_t& aEndContainer,
const int32_t& aEndOffset,
LayoutDeviceIntRect* aBounds);
mozilla::ipc::IPCResult RecvLengthForRange(const uint64_t& aID,
const int32_t& aStartOffset,
const uint64_t& aEndContainer,
const int32_t& aEndOffset,
int32_t* aLength);
mozilla::ipc::IPCResult RecvOffsetAtIndex(const uint64_t& aID,
const int32_t& aIndex,
uint64_t* aContainer,
int32_t* aOffset);
mozilla::ipc::IPCResult RecvRangeOfChild(const uint64_t& aID,
const uint64_t& aChild,
int32_t* aStartOffset,
int32_t* aEndOffset);
mozilla::ipc::IPCResult RecvLeafAtOffset(const uint64_t& aID,
const int32_t& aOffset,
uint64_t* aLeaf);
mozilla::ipc::IPCResult RecvAttributedTextForRange(
const uint64_t& aID, const int32_t& aStartOffset,
const uint64_t& aEndContainer, const int32_t& aEndOffset,
nsTArray<TextAttributesRun>* aAttributes);
MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult RecvSelectRange(
const uint64_t& aID, const int32_t& aStartOffset,
const uint64_t& aEndContainer, const int32_t& aEndOffset);
private:
HyperTextAccessibleWrap* IdToHyperTextAccessibleWrap(
const uint64_t& aID) const;
};
} // namespace a11y
} // namespace mozilla
#endif

Просмотреть файл

@ -1,19 +0,0 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_a11y_DocAccessiblePlatformExtParent_h
#define mozilla_a11y_DocAccessiblePlatformExtParent_h
#include "mozilla/a11y/PDocAccessiblePlatformExtParent.h"
namespace mozilla {
namespace a11y {
class DocAccessiblePlatformExtParent : public PDocAccessiblePlatformExtParent {
};
} // namespace a11y
} // namespace mozilla
#endif

Просмотреть файл

@ -1,67 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 protocol PDocAccessible;
include "mozilla/GfxMessageUtils.h";
using mozilla::a11y::EWhichRange from "mozilla/a11y/IPCTypes.h";
[RefCounted] using mozilla::a11y::AccAttributes from "mozilla/a11y/IPCTypes.h";
using mozilla::LayoutDeviceIntRect from "Units.h";
namespace mozilla {
namespace a11y {
struct TextAttributesRun {
nsString Text;
uint64_t ContainerID;
nullable AccAttributes TextAttributes;
};
[ManualDealloc, NestedUpTo=inside_sync] sync protocol PDocAccessiblePlatformExt {
manager PDocAccessible;
child:
async __delete__();
[Nested=inside_sync] sync RangeAt(uint64_t aID, int32_t aOffset, EWhichRange aRangeType)
returns(uint64_t aStartContainer, int32_t aStartOffset,
uint64_t aEndContainer, int32_t aEndOffset);
[Nested=inside_sync] sync NextClusterAt(uint64_t aID, int32_t aOffset)
returns(uint64_t aNextContainer, int32_t aNextOffset);
[Nested=inside_sync] sync PreviousClusterAt(uint64_t aID, int32_t aOffset)
returns(uint64_t aNextContainer, int32_t aNextOffset);
[Nested=inside_sync] sync TextForRange(uint64_t aID, int32_t aStartOffset, uint64_t aEndContainer, int32_t aEndOffset)
returns(nsString aText);
[Nested=inside_sync] sync BoundsForRange(uint64_t aID, int32_t aStartOffset, uint64_t aEndContainer, int32_t aEndOffset)
returns(LayoutDeviceIntRect aRetVal);
[Nested=inside_sync] sync LengthForRange(uint64_t aID, int32_t aStartOffset, uint64_t aEndContainer, int32_t aEndOffset)
returns(int32_t aLength);
[Nested=inside_sync] sync OffsetAtIndex(uint64_t aID, int32_t aIndex)
returns(uint64_t aContainer, int32_t aOffset);
[Nested=inside_sync] sync RangeOfChild(uint64_t aID, uint64_t aChild)
returns(int32_t aStartOffset, int32_t aEndOffset);
[Nested=inside_sync] sync LeafAtOffset(uint64_t aID, int32_t aOffset)
returns(uint64_t aLeaf);
[Nested=inside_sync] sync AttributedTextForRange(uint64_t aID, int32_t aStartOffset, uint64_t aEndContainer, int32_t aEndOffset)
returns(TextAttributesRun[] aAttributedText);
async SelectRange(uint64_t aID, int32_t aStartOffset, uint64_t aEndContainer, int32_t aEndOffset);
};
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -1,28 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
if CONFIG["ACCESSIBILITY"]:
IPDL_SOURCES += ["PDocAccessiblePlatformExt.ipdl"]
EXPORTS.mozilla.a11y += [
"DocAccessiblePlatformExtChild.h",
"DocAccessiblePlatformExtParent.h",
]
SOURCES += [
"DocAccessiblePlatformExtChild.cpp",
]
LOCAL_INCLUDES += [
"/accessible/base",
"/accessible/generic",
"/accessible/ipc/other",
"/accessible/mac",
]
include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul"

Просмотреть файл

@ -8,7 +8,5 @@ toolkit = CONFIG["MOZ_WIDGET_TOOLKIT"]
if toolkit == "android":
DIRS += ["android"]
elif toolkit == "cocoa":
DIRS += ["mac"]
else:
DIRS += ["other"]

Просмотреть файл

@ -7,89 +7,11 @@
#define mozilla_a11y_HyperTextAccessibleWrap_h__
#include "HyperTextAccessible.h"
#include "PlatformExtTypes.h"
#include "WordMovementType.h"
namespace mozilla {
namespace a11y {
struct TextPoint;
class HyperTextAccessibleWrap : public HyperTextAccessible {
public:
HyperTextAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc)
: HyperTextAccessible(aContent, aDoc) {}
void TextForRange(nsAString& aText, int32_t aStartOffset,
HyperTextAccessible* aEndContainer, int32_t aEndOffset);
void AttributedTextForRange(nsTArray<nsString>& aStrings,
nsTArray<RefPtr<AccAttributes>>& aProperties,
nsTArray<LocalAccessible*>& aContainers,
int32_t aStartOffset,
HyperTextAccessible* aEndContainer,
int32_t aEndOffset);
LayoutDeviceIntRect BoundsForRange(int32_t aStartOffset,
HyperTextAccessible* aEndContainer,
int32_t aEndOffset);
int32_t LengthForRange(int32_t aStartOffset,
HyperTextAccessible* aEndContainer,
int32_t aEndOffset);
void OffsetAtIndex(int32_t aIndex, HyperTextAccessible** aContainer,
int32_t* aOffset);
void RangeAt(int32_t aOffset, EWhichRange aRangeType,
HyperTextAccessible** aStartContainer, int32_t* aStartOffset,
HyperTextAccessible** aEndContainer, int32_t* aEndOffset);
void NextClusterAt(int32_t aOffset, HyperTextAccessible** aNextContainer,
int32_t* aNextOffset);
void PreviousClusterAt(int32_t aOffset, HyperTextAccessible** aPrevContainer,
int32_t* aPrevOffset);
void RangeOfChild(LocalAccessible* aChild, int32_t* aStartOffset,
int32_t* aEndOffset);
LocalAccessible* LeafAtOffset(int32_t aOffset);
MOZ_CAN_RUN_SCRIPT void SelectRange(int32_t aStartOffset,
HyperTextAccessible* aEndContainer,
int32_t aEndOffset);
protected:
~HyperTextAccessibleWrap() {}
private:
TextPoint FindTextPoint(int32_t aOffset, nsDirection aDirection,
nsSelectionAmount aAmount,
EWordMovementType aWordMovementType);
HyperTextAccessibleWrap* EditableRoot();
void LeftWordAt(int32_t aOffset, HyperTextAccessible** aStartContainer,
int32_t* aStartOffset, HyperTextAccessible** aEndContainer,
int32_t* aEndOffset);
void RightWordAt(int32_t aOffset, HyperTextAccessible** aStartContainer,
int32_t* aStartOffset, HyperTextAccessible** aEndContainer,
int32_t* aEndOffset);
void LineAt(int32_t aOffset, bool aNextLine,
HyperTextAccessible** aStartContainer, int32_t* aStartOffset,
HyperTextAccessible** aEndContainer, int32_t* aEndOffset);
void ParagraphAt(int32_t aOffset, HyperTextAccessible** aStartContainer,
int32_t* aStartOffset, HyperTextAccessible** aEndContainer,
int32_t* aEndOffset);
void StyleAt(int32_t aOffset, HyperTextAccessible** aStartContainer,
int32_t* aStartOffset, HyperTextAccessible** aEndContainer,
int32_t* aEndOffset);
};
typedef class HyperTextAccessible HyperTextAccessibleWrap;
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -1,776 +0,0 @@
/* clang-format off */
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* clang-format on */
/* 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 "HyperTextAccessibleWrap.h"
#include "LocalAccessible-inl.h"
#include "HTMLListAccessible.h"
#include "nsAccUtils.h"
#include "nsFrameSelection.h"
#include "TextLeafRange.h"
#include "TextRange.h"
#include "TreeWalker.h"
using namespace mozilla;
using namespace mozilla::a11y;
// HyperTextIterator
class HyperTextIterator {
public:
HyperTextIterator(HyperTextAccessible* aStartContainer, int32_t aStartOffset,
HyperTextAccessible* aEndContainer, int32_t aEndOffset)
: mCurrentContainer(aStartContainer),
mCurrentStartOffset(0),
mCurrentEndOffset(0),
mEndContainer(aEndContainer),
mEndOffset(0) {
mCurrentStartOffset =
std::min(aStartOffset,
static_cast<int32_t>(mCurrentContainer->CharacterCount()));
mCurrentEndOffset = mCurrentStartOffset;
mEndOffset = std::min(
aEndOffset, static_cast<int32_t>(mEndContainer->CharacterCount()));
}
bool Next();
int32_t SegmentLength();
// If offset is set to a child hyperlink, adjust it so it set on the first
// offset in the deepest link. Or, if the offset to the last character, set it
// to the outermost end offset in an ancestor. Returns true if iterator was
// mutated.
bool NormalizeForward();
// If offset is set right after child hyperlink, adjust it so it set on the
// last offset in the deepest link. Or, if the offset is on the first
// character of a link, set it to the outermost start offset in an ancestor.
// Returns true if iterator was mutated.
bool NormalizeBackward();
HyperTextAccessible* mCurrentContainer;
int32_t mCurrentStartOffset;
int32_t mCurrentEndOffset;
private:
int32_t NextLinkOffset();
HyperTextAccessible* mEndContainer;
int32_t mEndOffset;
};
bool HyperTextIterator::NormalizeForward() {
if (mCurrentStartOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT ||
mCurrentStartOffset >=
static_cast<int32_t>(mCurrentContainer->CharacterCount())) {
// If this is the end of the current container, mutate to its parent's
// end offset.
if (!mCurrentContainer->IsLink()) {
// If we are not a link, it is a root hypertext accessible.
return false;
}
if (!mCurrentContainer->LocalParent() ||
!mCurrentContainer->LocalParent()->IsHyperText()) {
// If we are a link, but our parent is not a hypertext accessible
// treat the current container as the root hypertext accessible.
// This can be the case with some XUL containers that are not
// hypertext accessibles.
return false;
}
uint32_t endOffset = mCurrentContainer->EndOffset();
if (endOffset != 0) {
mCurrentContainer = mCurrentContainer->LocalParent()->AsHyperText();
mCurrentStartOffset = endOffset;
if (mCurrentContainer == mEndContainer &&
mCurrentStartOffset >= mEndOffset) {
// Reached end boundary.
return false;
}
// Call NormalizeForward recursively to get top-most link if at the end of
// one, or innermost link if at the beginning.
NormalizeForward();
return true;
}
} else {
LocalAccessible* link = mCurrentContainer->LinkAt(
mCurrentContainer->LinkIndexAtOffset(mCurrentStartOffset));
// If there is a link at this offset, mutate into it.
if (link && link->IsHyperText()) {
if (mCurrentStartOffset > 0 &&
mCurrentContainer->LinkIndexAtOffset(mCurrentStartOffset) ==
mCurrentContainer->LinkIndexAtOffset(mCurrentStartOffset - 1)) {
MOZ_ASSERT_UNREACHABLE("Same link for previous offset");
return false;
}
mCurrentContainer = link->AsHyperText();
if (link->IsHTMLListItem()) {
LocalAccessible* bullet = link->AsHTMLListItem()->Bullet();
mCurrentStartOffset = bullet ? nsAccUtils::TextLength(bullet) : 0;
} else {
mCurrentStartOffset = 0;
}
if (mCurrentContainer == mEndContainer &&
mCurrentStartOffset >= mEndOffset) {
// Reached end boundary.
return false;
}
// Call NormalizeForward recursively to get top-most embedding ancestor
// if at the end of one, or innermost link if at the beginning.
NormalizeForward();
return true;
}
}
return false;
}
bool HyperTextIterator::NormalizeBackward() {
if (mCurrentStartOffset == 0) {
// If this is the start of the current container, mutate to its parent's
// start offset.
if (!mCurrentContainer->IsLink()) {
// If we are not a link, it is a root hypertext accessible.
return false;
}
if (!mCurrentContainer->LocalParent() ||
!mCurrentContainer->LocalParent()->IsHyperText()) {
// If we are a link, but our parent is not a hypertext accessible
// treat the current container as the root hypertext accessible.
// This can be the case with some XUL containers that are not
// hypertext accessibles.
return false;
}
uint32_t startOffset = mCurrentContainer->StartOffset();
mCurrentContainer = mCurrentContainer->LocalParent()->AsHyperText();
mCurrentStartOffset = startOffset;
// Call NormalizeBackward recursively to get top-most link if at the
// beginning of one, or innermost link if at the end.
NormalizeBackward();
return true;
} else {
LocalAccessible* link =
mCurrentContainer->GetChildAtOffset(mCurrentStartOffset - 1);
// If there is a link before this offset, mutate into it,
// and set the offset to its last character.
if (link && link->IsHyperText()) {
mCurrentContainer = link->AsHyperText();
mCurrentStartOffset = mCurrentContainer->CharacterCount();
// Call NormalizeBackward recursively to get top-most top-most embedding
// ancestor if at the beginning of one, or innermost link if at the end.
NormalizeBackward();
return true;
}
if (mCurrentContainer->IsHTMLListItem() &&
mCurrentContainer->AsHTMLListItem()->Bullet() == link) {
mCurrentStartOffset = 0;
NormalizeBackward();
return true;
}
}
return false;
}
int32_t HyperTextIterator::SegmentLength() {
int32_t endOffset = mCurrentEndOffset < 0
? mCurrentContainer->CharacterCount()
: mCurrentEndOffset;
return endOffset - mCurrentStartOffset;
}
int32_t HyperTextIterator::NextLinkOffset() {
int32_t linkCount = mCurrentContainer->LinkCount();
for (int32_t i = 0; i < linkCount; i++) {
LocalAccessible* link = mCurrentContainer->LinkAt(i);
MOZ_ASSERT(link);
int32_t linkStartOffset = link->StartOffset();
if (mCurrentStartOffset < linkStartOffset) {
return linkStartOffset;
}
}
return -1;
}
bool HyperTextIterator::Next() {
if (!mCurrentContainer->Document()->HasLoadState(
DocAccessible::eTreeConstructed)) {
// If the accessible tree is still being constructed the text tree
// is not in a traversable state yet.
return false;
}
if (mCurrentContainer == mEndContainer &&
(mCurrentEndOffset == -1 || mEndOffset <= mCurrentEndOffset)) {
return false;
} else {
mCurrentStartOffset = mCurrentEndOffset;
NormalizeForward();
}
int32_t nextLinkOffset = NextLinkOffset();
if (mCurrentContainer == mEndContainer &&
(nextLinkOffset == -1 || nextLinkOffset > mEndOffset)) {
mCurrentEndOffset =
mEndOffset < 0 ? mEndContainer->CharacterCount() : mEndOffset;
} else {
mCurrentEndOffset = nextLinkOffset < 0 ? mCurrentContainer->CharacterCount()
: nextLinkOffset;
}
return mCurrentStartOffset != mCurrentEndOffset;
}
void HyperTextAccessibleWrap::TextForRange(nsAString& aText,
int32_t aStartOffset,
HyperTextAccessible* aEndContainer,
int32_t aEndOffset) {
if (IsHTMLListItem()) {
LocalAccessible* maybeBullet = GetChildAtOffset(aStartOffset - 1);
if (maybeBullet) {
LocalAccessible* bullet = AsHTMLListItem()->Bullet();
if (maybeBullet == bullet) {
TextSubstring(0, nsAccUtils::TextLength(bullet), aText);
}
}
}
HyperTextIterator iter(this, aStartOffset, aEndContainer, aEndOffset);
while (iter.Next()) {
nsAutoString text;
iter.mCurrentContainer->TextSubstring(iter.mCurrentStartOffset,
iter.mCurrentEndOffset, text);
aText.Append(text);
}
}
void HyperTextAccessibleWrap::AttributedTextForRange(
nsTArray<nsString>& aStrings, nsTArray<RefPtr<AccAttributes>>& aProperties,
nsTArray<LocalAccessible*>& aContainers, int32_t aStartOffset,
HyperTextAccessible* aEndContainer, int32_t aEndOffset) {
if (IsHTMLListItem()) {
LocalAccessible* maybeBullet = GetChildAtOffset(aStartOffset - 1);
if (maybeBullet) {
LocalAccessible* bullet = AsHTMLListItem()->Bullet();
if (maybeBullet == bullet) {
nsAutoString text;
TextSubstring(0, nsAccUtils::TextLength(bullet), text);
int32_t unusedAttrStartOffset, unusedAttrEndOffset;
RefPtr<AccAttributes> props =
TextAttributes(true, aStartOffset - 1, &unusedAttrStartOffset,
&unusedAttrEndOffset);
aStrings.AppendElement(text);
aProperties.AppendElement(props);
aContainers.AppendElement(this);
}
}
}
HyperTextIterator iter(this, aStartOffset, aEndContainer, aEndOffset);
while (iter.Next()) {
int32_t attrStartOffset = 0;
int32_t attrEndOffset = iter.mCurrentStartOffset;
do {
int32_t oldEndOffset = attrEndOffset;
RefPtr<AccAttributes> props = iter.mCurrentContainer->TextAttributes(
true, attrEndOffset, &attrStartOffset, &attrEndOffset);
if (oldEndOffset == attrEndOffset) {
MOZ_ASSERT_UNREACHABLE("new attribute end offset should be different");
break;
}
nsAutoString text;
iter.mCurrentContainer->TextSubstring(
attrStartOffset < iter.mCurrentStartOffset ? iter.mCurrentStartOffset
: attrStartOffset,
attrEndOffset < iter.mCurrentEndOffset ? attrEndOffset
: iter.mCurrentEndOffset,
text);
aStrings.AppendElement(text);
aProperties.AppendElement(props);
aContainers.AppendElement(iter.mCurrentContainer);
} while (attrEndOffset < iter.mCurrentEndOffset);
}
}
LayoutDeviceIntRect HyperTextAccessibleWrap::BoundsForRange(
int32_t aStartOffset, HyperTextAccessible* aEndContainer,
int32_t aEndOffset) {
LayoutDeviceIntRect rect;
HyperTextIterator iter(this, aStartOffset, aEndContainer, aEndOffset);
while (iter.Next()) {
LayoutDeviceIntRect stringRect = iter.mCurrentContainer->TextBounds(
iter.mCurrentStartOffset, iter.mCurrentEndOffset);
rect.UnionRect(rect, stringRect);
}
return rect;
}
int32_t HyperTextAccessibleWrap::LengthForRange(
int32_t aStartOffset, HyperTextAccessible* aEndContainer,
int32_t aEndOffset) {
int32_t length = 0;
HyperTextIterator iter(this, aStartOffset, aEndContainer, aEndOffset);
while (iter.Next()) {
length += iter.SegmentLength();
}
return length;
}
void HyperTextAccessibleWrap::OffsetAtIndex(int32_t aIndex,
HyperTextAccessible** aContainer,
int32_t* aOffset) {
int32_t index = aIndex;
HyperTextIterator iter(this, 0, this, CharacterCount());
while (iter.Next()) {
int32_t segmentLength = iter.SegmentLength();
if (index <= segmentLength) {
*aContainer = iter.mCurrentContainer;
*aOffset = iter.mCurrentStartOffset + index;
break;
}
index -= segmentLength;
}
}
void HyperTextAccessibleWrap::RangeAt(int32_t aOffset, EWhichRange aRangeType,
HyperTextAccessible** aStartContainer,
int32_t* aStartOffset,
HyperTextAccessible** aEndContainer,
int32_t* aEndOffset) {
switch (aRangeType) {
case EWhichRange::eLeftWord:
LeftWordAt(aOffset, aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
break;
case EWhichRange::eRightWord:
RightWordAt(aOffset, aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
break;
case EWhichRange::eLine:
case EWhichRange::eLeftLine:
LineAt(aOffset, false, aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
break;
case EWhichRange::eRightLine:
LineAt(aOffset, true, aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
break;
case EWhichRange::eParagraph:
ParagraphAt(aOffset, aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
break;
case EWhichRange::eStyle:
StyleAt(aOffset, aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
break;
default:
break;
}
}
void HyperTextAccessibleWrap::LeftWordAt(int32_t aOffset,
HyperTextAccessible** aStartContainer,
int32_t* aStartOffset,
HyperTextAccessible** aEndContainer,
int32_t* aEndOffset) {
TextPoint here(this, aOffset);
TextPoint start =
FindTextPoint(aOffset, eDirPrevious, eSelectWord, eStartWord);
if (!start.mContainer) {
return;
}
auto* startContainer = static_cast<HyperTextAccessibleWrap*>(
start.mContainer->AsLocal()->AsHyperText());
if ((NativeState() & states::EDITABLE) &&
!(startContainer->NativeState() & states::EDITABLE)) {
// The word search crossed an editable boundary. Return the first word of
// the editable root.
return EditableRoot()->RightWordAt(0, aStartContainer, aStartOffset,
aEndContainer, aEndOffset);
}
TextPoint end = startContainer->FindTextPoint(start.mOffset, eDirNext,
eSelectWord, eEndWord);
if (end < here) {
*aStartContainer = end.mContainer->AsLocal()->AsHyperText();
*aEndContainer = here.mContainer->AsLocal()->AsHyperText();
*aStartOffset = end.mOffset;
*aEndOffset = here.mOffset;
} else {
*aStartContainer = startContainer;
*aEndContainer = end.mContainer->AsLocal()->AsHyperText();
*aStartOffset = start.mOffset;
*aEndOffset = end.mOffset;
}
}
void HyperTextAccessibleWrap::RightWordAt(int32_t aOffset,
HyperTextAccessible** aStartContainer,
int32_t* aStartOffset,
HyperTextAccessible** aEndContainer,
int32_t* aEndOffset) {
TextPoint here(this, aOffset);
TextPoint end = FindTextPoint(aOffset, eDirNext, eSelectWord, eEndWord);
if (!end.mContainer || end < here || here == end) {
// If we didn't find a word end, or if we wrapped around (bug 1652833),
// return with no result.
return;
}
auto* endContainer = static_cast<HyperTextAccessibleWrap*>(
end.mContainer->AsLocal()->AsHyperText());
if ((NativeState() & states::EDITABLE) &&
!(endContainer->NativeState() & states::EDITABLE)) {
// The word search crossed an editable boundary. Return with no result.
return;
}
TextPoint start = endContainer->FindTextPoint(end.mOffset, eDirPrevious,
eSelectWord, eStartWord);
if (here < start) {
*aStartContainer = here.mContainer->AsLocal()->AsHyperText();
*aEndContainer = start.mContainer->AsLocal()->AsHyperText();
*aStartOffset = here.mOffset;
*aEndOffset = start.mOffset;
} else {
*aStartContainer = start.mContainer->AsLocal()->AsHyperText();
*aEndContainer = endContainer;
*aStartOffset = start.mOffset;
*aEndOffset = end.mOffset;
}
}
void HyperTextAccessibleWrap::LineAt(int32_t aOffset, bool aNextLine,
HyperTextAccessible** aStartContainer,
int32_t* aStartOffset,
HyperTextAccessible** aEndContainer,
int32_t* aEndOffset) {
TextPoint here(this, aOffset);
TextPoint end =
FindTextPoint(aOffset, eDirNext, eSelectEndLine, eDefaultBehavior);
if (!end.mContainer || end < here) {
// If we didn't find a word end, or if we wrapped around (bug 1652833),
// return with no result.
return;
}
auto* endContainer = static_cast<HyperTextAccessibleWrap*>(
end.mContainer->AsLocal()->AsHyperText());
TextPoint start = endContainer->FindTextPoint(
end.mOffset, eDirPrevious, eSelectBeginLine, eDefaultBehavior);
if (!aNextLine && here < start) {
start = FindTextPoint(aOffset, eDirPrevious, eSelectBeginLine,
eDefaultBehavior);
if (!start.mContainer) {
return;
}
auto* startContainer = static_cast<HyperTextAccessibleWrap*>(
start.mContainer->AsLocal()->AsHyperText());
end = startContainer->FindTextPoint(start.mOffset, eDirNext, eSelectEndLine,
eDefaultBehavior);
}
*aStartContainer = start.mContainer->AsLocal()->AsHyperText();
*aEndContainer = end.mContainer->AsLocal()->AsHyperText();
*aStartOffset = start.mOffset;
*aEndOffset = end.mOffset;
}
void HyperTextAccessibleWrap::ParagraphAt(int32_t aOffset,
HyperTextAccessible** aStartContainer,
int32_t* aStartOffset,
HyperTextAccessible** aEndContainer,
int32_t* aEndOffset) {
TextPoint here(this, aOffset);
TextPoint end =
FindTextPoint(aOffset, eDirNext, eSelectParagraph, eDefaultBehavior);
if (!end.mContainer || end < here) {
// If we didn't find a word end, or if we wrapped around (bug 1652833),
// return with no result.
return;
}
if (end.mOffset == -1 && LocalParent() && LocalParent()->IsHyperText()) {
// If end offset is -1 we didn't find a paragraph boundary.
// This must be an inline container, go to its parent to
// retrieve paragraph boundaries.
static_cast<HyperTextAccessibleWrap*>(LocalParent()->AsHyperText())
->ParagraphAt(StartOffset(), aStartContainer, aStartOffset,
aEndContainer, aEndOffset);
return;
}
auto* endContainer = static_cast<HyperTextAccessibleWrap*>(
end.mContainer->AsLocal()->AsHyperText());
TextPoint start = static_cast<HyperTextAccessibleWrap*>(endContainer)
->FindTextPoint(end.mOffset, eDirPrevious,
eSelectParagraph, eDefaultBehavior);
*aStartContainer = start.mContainer->AsLocal()->AsHyperText();
*aEndContainer = endContainer;
*aStartOffset = start.mOffset;
*aEndOffset = end.mOffset;
}
void HyperTextAccessibleWrap::StyleAt(int32_t aOffset,
HyperTextAccessible** aStartContainer,
int32_t* aStartOffset,
HyperTextAccessible** aEndContainer,
int32_t* aEndOffset) {
// Get the range of the text leaf at this offset.
// A text leaf represents a stretch of like-styled text.
auto leaf = LeafAtOffset(aOffset);
if (!leaf) {
return;
}
MOZ_ASSERT(leaf->LocalParent()->IsHyperText());
HyperTextAccessibleWrap* container =
static_cast<HyperTextAccessibleWrap*>(leaf->LocalParent()->AsHyperText());
if (!container) {
return;
}
*aStartContainer = *aEndContainer = container;
container->RangeOfChild(leaf, aStartOffset, aEndOffset);
}
void HyperTextAccessibleWrap::NextClusterAt(
int32_t aOffset, HyperTextAccessible** aNextContainer,
int32_t* aNextOffset) {
TextPoint here(this, aOffset);
TextPoint next =
FindTextPoint(aOffset, eDirNext, eSelectCluster, eDefaultBehavior);
if ((next.mOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT &&
next.mContainer == Document()) ||
(next < here)) {
// If we reached the end of the doc, or if we wrapped to the start of the
// doc return given offset as-is.
*aNextContainer = this;
*aNextOffset = aOffset;
} else {
*aNextContainer = next.mContainer->AsLocal()->AsHyperText();
*aNextOffset = next.mOffset;
}
}
void HyperTextAccessibleWrap::PreviousClusterAt(
int32_t aOffset, HyperTextAccessible** aPrevContainer,
int32_t* aPrevOffset) {
TextPoint prev =
FindTextPoint(aOffset, eDirPrevious, eSelectCluster, eDefaultBehavior);
*aPrevContainer = prev.mContainer->AsLocal()->AsHyperText();
*aPrevOffset = prev.mOffset;
}
void HyperTextAccessibleWrap::RangeOfChild(LocalAccessible* aChild,
int32_t* aStartOffset,
int32_t* aEndOffset) {
MOZ_ASSERT(aChild->LocalParent() == this);
*aStartOffset = *aEndOffset = -1;
int32_t index = GetIndexOf(aChild);
if (index != -1) {
*aStartOffset = GetChildOffset(index);
// If this is the last child index + 1 will return the total
// chracter count.
*aEndOffset = GetChildOffset(index + 1);
}
}
LocalAccessible* HyperTextAccessibleWrap::LeafAtOffset(int32_t aOffset) {
HyperTextAccessible* text = this;
LocalAccessible* child = nullptr;
// The offset needed should "attach" the previous accessible if
// in between two accessibles.
int32_t innerOffset = aOffset > 0 ? aOffset - 1 : aOffset;
do {
int32_t childIdx = text->GetChildIndexAtOffset(innerOffset);
if (childIdx == -1) {
return text;
}
child = text->LocalChildAt(childIdx);
if (!child || nsAccUtils::MustPrune(text)) {
return text;
}
innerOffset -= text->GetChildOffset(childIdx);
text = child->AsHyperText();
} while (text);
return child;
}
void HyperTextAccessibleWrap::SelectRange(int32_t aStartOffset,
HyperTextAccessible* aEndContainer,
int32_t aEndOffset) {
TextLeafPoint start = ToTextLeafPoint(aStartOffset);
TextLeafPoint end = aEndContainer ? aEndContainer->ToTextLeafPoint(aEndOffset)
: TextLeafPoint();
TextLeafRange range(start, end);
if (range) {
range.SetSelection(0);
}
}
TextPoint HyperTextAccessibleWrap::FindTextPoint(
int32_t aOffset, nsDirection aDirection, nsSelectionAmount aAmount,
EWordMovementType aWordMovementType) {
// Layout can remain trapped in an editable. We normalize out of
// it if we are in its last offset.
HyperTextIterator iter(this, aOffset, this, CharacterCount());
if (aDirection == eDirNext) {
iter.NormalizeForward();
} else {
iter.NormalizeBackward();
}
// Find a leaf accessible frame to start with. PeekOffset wants this.
HyperTextAccessible* text = iter.mCurrentContainer;
LocalAccessible* child = nullptr;
int32_t innerOffset = iter.mCurrentStartOffset;
do {
int32_t childIdx = text->GetChildIndexAtOffset(innerOffset);
// We can have an empty text leaf as our only child. Since empty text
// leaves are not accessible we then have no children, but 0 is a valid
// innerOffset.
if (childIdx == -1) {
NS_ASSERTION(innerOffset == 0 && !text->ChildCount(), "No childIdx?");
return TextPoint(text, 0);
}
child = text->LocalChildAt(childIdx);
if (child->IsHyperText() && !child->ChildCount()) {
// If this is a childless hypertext, jump to its
// previous or next sibling, depending on
// direction.
if (aDirection == eDirPrevious && childIdx > 0) {
child = text->LocalChildAt(--childIdx);
} else if (aDirection == eDirNext &&
childIdx + 1 < static_cast<int32_t>(text->ChildCount())) {
child = text->LocalChildAt(++childIdx);
}
}
int32_t childOffset = text->GetChildOffset(childIdx);
if (child->IsHyperText() && aDirection == eDirPrevious && childIdx > 0 &&
innerOffset - childOffset == 0) {
// If we are searching backwards, and this is the begining of a
// segment, get the previous sibling so that layout will start
// its search there.
childIdx--;
innerOffset -= text->GetChildOffset(childIdx);
child = text->LocalChildAt(childIdx);
} else {
innerOffset -= childOffset;
}
text = child->AsHyperText();
} while (text);
nsIFrame* childFrame = child->GetFrame();
if (!childFrame) {
NS_ERROR("No child frame");
return TextPoint(this, aOffset);
}
int32_t innerContentOffset = innerOffset;
if (child->IsTextLeaf()) {
NS_ASSERTION(childFrame->IsTextFrame(), "Wrong frame!");
RenderedToContentOffset(childFrame, innerOffset, &innerContentOffset);
}
nsIFrame* frameAtOffset = childFrame;
int32_t offsetInFrame = 0;
childFrame->GetChildFrameContainingOffset(innerContentOffset, true,
&offsetInFrame, &frameAtOffset);
if (aDirection == eDirPrevious && offsetInFrame == 0) {
// If we are searching backwards, and we are at the start of a frame,
// get the previous continuation frame.
if (nsIFrame* prevInContinuation = frameAtOffset->GetPrevContinuation()) {
frameAtOffset = prevInContinuation;
}
}
PeekOffsetStruct pos(
aAmount, aDirection, innerContentOffset, nsPoint(0, 0),
{PeekOffsetOption::JumpLines, PeekOffsetOption::IsKeyboardSelect,
PeekOffsetOption::PreserveSpaces},
aWordMovementType);
nsresult rv = frameAtOffset->PeekOffset(&pos);
// PeekOffset fails on last/first lines of the text in certain cases.
if (NS_FAILED(rv) && aAmount == eSelectLine) {
pos.mAmount = aDirection == eDirNext ? eSelectEndLine : eSelectBeginLine;
frameAtOffset->PeekOffset(&pos);
}
if (!pos.mResultContent) {
NS_ERROR("No result content!");
return TextPoint(this, aOffset);
}
if (aDirection == eDirNext &&
nsContentUtils::PositionIsBefore(pos.mResultContent, mContent, nullptr,
nullptr)) {
// Bug 1652833 makes us sometimes return the first element on the doc.
return TextPoint(Document(), nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT);
}
HyperTextAccessible* container =
nsAccUtils::GetTextContainer(pos.mResultContent);
int32_t offset = container ? container->DOMPointToOffset(
pos.mResultContent, pos.mContentOffset,
aDirection == eDirNext)
: 0;
return TextPoint(container, offset);
}
HyperTextAccessibleWrap* HyperTextAccessibleWrap::EditableRoot() {
LocalAccessible* editable = nullptr;
for (LocalAccessible* acc = this; acc && acc != Document();
acc = acc->LocalParent()) {
if (acc->NativeState() & states::EDITABLE) {
editable = acc;
} else {
break;
}
}
return static_cast<HyperTextAccessibleWrap*>(editable->AsHyperText());
}

Просмотреть файл

@ -18,7 +18,6 @@ UNIFIED_SOURCES += [
"AccessibleWrap.mm",
"DocAccessibleWrap.mm",
"GeckoTextMarker.mm",
"HyperTextAccessibleWrap.mm",
"MacUtils.mm",
"MOXAccessibleBase.mm",
"MOXLandmarkAccessibles.mm",

Просмотреть файл

@ -36,39 +36,9 @@ platform = notwin
description = Legacy a11y IPC
platform = win
[PDocAccessiblePlatformExt::RangeAt]
description = Retrieve a text range given an offset and range type. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::NextClusterAt]
description = Retrieve next character from offset. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::PreviousClusterAt]
description = Retrieve previous character from offset. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::TextForRange]
description = Retrieve flattened string for text range. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::BoundsForRange]
description = Retrieve geometric bounds for text range. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::LengthForRange]
description = Retrieve length of text range. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::OffsetAtIndex]
description = Retrieve text offset at absolute index. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::RangeOfChild]
description = Retrieve text range in parent of child. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::LeafAtOffset]
description = Retrieve text leaf at given offset. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::ApplyPostSearchFilter]
description = Filter a preliminary list of accessibles that match a predicate. Platform API is synchronous, so this needs to be too.
platform = mac
[PDocAccessiblePlatformExt::AttributedTextForRange]
description = Retrieve a text range along with associated attributes given an offset and range type. Platform API is synchronous, so this needs to be too.
platform = mac
# The rest
[PHeapSnapshotTempFileHelper::OpenHeapSnapshotTempFile]