diff --git a/accessible/base/NotificationController.cpp b/accessible/base/NotificationController.cpp index f9fc625c0219..1a31014f9a50 100644 --- a/accessible/base/NotificationController.cpp +++ b/accessible/base/NotificationController.cpp @@ -823,11 +823,10 @@ void NotificationController::WillRefresh(mozilla::TimeStamp aTime) { if (textAcc) { // Remove the TextLeafAccessible if: // 1. The rendered text is empty; or - // 2. The text is just a space, but its layout frame has a width of 0, - // so it isn't visible. This can happen if there is whitespace before an - // invisible element at the end of a block. + // 2. The text is invisible, semantically irrelevant whitespace before a + // hard line break. if (text.mString.IsEmpty() || - (text.mString.EqualsLiteral(" ") && textFrame->GetRect().IsEmpty())) { + nsCoreUtils::IsTrimmedWhitespaceBeforeHardLineBreak(textFrame)) { #ifdef A11Y_LOG if (logging::IsEnabled(logging::eTree | logging::eText)) { logging::MsgBegin("TREE", "text node lost its content; doc: %p", diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index 88ed7332b4aa..844af4980d4f 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -1306,7 +1306,7 @@ LocalAccessible* nsAccessibilityService::CreateAccessible( // Ignore not rendered text nodes and whitespace text nodes between table // cells. if (text.mString.IsEmpty() || - (text.mString.EqualsLiteral(" ") && frame->GetRect().IsEmpty()) || + nsCoreUtils::IsTrimmedWhitespaceBeforeHardLineBreak(frame) || (aContext->IsTableRow() && nsCoreUtils::IsWhitespaceString(text.mString))) { if (aIsSubtreeHidden) *aIsSubtreeHidden = true; diff --git a/accessible/base/nsCoreUtils.cpp b/accessible/base/nsCoreUtils.cpp index de8320f0f459..fa76cc481c9a 100644 --- a/accessible/base/nsCoreUtils.cpp +++ b/accessible/base/nsCoreUtils.cpp @@ -661,3 +661,19 @@ Element* nsCoreUtils::GetAriaActiveDescendantElement(Element* aElement) { return nullptr; } + +bool nsCoreUtils::IsTrimmedWhitespaceBeforeHardLineBreak(nsIFrame* aFrame) { + if (!aFrame->GetRect().IsEmpty() || + !aFrame->HasAnyStateBits(TEXT_END_OF_LINE)) { + return false; + } + // Normally, accessibility calls nsIFrame::GetRenderedText with + // TrailingWhitespace::NoTrim. Using TrailingWhitespace::Trim instead trims 0 + // width whitespace before a hard line break, resulting in an empty string if + // that is all the frame contains. Note that TrailingWhitespace::Trim does + // *not* trim whitespace before a soft line break (wrapped line). + nsIFrame::RenderedText text = aFrame->GetRenderedText( + 0, UINT32_MAX, nsIFrame::TextOffsetType::OffsetsInContentText, + nsIFrame::TrailingWhitespace::Trim); + return text.mString.IsEmpty(); +} diff --git a/accessible/base/nsCoreUtils.h b/accessible/base/nsCoreUtils.h index fe46bf4fdf7d..67a5889834b0 100644 --- a/accessible/base/nsCoreUtils.h +++ b/accessible/base/nsCoreUtils.h @@ -336,6 +336,17 @@ class nsCoreUtils { nsINode* aStartAncestor); static Element* GetAriaActiveDescendantElement(Element* aElement); + + /** + * Return true if the given text frame is 0 width whitespace before a hard + * line break. This is not visible and is semantically irrelevant. This can + * happen if there is whitespace before an invisible element at the end of a + * block. For example: + *