| Index: content/browser/accessibility/browser_accessibility.cc
|
| diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
|
| index 0fdad54c91c4ef45eac37bfd034aba1e3c644049..b2bc17932177a600680c29d07911e524e8b30794 100644
|
| --- a/content/browser/accessibility/browser_accessibility.cc
|
| +++ b/content/browser/accessibility/browser_accessibility.cc
|
| @@ -262,28 +262,28 @@ gfx::Rect BrowserAccessibility::GetLocalBoundsForRange(int start, int len)
|
| gfx::Rect child_overlap_rect;
|
| switch (text_direction) {
|
| case ui::AX_TEXT_DIRECTION_NONE:
|
| - case ui::AX_TEXT_DIRECTION_LR: {
|
| + case ui::AX_TEXT_DIRECTION_LTR: {
|
| int left = child_rect.x() + start_pixel_offset;
|
| int right = child_rect.x() + end_pixel_offset;
|
| child_overlap_rect = gfx::Rect(left, child_rect.y(),
|
| right - left, child_rect.height());
|
| break;
|
| }
|
| - case ui::AX_TEXT_DIRECTION_RL: {
|
| + case ui::AX_TEXT_DIRECTION_RTL: {
|
| int right = child_rect.right() - start_pixel_offset;
|
| int left = child_rect.right() - end_pixel_offset;
|
| child_overlap_rect = gfx::Rect(left, child_rect.y(),
|
| right - left, child_rect.height());
|
| break;
|
| }
|
| - case ui::AX_TEXT_DIRECTION_TB: {
|
| + case ui::AX_TEXT_DIRECTION_TTB: {
|
| int top = child_rect.y() + start_pixel_offset;
|
| int bottom = child_rect.y() + end_pixel_offset;
|
| child_overlap_rect = gfx::Rect(child_rect.x(), top,
|
| child_rect.width(), bottom - top);
|
| break;
|
| }
|
| - case ui::AX_TEXT_DIRECTION_BT: {
|
| + case ui::AX_TEXT_DIRECTION_BTT: {
|
| int bottom = child_rect.bottom() - start_pixel_offset;
|
| int top = child_rect.bottom() - end_pixel_offset;
|
| child_overlap_rect = gfx::Rect(child_rect.x(), top,
|
| @@ -315,10 +315,13 @@ gfx::Rect BrowserAccessibility::GetGlobalBoundsForRange(int start, int len)
|
| }
|
|
|
| int BrowserAccessibility::GetWordStartBoundary(
|
| - int start, ui::TextBoundaryDirection direction) const {
|
| - DCHECK_GE(start, -1);
|
| + int offset, ui::TextBoundaryDirection direction) const {
|
| + DCHECK_GE(offset, -1);
|
| + int text_len = GetStaticTextLenRecursive();
|
| + DCHECK_LE(offset, text_len);
|
| +
|
| // Special offset that indicates that a word boundary has not been found.
|
| - int word_start_not_found = GetStaticTextLenRecursive();
|
| + int word_start_not_found = text_len;
|
| int word_start = word_start_not_found;
|
|
|
| switch (GetRole()) {
|
| @@ -332,11 +335,13 @@ int BrowserAccessibility::GetWordStartBoundary(
|
| // The next child starts where the previous one ended.
|
| child_start = child_end;
|
| BrowserAccessibility* child = InternalGetChild(i);
|
| - DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX);
|
| - const std::string& child_text = child->GetStringAttribute(
|
| - ui::AX_ATTR_VALUE);
|
| - int child_len = static_cast<int>(child_text.size());
|
| - child_end += child_len; // End is one past the last character.
|
| + if (child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX) {
|
| + LOG(WARNING) << "Found child of AX_ROLE_STATIC_TEXT that is not " <<
|
| + "AX_ROLE_INLINE_TEXT_BOX. ID=" child->GetId());
|
| + continue;
|
| + }
|
| + int child_len = GetStaticTextLenRecursive();
|
| + child_end += child_len;
|
|
|
| const std::vector<int32>& word_starts = child->GetIntListAttribute(
|
| ui::AX_ATTR_WORD_STARTS);
|
| @@ -345,9 +350,9 @@ int BrowserAccessibility::GetWordStartBoundary(
|
| continue;
|
| }
|
|
|
| - int local_start = start - child_start;
|
| + int local_offset = offset - child_start;
|
| std::vector<int32>::const_iterator iter = std::upper_bound(
|
| - word_starts.begin(), word_starts.end(), local_start);
|
| + word_starts.begin(), word_starts.end(), local_offset);
|
| if (iter != word_starts.end()) {
|
| if (direction == ui::FORWARDS_DIRECTION) {
|
| word_start = child_start + *iter;
|
| @@ -401,21 +406,56 @@ int BrowserAccessibility::GetWordStartBoundary(
|
| // Decide when to stop searching.
|
| if ((word_start != word_start_not_found &&
|
| direction == ui::FORWARDS_DIRECTION) ||
|
| - (start < child_len &&
|
| + (offset < child_len &&
|
| direction == ui::BACKWARDS_DIRECTION)) {
|
| break;
|
| }
|
|
|
| child_start += child_len;
|
| - if (start >= child_len)
|
| - start -= child_len;
|
| + if (offset >= child_len)
|
| + offset -= child_len;
|
| else
|
| - start = -1;
|
| + offset = -1;
|
| }
|
| return word_start;
|
| }
|
| }
|
|
|
| +int BrowserAccessibility::GetStyleChangeBoundary(
|
| + int offset, ui::TextBoundaryDirection direction) const {
|
| + DCHECK_GE(offset, 0);
|
| + int text_len = GetStaticTextLenRecursive();
|
| + DCHECK_LE(offset, text_len);
|
| +
|
| + int style_change_start;
|
| + if (direction == ui::BACKWARDS_DIRECTION)
|
| + style_change_start = 0;
|
| + else if (direction == ui::FORWARDS_DIRECTION)
|
| + style_change_start = text_len;
|
| + else
|
| + NOTREACHED();
|
| +
|
| + if (IsTextLeaf())
|
| + return style_change_start;
|
| +
|
| + BrowserAccessibility* leaf = GetTextLeafAtOffset(offset, &style_change_start);
|
| + DCHECK(leaf);
|
| +
|
| + BrowserAccessibility* sibling = leaf;
|
| + if (direction == ui::BACKWARDS_DIRECTION)
|
| + while ((sibling = GetPreviousTextLeaf()) && HaveSameStyle(*leaf, *sibling)) {
|
| + style_change_start -= sibling->GetStaticTextLenRecursive();
|
| + leaf = sibling;
|
| + }
|
| + else if (direction == ui::FORWARDS_DIRECTION)
|
| + while (sibling = GetNextTextLeaf() && HaveSameStyle(*leaf, *sibling)) {
|
| + style_change_start += leaf->GetStaticTextLenRecursive();
|
| + leaf = sibling;
|
| + }
|
| +
|
| + return style_change_start;
|
| +}
|
| +
|
| BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
|
| const gfx::Point& point) {
|
| // The best result found that's a child of this object.
|
| @@ -759,11 +799,51 @@ bool BrowserAccessibility::IsWebAreaForPresentationalIframe() const {
|
| return grandparent->GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL;
|
| }
|
|
|
| +//
|
| +// Protected methods.
|
| +//
|
| +
|
| +BrowserAccessibility* BrowserAccessibility::GetFirstTextLeaf() const {
|
| + int unused_leaf_offset;
|
| + return GetTextLeafAtOffset(0, &unused_leaf_offset);
|
| +}
|
| +
|
| +//
|
| +// Private methods.
|
| +//
|
| +
|
| +// Return true only for objects that are the deepest possible descendants which
|
| +// include complete text information.
|
| +// For example, objects with role AX_ROLE_EDIT_FIELD are not the deepest nodes
|
| +// with complete text information because they have objects with role
|
| +// AX_ROLE_STATIC_TEXT as their descendants which hold the text information.
|
| +// However, an object with role AX_ROLE_BUTTON has no AX_ROLE_STATIC_TEXT
|
| +// descendant and it stores its text information directly.
|
| +bool BrowserAccessibility::IsTextLeaf() const {
|
| + switch (GetRole()) {
|
| + case ui::AX_ROLE_BUTTON:
|
| + case ui::AX_ROLE_CHECK_BOX:
|
| + case ui::AX_ROLE_COLOR_WELL:
|
| + case ui::AX_ROLE_COMBO_BOX:
|
| + case ui::AX_ROLE_DATE:
|
| + case ui::AX_ROLE_DATE_TIME:
|
| + case ui::AX_ROLE_IMAGE:
|
| + case ui::AX_ROLE_LINE_BREAK:
|
| + case ui::AX_ROLE_LIST_MARKER:
|
| + case ui::AX_ROLE_POP_UP_BUTTON:
|
| + case ui::AX_ROLE_RADIO_BUTTON:
|
| + case ui::AX_ROLE_SEARCH_BOX:
|
| + case ui::AX_ROLE_TOGGLE_BUTTON:
|
| + case ui::AX_ROLE_STATIC_TEXT:
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +
|
| int BrowserAccessibility::GetStaticTextLenRecursive() const {
|
| - if (GetRole() == ui::AX_ROLE_STATIC_TEXT ||
|
| - GetRole() == ui::AX_ROLE_LINE_BREAK) {
|
| + if (IsTextLeaf())
|
| return static_cast<int>(GetStringAttribute(ui::AX_ATTR_VALUE).size());
|
| - }
|
|
|
| int len = 0;
|
| for (size_t i = 0; i < InternalChildCount(); ++i)
|
| @@ -771,6 +851,82 @@ int BrowserAccessibility::GetStaticTextLenRecursive() const {
|
| return len;
|
| }
|
|
|
| +// TODO(nektar): Refactor whole class to use this function where appropriate.
|
| +BrowserAccessibility* BrowserAccessibility::GetTextLeafAtOffset(
|
| + int offset,
|
| + int* leaf_start_offset) const {
|
| + DCHECK_GE(offset, 0);
|
| + DCHECK_LE(offset, GetStaticTextLenRecursive());
|
| + DCHECK(child_start_offset);
|
| +
|
| + if (IsTextLeaf()) {
|
| + *leaf_start_offset = 0;
|
| + return this;
|
| + }
|
| +
|
| + int child_start = 0;
|
| + BrowserAccessibility* leaf = nullptr;
|
| + for (size_t i = 0; i < InternalChildCount(); ++i) {
|
| + BrowserAccessibility* child = InternalGetChild(i);
|
| + int child_len = GetStaticTextLenRecursive();
|
| + int child_end = child_start + child_len;
|
| + if (offset < child_end) {
|
| + leaf = child->GetTextLeafAtOffset(offset, leaf_start_offset);
|
| + break;
|
| + }
|
| +
|
| + child_start = child_end;
|
| + offset -= child_len;
|
| + }
|
| +
|
| + *leaf_start_offset += child_start;
|
| + return leaf;
|
| +}
|
| +
|
| +BrowserAccessibility* BrowserAccessibility::GetLastTextLeaf() const {
|
| + int text_len = GetStaticTextLenRecursive();
|
| + if (text_len <= 0)
|
| + return GetFirstTextLeaf();
|
| +
|
| + int unused_leaf_offset;
|
| + return GetTextLeafAtOffset(text_len - 1, &unused_leaf_offset);
|
| +}
|
| +
|
| +BrowserAccessibility* BrowserAccessibility::GetNextTextLeaf() const {
|
| + if (GetFirstTextLeaf() && GetFirstTextLeaf() != this)
|
| + return GetNextFirstLeaf();
|
| +
|
| + BrowserAccessibility* next_leaf = nullptr;
|
| + BrowserAccessibility* current_object = GetNextSibling();
|
| + while (!next_leaf && current_object) {
|
| + next_leaf = current_object->GetFirstTextLeaf();
|
| + current_object = current_object->GetNextSibling();
|
| + }
|
| + if (next_leaf)
|
| + return next_leaf;
|
| +
|
| + if (GetParent() && GetParent()->GetNextSibling())
|
| + next_leaf = GetParent()->GetNextSibling()->GetNextTextLeaf();
|
| +
|
| + return next_leaf;
|
| +}
|
| +
|
| +BrowserAccessibility* BrowserAccessibility::GetPreviousTextLeaf() const {
|
| + BrowserAccessibility* previous_leaf = nullptr;
|
| + BrowserAccessibility* current_object = GetPreviousSibling();
|
| + while (!previous_leaf && current_object) {
|
| + previous_leaf = current_object->GetLastTextLeaf();
|
| + current_object = current_object->GetPreviousSibling();
|
| + }
|
| + if (previous_leaf)
|
| + return previous_leaf;
|
| +
|
| + if (GetParent() && GetParent()->GetPreviousSibling())
|
| + previous_leaf = GetParent()->GetPreviousSibling()->GetPreviousTextLeaf();
|
| +
|
| + return previous_leaf;
|
| +}
|
| +
|
| BrowserAccessibility* BrowserAccessibility::GetParentForBoundsCalculation()
|
| const {
|
| if (!node_ || !manager_)
|
| @@ -825,4 +981,13 @@ gfx::Rect BrowserAccessibility::ElementBoundsToLocalBounds(gfx::Rect bounds)
|
| return bounds;
|
| }
|
|
|
| +//
|
| +// Static methods.
|
| +//
|
| +
|
| +bool BrowserAccessibility::HaveSameStyle(BrowserAccessibility& object1,
|
| + BrowserAccessibility& object2) {
|
| +
|
| +}
|
| +
|
| } // namespace content
|
|
|