diff --git a/accessible/tests/browser/windows/uia/browser_textPatterns.js b/accessible/tests/browser/windows/uia/browser_textPatterns.js
index 3840530f0509..efe3e7e9e901 100644
--- a/accessible/tests/browser/windows/uia/browser_textPatterns.js
+++ b/accessible/tests/browser/windows/uia/browser_textPatterns.js
@@ -1,3 +1,4 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
/* 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/. */
@@ -2162,6 +2163,69 @@ addUiaTask(
{ uiaEnabled: true, uiaDisabled: true, chrome: true }
);
+/**
+ * Test the Text pattern's GetBoundingRectangles method with the caret.
+ */
+addUiaTask(
+ `
+
+ `,
+ async function testTextRangeGetBoundingRectanglesCaret(browser, docAcc) {
+ info("Focusing editable");
+ const editable = findAccessibleChildByID(docAcc, "editable");
+ const ce0 = findAccessibleChildByID(docAcc, "ce0");
+ let moved = waitForEvent(EVENT_TEXT_CARET_MOVED, ce0);
+ editable.takeFocus();
+ await moved;
+ await runPython(`
+ global text
+ doc = getDocUia()
+ editable = findUiaByDomId(doc, "editable")
+ text = getUiaPattern(editable, "Text")
+ `);
+ let uiaRects = await runPython(
+ `text.GetSelection().GetElement(0).GetBoundingRectangles()`
+ );
+ testTextPos(ce0, 0, [uiaRects[0], uiaRects[1]], COORDTYPE_SCREEN_RELATIVE);
+
+ info("ArrowRight to end of line");
+ moved = waitForEvent(EVENT_TEXT_CARET_MOVED, ce0);
+ EventUtils.synthesizeKey("KEY_ArrowRight");
+ await moved;
+ uiaRects = await runPython(
+ `text.GetSelection().GetElement(0).GetBoundingRectangles()`
+ );
+ // Bug 1966812: We would ideally return a rect here.
+ is(uiaRects.length, 0, "GetBoundingRectangles returned nothing");
+
+ info("ArrowRight to line feed on blank line");
+ const ce1 = findAccessibleChildByID(docAcc, "ce1");
+ moved = waitForEvent(EVENT_TEXT_CARET_MOVED, ce1);
+ EventUtils.synthesizeKey("KEY_ArrowRight");
+ await moved;
+ uiaRects = await runPython(
+ `text.GetSelection().GetElement(0).GetBoundingRectangles()`
+ );
+ testTextPos(ce1, 0, [uiaRects[0], uiaRects[1]], COORDTYPE_SCREEN_RELATIVE);
+
+ info("ArrowRight to b");
+ const ce2 = findAccessibleChildByID(docAcc, "ce2");
+ moved = waitForEvent(EVENT_TEXT_CARET_MOVED, ce2);
+ EventUtils.synthesizeKey("KEY_ArrowRight");
+ await moved;
+ uiaRects = await runPython(
+ `text.GetSelection().GetElement(0).GetBoundingRectangles()`
+ );
+ testTextPos(ce2, 0, [uiaRects[0], uiaRects[1]], COORDTYPE_SCREEN_RELATIVE);
+ },
+ // The IA2 -> UIA proxy doesn't support this.
+ { uiaEnabled: true, uiaDisabled: false }
+);
+
/**
* Test the TextRange pattern's ScrollIntoView method.
*/
diff --git a/accessible/windows/uia/UiaTextRange.cpp b/accessible/windows/uia/UiaTextRange.cpp
index defdc5248a20..3806dce9e0c5 100644
--- a/accessible/windows/uia/UiaTextRange.cpp
+++ b/accessible/windows/uia/UiaTextRange.cpp
@@ -703,7 +703,21 @@ UiaTextRange::GetBoundingRectangles(__RPC__deref_out_opt SAFEARRAY** aRetVal) {
}
// Get the rectangles for each line.
- const nsTArray lineRects = range.LineRects();
+ nsTArray lineRects = range.LineRects();
+ if (lineRects.IsEmpty() && !mIsEndOfLineInsertionPoint &&
+ range.Start() == range.End()) {
+ // The documentation for GetBoundingRectangles says that we should return
+ // "An empty array for a degenerate range.":
+ // https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcore/nf-uiautomationcore-itextrangeprovider-getboundingrectangles#return-value
+ // This is exactly what range.LineRects() just did. However, contrary to
+ // this, some clients (including Microsoft Text Cursor Indicator) call
+ // GetBoundingRectangles on a degenerate range when querying the caret and
+ // expect rectangles to be returned. Therefore, use the character bounds.
+ // Bug 1966812: Ideally, we would also return a rectangle when
+ // mIsEndOfLineInsertionPoint is true. However, we don't currently have code
+ // to calculate a rectangle in that case.
+ lineRects.AppendElement(range.Start().CharBounds());
+ }
// For UIA's purposes, the rectangles of this array are four doubles arranged
// in order {left, top, width, height}.