diff --git a/accessible/src/generic/HyperTextAccessible.cpp b/accessible/src/generic/HyperTextAccessible.cpp index a2a7078f710c..b09eb7e41177 100644 --- a/accessible/src/generic/HyperTextAccessible.cpp +++ b/accessible/src/generic/HyperTextAccessible.cpp @@ -1084,6 +1084,9 @@ HyperTextAccessible::GetTextAtOffset(int32_t aOffset, } } + if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) + offset = AdjustCaretOffset(offset); + // Home key, arrow down and if not on last line then home key. *aStartOffset = FindLineBoundary(offset, eDirPrevious, eSelectBeginLine); *aEndOffset = FindLineBoundary(offset, eDirNext, eSelectLine); @@ -1109,6 +1112,9 @@ HyperTextAccessible::GetTextAtOffset(int32_t aOffset, } } + if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) + offset = AdjustCaretOffset(offset); + // In contrast to word end boundary we follow the spec here. End key, // then up arrow and if not on first line then end key. *aEndOffset = FindLineBoundary(offset, eDirNext, eSelectEndLine); diff --git a/accessible/src/generic/HyperTextAccessible.h b/accessible/src/generic/HyperTextAccessible.h index a0df003423b9..d348a5c64109 100644 --- a/accessible/src/generic/HyperTextAccessible.h +++ b/accessible/src/generic/HyperTextAccessible.h @@ -263,6 +263,26 @@ protected: return aOffset; } + /** + * Adjust an offset the caret stays at to get a text by line boundary. + */ + int32_t AdjustCaretOffset(int32_t aOffset) + { + // It is the same character offset when the caret is visually at the very + // end of a line or the start of a new line (soft line break). Getting text + // at the line should provide the line with the visual caret, otherwise + // screen readers will announce the wrong line as the user presses up or + // down arrow and land at the end of a line. + if (aOffset > 0) { + nsRefPtr frameSelection = FrameSelection(); + if (frameSelection && + frameSelection->GetHint() == nsFrameSelection::HINTLEFT) { + return aOffset - 1; + } + } + return aOffset; + } + /** * Return an offset of the found word boundary. */ diff --git a/accessible/tests/mochitest/text/test_atcaretoffset.html b/accessible/tests/mochitest/text/test_atcaretoffset.html index b1dd2280283e..5a19235b6f7f 100644 --- a/accessible/tests/mochitest/text/test_atcaretoffset.html +++ b/accessible/tests/mochitest/text/test_atcaretoffset.html @@ -46,11 +46,11 @@ testTextAfterOffset(kCaretOffset, BOUNDARY_LINE_END, "", 15, 15, "textarea", kOk, kTodo, kTodo); - testTextAtOffset(kCaretOffset, BOUNDARY_LINE_START, "", 15, 15, - "textarea", kTodo, kTodo, kOk); + testTextAtOffset(kCaretOffset, BOUNDARY_LINE_START, "words", 10, 15, + [ "textarea" ]); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "words", 10, 15, - "textarea", kOk, kOk, kOk); + [ "textarea" ]); testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "words", 10, 15, "textarea", kOk, kOk, kOk); @@ -80,8 +80,8 @@ testTextAtOffset(kCaretOffset, BOUNDARY_LINE_START, "words", 10, 15, [ "textarea" ]); - testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10, - "textarea", kTodo, kTodo, kTodo); + testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "words", 10, 15, + [ "textarea" ]); testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "two ", 6, 10, "textarea", kTodo, kTodo, kOk); @@ -110,10 +110,10 @@ "textarea", kTodo, kTodo, kTodo); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_START, "two ", 6, 10, - "textarea", kOk, kOk, kOk); + [ "textarea" ]); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10, - "textarea", kOk, kOk, kOk); + [ "textarea" ]); testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "aword\n", 0, 6, "textarea", kTodo, kTodo, kOk); @@ -141,10 +141,10 @@ "textarea", kTodo, kTodo, kOk); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_START, "two ", 6, 10, - "textarea", kTodo, kTodo, kTodo); + [ "textarea" ]); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "\ntwo ", 5, 10, - "textarea", kTodo, kTodo, kTodo); + [ "textarea" ]); testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "aword\n", 0, 6, "textarea", kTodo, kTodo, kTodo); @@ -172,10 +172,10 @@ "textarea", kOk, kOk, kOk); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_START, "aword\n", 0, 6, - "textarea", kOk, kOk, kOk); + [ "textarea" ]); - testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "", 0, 0, - "textarea", kTodo, kOk, kTodo); + testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "aword", 0, 5, + [ "textarea" ]); testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "", 0, 0, "textarea", kOk, kOk, kOk); @@ -203,10 +203,10 @@ "textarea", kTodo, kTodo, kTodo); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_START, "aword\n", 0, 6, - "textarea", kOk, kOk, kOk); + [ "textarea" ]); testTextAtOffset(kCaretOffset, BOUNDARY_LINE_END, "aword", 0, 5, - "textarea", kOk, kOk, kOk); + [ "textarea" ]); testTextBeforeOffset(kCaretOffset, BOUNDARY_LINE_START, "", 0, 0, "textarea", kTodo, kOk, kTodo);