Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 978fa86

Browse files
committed
Bug 1901464 part 3: Implement ITextProvider::GetVisibleRanges. r=nlapre
Differential Revision: https://phabricator.services.mozilla.com/D236090
1 parent 2a6f993 commit 978fa86

File tree

4 files changed

+120
-1
lines changed

4 files changed

+120
-1
lines changed

accessible/base/TextLeafRange.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,6 +2240,26 @@ void TextLeafRange::ScrollIntoView(uint32_t aScrollType) const {
22402240
aScrollType);
22412241
}
22422242

2243+
nsTArray<TextLeafRange> TextLeafRange::VisibleLines(
2244+
Accessible* aContainer) const {
2245+
MOZ_ASSERT(aContainer);
2246+
// We want to restrict our lines to those visible within aContainer.
2247+
LayoutDeviceIntRect containerBounds = aContainer->Bounds();
2248+
nsTArray<TextLeafRange> lines;
2249+
WalkLineRects([&lines, &containerBounds](TextLeafRange aLine,
2250+
LayoutDeviceIntRect aLineRect) {
2251+
// XXX This doesn't correctly handle lines that are scrolled out where the
2252+
// scroll container is a descendant of aContainer. Such lines might
2253+
// intersect with containerBounds, but the scroll container could be a
2254+
// descendant of aContainer and should thus exclude this line. See bug
2255+
// 1945010 for more details.
2256+
if (aLineRect.Intersects(containerBounds)) {
2257+
lines.AppendElement(aLine);
2258+
}
2259+
});
2260+
return lines;
2261+
}
2262+
22432263
bool TextLeafRange::WalkLineRects(LineRectCallback aCallback) const {
22442264
if (mEnd <= mStart) {
22452265
return false;

accessible/base/TextLeafRange.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,12 @@ class TextLeafRange final {
329329

330330
MOZ_CAN_RUN_SCRIPT void ScrollIntoView(uint32_t aScrollType) const;
331331

332+
/**
333+
* Returns sub-ranges for all the lines in this range visible within the given
334+
* container Accessible.
335+
*/
336+
nsTArray<TextLeafRange> VisibleLines(Accessible* aContainer) const;
337+
332338
private:
333339
TextLeafPoint mStart;
334340
TextLeafPoint mEnd;

accessible/tests/browser/windows/uia/browser_textPatterns.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,3 +2209,82 @@ addUiaTask(
22092209
},
22102210
{ uiaEnabled: true, uiaDisabled: true }
22112211
);
2212+
2213+
/**
2214+
* Test the Text pattern's GetVisibleRanges method.
2215+
*/
2216+
addUiaTask(
2217+
`
2218+
<div id="div">
2219+
<p>line1</p>
2220+
<p>line2</p>
2221+
<p style="position: absolute; left: -10000px; width: 1px;">line3</p>
2222+
<p>line4</p>
2223+
</div>
2224+
<!-- We use 0.5lh so the second line is definitely fully scrolled out.
2225+
With 1lh, it could be partially visible and thus included. -->
2226+
<textarea id="textarea" style="height: 0.5lh;">line5
2227+
line6
2228+
line7</textarea>
2229+
<hr aria-hidden="true" style="height: 100vh;">
2230+
<p>line8</p>
2231+
`,
2232+
async function testTextGetVisibleRanges() {
2233+
await runPython(`
2234+
global doc, docText, ranges
2235+
doc = getDocUia()
2236+
docText = getUiaPattern(doc, "Text")
2237+
ranges = docText.GetVisibleRanges()
2238+
`);
2239+
// XXX This should be 4 once we fix the scrolling case below.
2240+
is(
2241+
await runPython(`ranges.Length`),
2242+
6,
2243+
"doc has correct number of visible ranges"
2244+
);
2245+
is(
2246+
await runPython(`ranges.GetElement(0).GetText(-1)`),
2247+
"line1",
2248+
"range 0 text correct"
2249+
);
2250+
is(
2251+
await runPython(`ranges.GetElement(1).GetText(-1)`),
2252+
"line2",
2253+
"range 1 text correct"
2254+
);
2255+
// line3 is off-screen and thus not visible.
2256+
is(
2257+
await runPython(`ranges.GetElement(2).GetText(-1)`),
2258+
"line4",
2259+
"range 2 text correct"
2260+
);
2261+
is(
2262+
await runPython(`ranges.GetElement(3).GetText(-1)`),
2263+
"line5\n",
2264+
"range 3 text correct"
2265+
);
2266+
// XXX line6 and line7 are scrolled off screen by the textarea, but we
2267+
// incorrectly return them for now (ranges 4 and 5).
2268+
// line8 is scrolled off screen by the document.
2269+
2270+
await runPython(`
2271+
textarea = findUiaByDomId(doc, "textarea")
2272+
textareaText = getUiaPattern(textarea, "Text")
2273+
global ranges
2274+
ranges = textareaText.GetVisibleRanges()
2275+
`);
2276+
is(
2277+
await runPython(`ranges.Length`),
2278+
1,
2279+
"textarea has correct number of visible ranges"
2280+
);
2281+
is(
2282+
await runPython(`ranges.GetElement(0).GetText(-1)`),
2283+
"line5\n",
2284+
"range 0 text correct"
2285+
);
2286+
// line6 and line7 are scrolled off screen by the textarea.
2287+
},
2288+
// The IA2 -> UIA proxy doesn't support GetVisibleRanges.
2289+
{ uiaEnabled: true, uiaDisabled: false }
2290+
);

accessible/windows/uia/UiaText.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,21 @@ UiaText::GetSelection(__RPC__deref_out_opt SAFEARRAY** aRetVal) {
6666

6767
STDMETHODIMP
6868
UiaText::GetVisibleRanges(__RPC__deref_out_opt SAFEARRAY** aRetVal) {
69-
return E_NOTIMPL;
69+
if (!aRetVal) {
70+
return E_INVALIDARG;
71+
}
72+
Accessible* acc = Acc();
73+
if (!acc) {
74+
return CO_E_OBJNOTCONNECTED;
75+
}
76+
TextLeafRange fullRange = TextLeafRange::FromAccessible(acc);
77+
// The most pragmatic way to determine visible text is to walk by line.
78+
// XXX TextLeafRange::VisibleLines doesn't correctly handle lines that are
79+
// scrolled out where the scroll container is a descendant of acc. See bug
80+
// 1945010.
81+
nsTArray<TextLeafRange> ranges = fullRange.VisibleLines(acc);
82+
*aRetVal = TextLeafRangesToUiaRanges(ranges);
83+
return S_OK;
7084
}
7185

7286
STDMETHODIMP

0 commit comments

Comments
 (0)