зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1730085 part 2: Implement support for BOUNDARY_LINE_END in TextLeafPoint and HyperTextAccessibleBase. r=eeejay
BOUNDARY_LINE_END is implemented using BOUNDARY_LINE_START and adjusting for line feed characters, which are line end boundaries where present. Differential Revision: https://phabricator.services.mozilla.com/D138103
This commit is contained in:
Родитель
9e62d53a3d
Коммит
df5caa3102
|
@ -424,6 +424,12 @@ bool TextLeafPoint::IsEmptyLastLine() const {
|
|||
return text.CharAt(0) == '\n';
|
||||
}
|
||||
|
||||
char16_t TextLeafPoint::GetChar() const {
|
||||
nsAutoString text;
|
||||
mAcc->AppendTextTo(text, mOffset, 1);
|
||||
return text.CharAt(0);
|
||||
}
|
||||
|
||||
TextLeafPoint TextLeafPoint::FindPrevLineStartSameLocalAcc(
|
||||
bool aIncludeOrigin) const {
|
||||
LocalAccessible* acc = mAcc->AsLocal();
|
||||
|
@ -743,6 +749,9 @@ TextLeafPoint TextLeafPoint::FindBoundary(AccessibleTextBoundary aBoundaryType,
|
|||
return ActualizeCaret().FindBoundary(aBoundaryType, aDirection,
|
||||
aIncludeOrigin);
|
||||
}
|
||||
if (aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_END) {
|
||||
return FindLineEnd(aDirection, aIncludeOrigin);
|
||||
}
|
||||
if (aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START &&
|
||||
aIncludeOrigin && aDirection == eDirPrevious && IsEmptyLastLine()) {
|
||||
// If we're at an empty line at the end of an Accessible, we don't want to
|
||||
|
@ -818,6 +827,46 @@ TextLeafPoint TextLeafPoint::FindBoundary(AccessibleTextBoundary aBoundaryType,
|
|||
return TextLeafPoint();
|
||||
}
|
||||
|
||||
TextLeafPoint TextLeafPoint::FindLineEnd(nsDirection aDirection,
|
||||
bool aIncludeOrigin) const {
|
||||
if (aDirection == eDirPrevious && IsEmptyLastLine()) {
|
||||
// If we're at an empty line at the end of an Accessible, we don't want to
|
||||
// walk into the previous line. For example, this can happen if the caret
|
||||
// is positioned on an empty line at the end of a textarea.
|
||||
// Because we want the line end, we must walk back to the line feed
|
||||
// character.
|
||||
return FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious);
|
||||
}
|
||||
if (aIncludeOrigin && IsLineFeedChar()) {
|
||||
return *this;
|
||||
}
|
||||
if (aDirection == eDirPrevious && !aIncludeOrigin) {
|
||||
// If there is a line feed immediately before us, return that.
|
||||
TextLeafPoint prevChar =
|
||||
FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious);
|
||||
if (prevChar.IsLineFeedChar()) {
|
||||
return prevChar;
|
||||
}
|
||||
}
|
||||
TextLeafPoint searchFrom = *this;
|
||||
if (aDirection == eDirNext && (IsLineFeedChar() || IsEmptyLastLine())) {
|
||||
// If we search for the next line start from a line feed, we'll get the
|
||||
// character immediately following the line feed. We actually want the
|
||||
// next line start after that. Skip the line feed.
|
||||
searchFrom = FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirNext);
|
||||
}
|
||||
TextLeafPoint lineStart = searchFrom.FindBoundary(
|
||||
nsIAccessibleText::BOUNDARY_LINE_START, aDirection, aIncludeOrigin);
|
||||
// If there is a line feed before this line start (at the end of the previous
|
||||
// line), we must return that.
|
||||
TextLeafPoint prevChar = lineStart.FindBoundary(
|
||||
nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious, false);
|
||||
if (prevChar && prevChar.IsLineFeedChar()) {
|
||||
return prevChar;
|
||||
}
|
||||
return lineStart;
|
||||
}
|
||||
|
||||
already_AddRefed<AccAttributes> TextLeafPoint::GetTextAttributesLocalAcc(
|
||||
bool aIncludeDefaults) const {
|
||||
LocalAccessible* acc = mAcc->AsLocal();
|
||||
|
|
|
@ -146,9 +146,13 @@ class TextLeafPoint final {
|
|||
const AccAttributes* aOriginAttrs = nullptr,
|
||||
bool aIncludeDefaults = true) const;
|
||||
|
||||
bool IsLineFeedChar() const { return GetChar() == '\n'; }
|
||||
|
||||
private:
|
||||
bool IsEmptyLastLine() const;
|
||||
|
||||
char16_t GetChar() const;
|
||||
|
||||
TextLeafPoint FindLineStartSameRemoteAcc(nsDirection aDirection,
|
||||
bool aIncludeOrigin) const;
|
||||
|
||||
|
@ -158,6 +162,8 @@ class TextLeafPoint final {
|
|||
*/
|
||||
TextLeafPoint FindLineStartSameAcc(nsDirection aDirection,
|
||||
bool aIncludeOrigin) const;
|
||||
|
||||
TextLeafPoint FindLineEnd(nsDirection aDirection, bool aIncludeOrigin) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -216,6 +216,24 @@ std::pair<bool, int32_t> HyperTextAccessibleBase::TransformOffset(
|
|||
return {false, aIsEndOffset ? static_cast<int32_t>(CharacterCount()) : 0};
|
||||
}
|
||||
|
||||
void HyperTextAccessibleBase::AdjustOriginIfEndBoundary(
|
||||
TextLeafPoint& aOrigin, AccessibleTextBoundary aBoundaryType) const {
|
||||
if (aBoundaryType != nsIAccessibleText::BOUNDARY_LINE_END &&
|
||||
aBoundaryType != nsIAccessibleText::BOUNDARY_WORD_END) {
|
||||
return;
|
||||
}
|
||||
TextLeafPoint actualOrig =
|
||||
aOrigin.IsCaret() ? aOrigin.ActualizeCaret(/* aAdjustAtEndOfLine */ false)
|
||||
: aOrigin;
|
||||
if (aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_END) {
|
||||
if (!actualOrig.IsLineFeedChar()) {
|
||||
return;
|
||||
}
|
||||
aOrigin =
|
||||
actualOrig.FindBoundary(nsIAccessibleText::BOUNDARY_CHAR, eDirPrevious);
|
||||
}
|
||||
}
|
||||
|
||||
void HyperTextAccessibleBase::TextBeforeOffset(
|
||||
int32_t aOffset, AccessibleTextBoundary aBoundaryType,
|
||||
int32_t* aStartOffset, int32_t* aEndOffset, nsAString& aText) {
|
||||
|
@ -238,12 +256,14 @@ void HyperTextAccessibleBase::TextBeforeOffset(
|
|||
break;
|
||||
case nsIAccessibleText::BOUNDARY_WORD_START:
|
||||
case nsIAccessibleText::BOUNDARY_LINE_START:
|
||||
case nsIAccessibleText::BOUNDARY_LINE_END:
|
||||
TextLeafPoint orig;
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
|
||||
orig = TextLeafPoint::GetCaret(Acc());
|
||||
} else {
|
||||
orig = ToTextLeafPoint(static_cast<int32_t>(adjustedOffset));
|
||||
}
|
||||
AdjustOriginIfEndBoundary(orig, aBoundaryType);
|
||||
TextLeafPoint end = orig.FindBoundary(aBoundaryType, eDirPrevious,
|
||||
/* aIncludeOrigin */ true);
|
||||
bool ok;
|
||||
|
@ -293,11 +313,14 @@ void HyperTextAccessibleBase::TextAtOffset(int32_t aOffset,
|
|||
break;
|
||||
case nsIAccessibleText::BOUNDARY_WORD_START:
|
||||
case nsIAccessibleText::BOUNDARY_LINE_START:
|
||||
TextLeafPoint origStart, end;
|
||||
case nsIAccessibleText::BOUNDARY_LINE_END:
|
||||
TextLeafPoint start, end;
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
|
||||
origStart = end = TextLeafPoint::GetCaret(Acc());
|
||||
start = TextLeafPoint::GetCaret(Acc());
|
||||
AdjustOriginIfEndBoundary(start, aBoundaryType);
|
||||
end = start;
|
||||
} else {
|
||||
origStart = ToTextLeafPoint(static_cast<int32_t>(adjustedOffset));
|
||||
start = ToTextLeafPoint(static_cast<int32_t>(adjustedOffset));
|
||||
Accessible* childAcc = GetChildAtOffset(adjustedOffset);
|
||||
if (childAcc && childAcc->IsHyperText()) {
|
||||
// We're searching for boundaries enclosing an embedded object.
|
||||
|
@ -310,11 +333,12 @@ void HyperTextAccessibleBase::TextAtOffset(int32_t aOffset,
|
|||
end = ToTextLeafPoint(static_cast<int32_t>(adjustedOffset),
|
||||
/* aDescendToEnd */ true);
|
||||
} else {
|
||||
end = origStart;
|
||||
AdjustOriginIfEndBoundary(start, aBoundaryType);
|
||||
end = start;
|
||||
}
|
||||
}
|
||||
TextLeafPoint start = origStart.FindBoundary(aBoundaryType, eDirPrevious,
|
||||
/* aIncludeOrigin */ true);
|
||||
start = start.FindBoundary(aBoundaryType, eDirPrevious,
|
||||
/* aIncludeOrigin */ true);
|
||||
bool ok;
|
||||
std::tie(ok, *aStartOffset) = TransformOffset(start.mAcc, start.mOffset,
|
||||
/* aIsEndOffset */ false);
|
||||
|
@ -352,6 +376,7 @@ void HyperTextAccessibleBase::TextAfterOffset(
|
|||
}
|
||||
case nsIAccessibleText::BOUNDARY_WORD_START:
|
||||
case nsIAccessibleText::BOUNDARY_LINE_START:
|
||||
case nsIAccessibleText::BOUNDARY_LINE_END:
|
||||
TextLeafPoint orig;
|
||||
if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
|
||||
orig = TextLeafPoint::GetCaret(Acc());
|
||||
|
@ -359,6 +384,7 @@ void HyperTextAccessibleBase::TextAfterOffset(
|
|||
orig = ToTextLeafPoint(static_cast<int32_t>(adjustedOffset),
|
||||
/* aDescendToEnd */ true);
|
||||
}
|
||||
AdjustOriginIfEndBoundary(orig, aBoundaryType);
|
||||
TextLeafPoint start = orig.FindBoundary(aBoundaryType, eDirNext);
|
||||
bool ok;
|
||||
std::tie(ok, *aStartOffset) = TransformOffset(start.mAcc, start.mOffset,
|
||||
|
|
|
@ -178,6 +178,16 @@ class HyperTextAccessibleBase {
|
|||
std::pair<bool, int32_t> TransformOffset(Accessible* aDescendant,
|
||||
int32_t aOffset,
|
||||
bool aIsEndOffset) const;
|
||||
|
||||
/**
|
||||
* Helper method for TextBefore/At/AfterOffset.
|
||||
* If BOUNDARY_LINE_END was requested and the origin is itself a line end
|
||||
* boundary, we must use the line which ends at the origin. We must do
|
||||
* similarly for BOUNDARY_WORD_END. This method adjusts the origin
|
||||
* accordingly.
|
||||
*/
|
||||
void AdjustOriginIfEndBoundary(TextLeafPoint& aOrigin,
|
||||
AccessibleTextBoundary aBoundaryType) const;
|
||||
};
|
||||
|
||||
} // namespace mozilla::a11y
|
||||
|
|
|
@ -922,7 +922,8 @@ void HyperTextAccessible::TextBeforeOffset(int32_t aOffset,
|
|||
nsAString& aText) {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup() &&
|
||||
(aBoundaryType == nsIAccessibleText::BOUNDARY_WORD_START ||
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START)) {
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START ||
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_END)) {
|
||||
// This isn't strictly related to caching, but this new text implementation
|
||||
// is being developed to make caching feasible. We put it behind this pref
|
||||
// to make it easy to test while it's still under development.
|
||||
|
@ -1011,7 +1012,8 @@ void HyperTextAccessible::TextAtOffset(int32_t aOffset,
|
|||
int32_t* aEndOffset, nsAString& aText) {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup() &&
|
||||
(aBoundaryType == nsIAccessibleText::BOUNDARY_WORD_START ||
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START)) {
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START ||
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_END)) {
|
||||
// This isn't strictly related to caching, but this new text implementation
|
||||
// is being developed to make caching feasible. We put it behind this pref
|
||||
// to make it easy to test while it's still under development.
|
||||
|
@ -1108,7 +1110,8 @@ void HyperTextAccessible::TextAfterOffset(int32_t aOffset,
|
|||
nsAString& aText) {
|
||||
if (StaticPrefs::accessibility_cache_enabled_AtStartup() &&
|
||||
(aBoundaryType == nsIAccessibleText::BOUNDARY_WORD_START ||
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START)) {
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_START ||
|
||||
aBoundaryType == nsIAccessibleText::BOUNDARY_LINE_END)) {
|
||||
// This isn't strictly related to caching, but this new text implementation
|
||||
// is being developed to make caching feasible. We put it behind this pref
|
||||
// to make it easy to test while it's still under development.
|
||||
|
|
|
@ -57,6 +57,25 @@ ef gh</pre>
|
|||
[0, 5, "ef gh", 6, 11],
|
||||
[6, 11, "", 11, 11],
|
||||
]);
|
||||
if (isWinNoCache) {
|
||||
todo(
|
||||
false,
|
||||
"Cache disabled, so RemoteAccessible doesn't support BOUNDARY_LINE_END on Windows"
|
||||
);
|
||||
} else {
|
||||
testTextAtOffset(acc, BOUNDARY_LINE_END, [
|
||||
[0, 5, "ab cd", 0, 5],
|
||||
[6, 11, "\nef gh", 5, 11],
|
||||
]);
|
||||
testTextBeforeOffset(acc, BOUNDARY_LINE_END, [
|
||||
[0, 5, "", 0, 0],
|
||||
[6, 11, "ab cd", 0, 5],
|
||||
]);
|
||||
testTextAfterOffset(acc, BOUNDARY_LINE_END, [
|
||||
[0, 5, "\nef gh", 5, 11],
|
||||
[6, 11, "", 11, 11],
|
||||
]);
|
||||
}
|
||||
testTextAtOffset(acc, BOUNDARY_WORD_START, [
|
||||
[0, 2, "ab ", 0, 3],
|
||||
[3, 5, "cd\n", 3, 6],
|
||||
|
|
Загрузка…
Ссылка в новой задаче