зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
19ab04b63e
Коммит
9b58fed3a9
|
@ -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]
|
||||
|
|
Загрузка…
Ссылка в новой задаче