| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/accessibility/browser_accessibility.h" | 5 #include "content/browser/accessibility/browser_accessibility.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 return ElementBoundsToLocalBounds(bounds); | 221 return ElementBoundsToLocalBounds(bounds); |
| 222 } | 222 } |
| 223 | 223 |
| 224 int end = start + len; | 224 int end = start + len; |
| 225 int child_start = 0; | 225 int child_start = 0; |
| 226 int child_end = 0; | 226 int child_end = 0; |
| 227 | 227 |
| 228 gfx::Rect bounds; | 228 gfx::Rect bounds; |
| 229 for (size_t i = 0; i < InternalChildCount() && child_end < start + len; ++i) { | 229 for (size_t i = 0; i < InternalChildCount() && child_end < start + len; ++i) { |
| 230 BrowserAccessibility* child = InternalGetChild(i); | 230 BrowserAccessibility* child = InternalGetChild(i); |
| 231 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); | 231 if (child->GetRole() != ui::AX_ROLE_INLINE_TEXT_BOX) { |
| 232 DLOG(WARNING) << "BrowserAccessibility objects with role STATIC_TEXT " << |
| 233 "should have children of role INLINE_TEXT_BOX."; |
| 234 continue; |
| 235 } |
| 236 |
| 232 std::string child_text; | 237 std::string child_text; |
| 233 child->GetStringAttribute(ui::AX_ATTR_VALUE, &child_text); | 238 child->GetStringAttribute(ui::AX_ATTR_VALUE, &child_text); |
| 234 int child_len = static_cast<int>(child_text.size()); | 239 int child_len = static_cast<int>(child_text.size()); |
| 235 child_start = child_end; | 240 child_start = child_end; |
| 236 child_end += child_len; | 241 child_end += child_len; |
| 237 | 242 |
| 238 if (child_end < start) | 243 if (child_end < start) |
| 239 continue; | 244 continue; |
| 240 | 245 |
| 241 int overlap_start = std::max(start, child_start); | 246 int overlap_start = std::max(start, child_start); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 | 309 |
| 305 // Adjust the bounds by the top left corner of the containing view's bounds | 310 // Adjust the bounds by the top left corner of the containing view's bounds |
| 306 // in screen coordinates. | 311 // in screen coordinates. |
| 307 bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin()); | 312 bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin()); |
| 308 | 313 |
| 309 return bounds; | 314 return bounds; |
| 310 } | 315 } |
| 311 | 316 |
| 312 int BrowserAccessibility::GetWordStartBoundary( | 317 int BrowserAccessibility::GetWordStartBoundary( |
| 313 int start, ui::TextBoundaryDirection direction) const { | 318 int start, ui::TextBoundaryDirection direction) const { |
| 314 int word_start = 0; | 319 DCHECK_GE(start, -1); |
| 315 int prev_word_start = 0; | 320 // Special offset that indicates that a word boundary has not been found. |
| 316 if (GetRole() != ui::AX_ROLE_STATIC_TEXT) { | 321 int word_start_not_found = GetStaticTextLenRecursive(); |
| 317 for (size_t i = 0; i < InternalChildCount(); ++i) { | 322 int word_start = word_start_not_found; |
| 318 BrowserAccessibility* child = InternalGetChild(i); | 323 |
| 319 int child_len = child->GetStaticTextLenRecursive(); | 324 switch (GetRole()) { |
| 320 int child_word_start = child->GetWordStartBoundary(start, direction); | 325 case ui::AX_ROLE_STATIC_TEXT: { |
| 321 word_start += child_word_start; | 326 int prev_word_start = word_start_not_found; |
| 322 if (child_word_start != child_len) | 327 int child_start = 0; |
| 328 int child_end = 0; |
| 329 |
| 330 // Go through the inline text boxes. |
| 331 for (size_t i = 0; i < InternalChildCount(); ++i) { |
| 332 // The next child starts where the previous one ended. |
| 333 child_start = child_end; |
| 334 BrowserAccessibility* child = InternalGetChild(i); |
| 335 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); |
| 336 const std::string& child_text = child->GetStringAttribute( |
| 337 ui::AX_ATTR_VALUE); |
| 338 int child_len = static_cast<int>(child_text.size()); |
| 339 child_end += child_len; // End is one past the last character. |
| 340 |
| 341 const std::vector<int32>& word_starts = child->GetIntListAttribute( |
| 342 ui::AX_ATTR_WORD_STARTS); |
| 343 if (word_starts.empty()) { |
| 344 word_start = child_end; |
| 345 continue; |
| 346 } |
| 347 |
| 348 int local_start = start - child_start; |
| 349 std::vector<int32>::const_iterator iter = std::upper_bound( |
| 350 word_starts.begin(), word_starts.end(), local_start); |
| 351 if (iter != word_starts.end()) { |
| 352 if (direction == ui::FORWARDS_DIRECTION) { |
| 353 word_start = child_start + *iter; |
| 354 } else if (direction == ui::BACKWARDS_DIRECTION) { |
| 355 if (iter == word_starts.begin()) { |
| 356 // Return the position of the last word in the previous child. |
| 357 word_start = prev_word_start; |
| 358 } else { |
| 359 word_start = child_start + *(iter - 1); |
| 360 } |
| 361 } else { |
| 362 NOTREACHED(); |
| 363 } |
| 323 break; | 364 break; |
| 324 start -= child_len; | 365 } |
| 325 } | |
| 326 return word_start; | |
| 327 } | |
| 328 | 366 |
| 329 int child_start = 0; | 367 // No word start that is greater than the requested offset has been |
| 330 int child_end = 0; | 368 // found. |
| 331 for (size_t i = 0; i < InternalChildCount(); ++i) { | 369 prev_word_start = child_start + *(iter - 1); |
| 332 // The next child starts where the previous one ended. | 370 if (direction == ui::FORWARDS_DIRECTION) { |
| 333 child_start = child_end; | 371 word_start = child_end; |
| 334 BrowserAccessibility* child = InternalGetChild(i); | 372 } else if (direction == ui::BACKWARDS_DIRECTION) { |
| 335 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); | 373 word_start = prev_word_start; |
| 336 const std::string& child_text = child->GetStringAttribute( | 374 } else { |
| 337 ui::AX_ATTR_VALUE); | 375 NOTREACHED(); |
| 338 int child_len = static_cast<int>(child_text.size()); | 376 } |
| 339 child_end += child_len; // End is one past the last character. | 377 } |
| 340 | 378 return word_start; |
| 341 const std::vector<int32>& word_starts = child->GetIntListAttribute( | |
| 342 ui::AX_ATTR_WORD_STARTS); | |
| 343 if (word_starts.empty()) { | |
| 344 word_start = child_end; | |
| 345 continue; | |
| 346 } | 379 } |
| 347 | 380 |
| 348 int local_start = start - child_start; | 381 case ui::AX_ROLE_LINE_BREAK: |
| 349 std::vector<int32>::const_iterator iter = std::upper_bound( | 382 // Words never start at a line break. |
| 350 word_starts.begin(), word_starts.end(), local_start); | 383 return word_start_not_found; |
| 351 if (iter != word_starts.end()) { | 384 |
| 352 if (direction == ui::FORWARDS_DIRECTION) { | 385 default: |
| 353 word_start = child_start + *iter; | 386 // If there are no children, the word start boundary is still unknown or |
| 354 } else if (direction == ui::BACKWARDS_DIRECTION) { | 387 // found previously depending on the direction. |
| 355 if (iter == word_starts.begin()) { | 388 if (!InternalChildCount()) |
| 356 // Return the position of the last word in the previous child. | 389 return word_start_not_found; |
| 357 word_start = prev_word_start; | 390 |
| 358 } else { | 391 int child_start = 0; |
| 359 word_start = child_start + *(iter - 1); | 392 for (size_t i = 0; i < InternalChildCount(); ++i) { |
| 393 BrowserAccessibility* child = InternalGetChild(i); |
| 394 int child_len = child->GetStaticTextLenRecursive(); |
| 395 int child_word_start = child->GetWordStartBoundary(start, direction); |
| 396 if (child_word_start < child_len) { |
| 397 // We have found a possible word boundary. |
| 398 word_start = child_start + child_word_start; |
| 360 } | 399 } |
| 361 } else { | 400 |
| 362 NOTREACHED(); | 401 // Decide when to stop searching. |
| 402 if ((word_start != word_start_not_found && |
| 403 direction == ui::FORWARDS_DIRECTION) || |
| 404 (start < child_len && |
| 405 direction == ui::BACKWARDS_DIRECTION)) { |
| 406 break; |
| 407 } |
| 408 |
| 409 child_start += child_len; |
| 410 if (start >= child_len) |
| 411 start -= child_len; |
| 412 else |
| 413 start = -1; |
| 363 } | 414 } |
| 364 break; | 415 return word_start; |
| 365 } | |
| 366 | |
| 367 // No word start that is >= to the requested offset has been found. | |
| 368 prev_word_start = child_start + *(iter - 1); | |
| 369 if (direction == ui::FORWARDS_DIRECTION) { | |
| 370 word_start = child_end; | |
| 371 } else if (direction == ui::BACKWARDS_DIRECTION) { | |
| 372 word_start = prev_word_start; | |
| 373 } else { | |
| 374 NOTREACHED(); | |
| 375 } | |
| 376 } | 416 } |
| 377 | |
| 378 return word_start; | |
| 379 } | 417 } |
| 380 | 418 |
| 381 BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint( | 419 BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint( |
| 382 const gfx::Point& point) { | 420 const gfx::Point& point) { |
| 383 // The best result found that's a child of this object. | 421 // The best result found that's a child of this object. |
| 384 BrowserAccessibility* child_result = NULL; | 422 BrowserAccessibility* child_result = NULL; |
| 385 // The best result that's an indirect descendant like grandchild, etc. | 423 // The best result that's an indirect descendant like grandchild, etc. |
| 386 BrowserAccessibility* descendant_result = NULL; | 424 BrowserAccessibility* descendant_result = NULL; |
| 387 | 425 |
| 388 // Walk the children recursively looking for the BrowserAccessibility that | 426 // Walk the children recursively looking for the BrowserAccessibility that |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 return false; | 753 return false; |
| 716 | 754 |
| 717 BrowserAccessibility* grandparent = parent->GetParent(); | 755 BrowserAccessibility* grandparent = parent->GetParent(); |
| 718 if (!grandparent) | 756 if (!grandparent) |
| 719 return false; | 757 return false; |
| 720 | 758 |
| 721 return grandparent->GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL; | 759 return grandparent->GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL; |
| 722 } | 760 } |
| 723 | 761 |
| 724 int BrowserAccessibility::GetStaticTextLenRecursive() const { | 762 int BrowserAccessibility::GetStaticTextLenRecursive() const { |
| 725 if (GetRole() == ui::AX_ROLE_STATIC_TEXT) | 763 if (GetRole() == ui::AX_ROLE_STATIC_TEXT || |
| 764 GetRole() == ui::AX_ROLE_LINE_BREAK) { |
| 726 return static_cast<int>(GetStringAttribute(ui::AX_ATTR_VALUE).size()); | 765 return static_cast<int>(GetStringAttribute(ui::AX_ATTR_VALUE).size()); |
| 766 } |
| 727 | 767 |
| 728 int len = 0; | 768 int len = 0; |
| 729 for (size_t i = 0; i < InternalChildCount(); ++i) | 769 for (size_t i = 0; i < InternalChildCount(); ++i) |
| 730 len += InternalGetChild(i)->GetStaticTextLenRecursive(); | 770 len += InternalGetChild(i)->GetStaticTextLenRecursive(); |
| 731 return len; | 771 return len; |
| 732 } | 772 } |
| 733 | 773 |
| 734 BrowserAccessibility* BrowserAccessibility::GetParentForBoundsCalculation() | 774 BrowserAccessibility* BrowserAccessibility::GetParentForBoundsCalculation() |
| 735 const { | 775 const { |
| 736 if (!node_ || !manager_) | 776 if (!node_ || !manager_) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 } | 819 } |
| 780 need_to_offset_web_area = true; | 820 need_to_offset_web_area = true; |
| 781 } | 821 } |
| 782 parent = parent->GetParentForBoundsCalculation(); | 822 parent = parent->GetParentForBoundsCalculation(); |
| 783 } | 823 } |
| 784 | 824 |
| 785 return bounds; | 825 return bounds; |
| 786 } | 826 } |
| 787 | 827 |
| 788 } // namespace content | 828 } // namespace content |
| OLD | NEW |