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( + ` +
+
a
+

+
b
+
+ `, + 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}.