Chromium Code Reviews| Index: content/browser/accessibility/browser_accessibility.cc |
| diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc |
| index fa606fc2bfe5ddc3b135f8af0defea691c9003f3..97fd27f19f9fb21bf6ae5e5629cb9266789c100f 100644 |
| --- a/content/browser/accessibility/browser_accessibility.cc |
| +++ b/content/browser/accessibility/browser_accessibility.cc |
| @@ -186,6 +186,41 @@ BrowserAccessibility* BrowserAccessibility::GetNextSibling() const { |
| return nullptr; |
| } |
| +bool BrowserAccessibility::IsPreviousSiblingOnSameLine() const { |
| + const BrowserAccessibility* previous_sibling = GetPreviousSibling(); |
| + if (!previous_sibling) |
| + return false; |
| + |
| + int32_t previous_on_line_id; |
| + if (GetIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID, &previous_on_line_id)) { |
| + const BrowserAccessibility* previous_on_line = |
| + manager()->GetFromID(previous_on_line_id); |
| + // In the case of static text objects, the object designated to be the |
| + // previous object on this line might be a child of the previous sibling, |
| + // i.e. the last inline text box of the previous static text object. |
| + return previous_on_line && |
| + previous_on_line->IsDescendantOf(previous_sibling); |
| + } |
| + return false; |
| +} |
| + |
| +bool BrowserAccessibility::IsNextSiblingOnSameLine() const { |
| + const BrowserAccessibility* next_sibling = GetNextSibling(); |
| + if (!next_sibling) |
| + return false; |
| + |
| + int32_t next_on_line_id; |
| + if (GetIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID, &next_on_line_id)) { |
| + const BrowserAccessibility* next_on_line = |
| + manager()->GetFromID(next_on_line_id); |
| + // In the case of static text objects, the object designated to be the next |
| + // object on this line might be a child of the next sibling, i.e. the first |
| + // inline text box of the next static text object. |
| + return next_on_line && next_on_line->IsDescendantOf(next_sibling); |
| + } |
| + return false; |
| +} |
| + |
| BrowserAccessibility* BrowserAccessibility::PlatformDeepestFirstChild() const { |
| if (!PlatformChildCount()) |
| return nullptr; |
| @@ -468,6 +503,57 @@ base::string16 BrowserAccessibility::GetValue() const { |
| return value; |
| } |
| +int BrowserAccessibility::GetLineStartBoundary( |
| + int start, |
| + ui::TextBoundaryDirection direction) const { |
| + DCHECK_GE(start, 0); |
| + DCHECK_LE(start, static_cast<int>(GetText().length())); |
| + |
| + if (IsSimpleTextControl()) { |
| + const std::vector<int32_t>& line_breaks = |
| + GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS); |
| + return ui::FindAccessibleTextBoundary(GetText(), line_breaks, |
| + ui::LINE_BOUNDARY, start, direction); |
| + } |
| + |
| + // Keeps track of the start offset of each consecutive line. |
| + int line_start = 0; |
| + // Keeps track of the length of each consecutive line. |
| + int line_length = 0; |
| + for (size_t i = 0; i < InternalChildCount(); ++i) { |
| + const BrowserAccessibility* child = InternalGetChild(i); |
| + DCHECK(child); |
| + // Child objects are of length one, since they are represented by a |
| + // single embedded object character. The exception is text-only objects. |
| + int child_length = 1; |
| + if (child->IsTextOnlyObject()) |
| + child_length = static_cast<int>(child->GetText().length()); |
| + line_length += child_length; |
| + start -= child_length; |
| + |
| + // Stop when we reach both the object containing our start offset and the |
| + // end of the line on which this object is located. |
| + if (start < 0 && !IsNextSiblingOnSameLine()) |
| + break; |
| + |
| + if (!IsNextSiblingOnSameLine()) { |
| + line_start += line_length; |
| + line_length = 0; |
| + } |
| + } |
| + |
| + switch (direction) { |
| + case ui::FORWARDS_DIRECTION: |
| + return line_start + line_length; |
| + case ui::BACKWARDS_DIRECTION: |
| + return line_start; |
| + default: |
| + NOTREACHED(); |
| + } |
| + return static_cast<int>(GetText().length()); |
| + ; |
|
dmazzoni
2016/04/22 15:34:49
nit: extra semicolon?
|
| +} |
| + |
| int BrowserAccessibility::GetWordStartBoundary( |
| int start, ui::TextBoundaryDirection direction) const { |
| DCHECK_GE(start, -1); |
| @@ -485,7 +571,7 @@ int BrowserAccessibility::GetWordStartBoundary( |
| for (size_t i = 0; i < InternalChildCount(); ++i) { |
| // The next child starts where the previous one ended. |
| child_start = child_end; |
| - BrowserAccessibility* child = InternalGetChild(i); |
| + const BrowserAccessibility* child = InternalGetChild(i); |
| DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); |
| int child_len = static_cast<int>(child->GetText().size()); |
| child_end += child_len; // End is one past the last character. |
| @@ -553,7 +639,7 @@ int BrowserAccessibility::GetWordStartBoundary( |
| // single embedded object character. The exception is text-only objects. |
| int child_len = 1; |
| if (child->IsTextOnlyObject()) { |
| - child_len = static_cast<int>(child->GetText().size()); |
| + child_len = static_cast<int>(child->GetText().length()); |
| int child_word_start = child->GetWordStartBoundary(start, direction); |
| if (child_word_start < child_len) { |
| // We have found a possible word boundary. |