Closed Bug 1897597 Opened 2 years ago Closed 2 years ago

IAccessibleText assumes lines breaks when switching text direction

Categories

(Core :: Disability Access APIs, defect)

Firefox 126
defect

Tracking

()

RESOLVED FIXED
128 Branch
Tracking Status
firefox128 --- fixed

People

(Reporter: alderuijter, Assigned: Jamie)

References

(Blocks 1 open bug)

Details

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0

Steps to reproduce:

  1. With NVDA as a screen reader on Windows, open Firefox
  2. On the address bar, type: data:text/html, <textarea />
  3. In the text area, type: The first hebrew letter is א, the second is ב.
  4. Use up and down arrows to move through the text.

Actual results:

NVDA fails to read the hebrew characters in the text.
Inspection with IAccessibleTextObject.textAtOffset reveals that erroneous line breaks are assumed around the hebrew characters. Therefore when NVDA retrieves offsets with textAtOffset using IA2_TEXT_BOUNDARY_LINE, it receives partial lines.

Expected results:

NVDA reads the text as provided, including Hebrew characters.

Morgan, I vaguely recall us thinking we would probably hit a problem like this with bidi text, but I can't remember whether we got any further than that thought.

When a single text node wraps across lines, it gets split into continuations. Thus, a11y::TextLeafRange treats continuations as line breaks. I haven't looked at the layout frame tree yet, but I'm fairly sure changes in text direction cause text to be split into continuations as well. Thus, TextLeafRange incorrectly treats these as line breaks.

We could use a line iterator to detect this like we do in IsLocalAccAtLineStart, but I'd rather not because line iterators are complicated and potentially expensive. This led me to wonder whether there's some way to ask a continuation whether it was split because of a line break or bidi. I found two state bits of potential interest:

  1. NS_FRAME_IS_FLUID_CONTINUATION: For a continuation frame, if this bit is set, then this a "fluid" continuation, i.e., across a line boundary. Otherwise it's a "hard" continuation, e.g. a bidi continuation.
  2. NS_FRAME_IS_BIDI: If this bit is set, the frame itself is a bidi continuation, or is incomplete (its next sibling is a bidi continuation).

I think we might need to use both of these because it seems that a hard/non-fluid continuation can also happen for other reasons.

There's also a concept of "flow", but I don't think we can use that because nsTextFrame::NextInFlow just returns null if the next continuation isn't fluid. In contrast, I think we want to skip past non-fluid continuations to any subsequent fluid continuations. That said, I'm not entirely clear what happens if you have both non-fluid (bidi) and fluid (line wrapping) continuations in the same text node.

Assuming I'm remotely correct here, we'll need to tweak TextLeafRange to skip non-fluid continuations when it walks. There are also some spots where we check the continuation of the origin that will probably need to be tweaked as well.

Blocks: texta11y
Severity: -- → S3
Status: UNCONFIRMED → NEW
Ever confirmed: true
OS: Unspecified → All
Hardware: Unspecified → All
Assignee: nobody → jteh

I have a patch locally which mostly fixes this. However, there is an edge case it doesn't handle:

data:text/html,<meta charset="utf-8"><p contenteditable style="font-family: monospace; width: 3ch; word-break: break-word">אb בב eא

A11y thinks the first line is:

"אb בב "

It should actually be:

"אb "

The second frame doesn't have NS_FRAME_IS_FLUID_CONTINUATION, I guess because it is in fact a bidi split... but it's also a line wrap!

:jfkthame, is there some cheap way I can detect a bidi continuation which also flows onto a new line?

Flags: needinfo?(jfkthame)

Continuations occur when text wraps onto a new line (fluid continuations), but they also occur when the text direction changes (non-fluid continuations).
Previously, TextLeafRange assumed that all continuations were line breaks.
We now skip non-fluid continuations when searching for the next or previous line break.

I guess one way might be to use a line iterator if a continuation is non-fluid and both it and its previous continuation have the NS_FRAME_IS_BIDI state bit. I'm still hoping for a solution that doesn't require a line iterator, though.

It sounds to me like a line iterator really is what you want here. IIRC we added some line iterator caching a while back, so it may not be terribly expensive.

Flags: needinfo?(jfkthame)

I was hoping you wouldn't say that, but... fair enough.

The problem is that we only have caching for nsBlockInFlowLineIterator, but there are frames other than block frames which can provide an nsILineIterator. The nsILineIterator for block frames doesn't cache. That means we need to use nsBlockInFlowLineIterator for block frames but nsILineIterator for everything else, which makes things complicated. I also worry there could be a case where nsILineIterator on a non-block frame gets expensive.

There should be no functional change here.
However, we're going to need to reuse this elsewhere in the next patch.

Attachment #9402683 - Attachment description: Bug 1897597 WIP: Don't treat non-fluid continuations as line breaks. → Bug 1897597 part 2 WIP: Don't treat bidi split continuations as line breaks.
Attachment #9402683 - Attachment description: Bug 1897597 part 2 WIP: Don't treat bidi split continuations as line breaks. → Bug 1897597 part 2: Don't treat bidi split continuations as line breaks.
Pushed by jteh@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/6652a57a0bc6 part 1: Split TextLeafRange code to check whether frames are on different lines into a separate function. r=morgan https://hg.mozilla.org/integration/autoland/rev/808efd1651fa part 2: Don't treat bidi split continuations as line breaks. r=morgan
Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 128 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: