| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 if (GetParent() && | 179 if (GetParent() && |
| 180 GetIndexInParent() >= 0 && | 180 GetIndexInParent() >= 0 && |
| 181 GetIndexInParent() < static_cast<int>( | 181 GetIndexInParent() < static_cast<int>( |
| 182 GetParent()->InternalChildCount() - 1)) { | 182 GetParent()->InternalChildCount() - 1)) { |
| 183 return GetParent()->InternalGetChild(GetIndexInParent() + 1); | 183 return GetParent()->InternalGetChild(GetIndexInParent() + 1); |
| 184 } | 184 } |
| 185 | 185 |
| 186 return nullptr; | 186 return nullptr; |
| 187 } | 187 } |
| 188 | 188 |
| 189 bool BrowserAccessibility::IsPreviousSiblingOnSameLine() const { |
| 190 const BrowserAccessibility* previous_sibling = GetPreviousSibling(); |
| 191 if (!previous_sibling) |
| 192 return false; |
| 193 |
| 194 const BrowserAccessibility* text_object = this; |
| 195 while (!text_object->IsTextOnlyObject()) { |
| 196 // If we don't find a text object, then sibling cannot be on the same line. |
| 197 if (!text_object->InternalChildCount()) |
| 198 return false; |
| 199 text_object = text_object->InternalGetChild(0); |
| 200 } |
| 201 |
| 202 int32_t previous_on_line_id; |
| 203 if (text_object->GetIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID, |
| 204 &previous_on_line_id)) { |
| 205 const BrowserAccessibility* previous_on_line = |
| 206 manager()->GetFromID(previous_on_line_id); |
| 207 // In the case of static text objects, the object designated to be the |
| 208 // previous object on this line might be a child of the previous sibling, |
| 209 // i.e. the last inline text box of the previous static text object. |
| 210 return previous_on_line && |
| 211 previous_on_line->IsDescendantOf(previous_sibling); |
| 212 } |
| 213 return false; |
| 214 } |
| 215 |
| 216 bool BrowserAccessibility::IsNextSiblingOnSameLine() const { |
| 217 const BrowserAccessibility* next_sibling = GetNextSibling(); |
| 218 if (!next_sibling) |
| 219 return false; |
| 220 |
| 221 const BrowserAccessibility* text_object = this; |
| 222 while (!text_object->IsTextOnlyObject()) { |
| 223 // If we don't find a text object, then sibling cannot be on the same line. |
| 224 if (!text_object->InternalChildCount()) |
| 225 return false; |
| 226 text_object = text_object->InternalGetChild(0); |
| 227 } |
| 228 |
| 229 int32_t next_on_line_id; |
| 230 if (text_object->GetIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID, |
| 231 &next_on_line_id)) { |
| 232 const BrowserAccessibility* next_on_line = |
| 233 manager()->GetFromID(next_on_line_id); |
| 234 // In the case of static text objects, the object designated to be the next |
| 235 // object on this line might be a child of the next sibling, i.e. the first |
| 236 // inline text box of the next static text object. |
| 237 return next_on_line && next_on_line->IsDescendantOf(next_sibling); |
| 238 } |
| 239 return false; |
| 240 } |
| 241 |
| 189 BrowserAccessibility* BrowserAccessibility::PlatformDeepestFirstChild() const { | 242 BrowserAccessibility* BrowserAccessibility::PlatformDeepestFirstChild() const { |
| 190 if (!PlatformChildCount()) | 243 if (!PlatformChildCount()) |
| 191 return nullptr; | 244 return nullptr; |
| 192 | 245 |
| 193 BrowserAccessibility* deepest_child = PlatformGetChild(0); | 246 BrowserAccessibility* deepest_child = PlatformGetChild(0); |
| 194 while (deepest_child->PlatformChildCount()) | 247 while (deepest_child->PlatformChildCount()) |
| 195 deepest_child = deepest_child->PlatformGetChild(0); | 248 deepest_child = deepest_child->PlatformGetChild(0); |
| 196 | 249 |
| 197 return deepest_child; | 250 return deepest_child; |
| 198 } | 251 } |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 base::string16 BrowserAccessibility::GetValue() const { | 514 base::string16 BrowserAccessibility::GetValue() const { |
| 462 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); | 515 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); |
| 463 // Some screen readers like Jaws and older versions of VoiceOver require a | 516 // Some screen readers like Jaws and older versions of VoiceOver require a |
| 464 // value to be set in text fields with rich content, even though the same | 517 // value to be set in text fields with rich content, even though the same |
| 465 // information is available on the children. | 518 // information is available on the children. |
| 466 if (value.empty() && (IsSimpleTextControl() || IsRichTextControl())) | 519 if (value.empty() && (IsSimpleTextControl() || IsRichTextControl())) |
| 467 value = GetInnerText(); | 520 value = GetInnerText(); |
| 468 return value; | 521 return value; |
| 469 } | 522 } |
| 470 | 523 |
| 524 int BrowserAccessibility::GetLineStartBoundary( |
| 525 int start, |
| 526 ui::TextBoundaryDirection direction) const { |
| 527 DCHECK_GE(start, 0); |
| 528 DCHECK_LE(start, static_cast<int>(GetText().length())); |
| 529 |
| 530 if (IsSimpleTextControl()) { |
| 531 const std::vector<int32_t>& line_breaks = |
| 532 GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS); |
| 533 return ui::FindAccessibleTextBoundary(GetText(), line_breaks, |
| 534 ui::LINE_BOUNDARY, start, direction); |
| 535 } |
| 536 |
| 537 // Keeps track of the start offset of each consecutive line. |
| 538 int line_start = 0; |
| 539 // Keeps track of the length of each consecutive line. |
| 540 int line_length = 0; |
| 541 for (size_t i = 0; i < InternalChildCount(); ++i) { |
| 542 const BrowserAccessibility* child = InternalGetChild(i); |
| 543 DCHECK(child); |
| 544 // Child objects are of length one, since they are represented by a |
| 545 // single embedded object character. The exception is text-only objects. |
| 546 int child_length = 1; |
| 547 if (child->IsTextOnlyObject()) |
| 548 child_length = static_cast<int>(child->GetText().length()); |
| 549 line_length += child_length; |
| 550 start -= child_length; |
| 551 |
| 552 // Stop when we reach both the object containing our start offset and the |
| 553 // end of the line on which this object is located. |
| 554 if (start < 0 && !child->IsNextSiblingOnSameLine()) |
| 555 break; |
| 556 |
| 557 if (!child->IsNextSiblingOnSameLine()) { |
| 558 line_start += line_length; |
| 559 line_length = 0; |
| 560 } |
| 561 } |
| 562 |
| 563 int result = 0; |
| 564 switch (direction) { |
| 565 case ui::FORWARDS_DIRECTION: |
| 566 result = line_start + line_length; |
| 567 break; |
| 568 case ui::BACKWARDS_DIRECTION: |
| 569 result = line_start; |
| 570 break; |
| 571 default: |
| 572 NOTREACHED(); |
| 573 } |
| 574 return result; |
| 575 } |
| 576 |
| 471 int BrowserAccessibility::GetWordStartBoundary( | 577 int BrowserAccessibility::GetWordStartBoundary( |
| 472 int start, ui::TextBoundaryDirection direction) const { | 578 int start, ui::TextBoundaryDirection direction) const { |
| 473 DCHECK_GE(start, -1); | 579 DCHECK_GE(start, -1); |
| 474 // Special offset that indicates that a word boundary has not been found. | 580 // Special offset that indicates that a word boundary has not been found. |
| 475 int word_start_not_found = static_cast<int>(GetText().size()); | 581 int word_start_not_found = static_cast<int>(GetText().size()); |
| 476 int word_start = word_start_not_found; | 582 int word_start = word_start_not_found; |
| 477 | 583 |
| 478 switch (GetRole()) { | 584 switch (GetRole()) { |
| 479 case ui::AX_ROLE_STATIC_TEXT: { | 585 case ui::AX_ROLE_STATIC_TEXT: { |
| 480 int prev_word_start = word_start_not_found; | 586 int prev_word_start = word_start_not_found; |
| 481 int child_start = 0; | 587 int child_start = 0; |
| 482 int child_end = 0; | 588 int child_end = 0; |
| 483 | 589 |
| 484 // Go through the inline text boxes. | 590 // Go through the inline text boxes. |
| 485 for (size_t i = 0; i < InternalChildCount(); ++i) { | 591 for (size_t i = 0; i < InternalChildCount(); ++i) { |
| 486 // The next child starts where the previous one ended. | 592 // The next child starts where the previous one ended. |
| 487 child_start = child_end; | 593 child_start = child_end; |
| 488 BrowserAccessibility* child = InternalGetChild(i); | 594 const BrowserAccessibility* child = InternalGetChild(i); |
| 489 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); | 595 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); |
| 490 int child_len = static_cast<int>(child->GetText().size()); | 596 int child_len = static_cast<int>(child->GetText().size()); |
| 491 child_end += child_len; // End is one past the last character. | 597 child_end += child_len; // End is one past the last character. |
| 492 | 598 |
| 493 const std::vector<int32_t>& word_starts = | 599 const std::vector<int32_t>& word_starts = |
| 494 child->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS); | 600 child->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS); |
| 495 if (word_starts.empty()) { | 601 if (word_starts.empty()) { |
| 496 word_start = child_end; | 602 word_start = child_end; |
| 497 continue; | 603 continue; |
| 498 } | 604 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 if (IsSimpleTextControl() && InternalChildCount() == 1) { | 652 if (IsSimpleTextControl() && InternalChildCount() == 1) { |
| 547 this_object = InternalGetChild(0); | 653 this_object = InternalGetChild(0); |
| 548 } | 654 } |
| 549 int child_start = 0; | 655 int child_start = 0; |
| 550 for (size_t i = 0; i < this_object->InternalChildCount(); ++i) { | 656 for (size_t i = 0; i < this_object->InternalChildCount(); ++i) { |
| 551 BrowserAccessibility* child = this_object->InternalGetChild(i); | 657 BrowserAccessibility* child = this_object->InternalGetChild(i); |
| 552 // Child objects are of length one, since they are represented by a | 658 // Child objects are of length one, since they are represented by a |
| 553 // single embedded object character. The exception is text-only objects. | 659 // single embedded object character. The exception is text-only objects. |
| 554 int child_len = 1; | 660 int child_len = 1; |
| 555 if (child->IsTextOnlyObject()) { | 661 if (child->IsTextOnlyObject()) { |
| 556 child_len = static_cast<int>(child->GetText().size()); | 662 child_len = static_cast<int>(child->GetText().length()); |
| 557 int child_word_start = child->GetWordStartBoundary(start, direction); | 663 int child_word_start = child->GetWordStartBoundary(start, direction); |
| 558 if (child_word_start < child_len) { | 664 if (child_word_start < child_len) { |
| 559 // We have found a possible word boundary. | 665 // We have found a possible word boundary. |
| 560 word_start = child_start + child_word_start; | 666 word_start = child_start + child_word_start; |
| 561 } | 667 } |
| 562 | 668 |
| 563 // Decide when to stop searching. | 669 // Decide when to stop searching. |
| 564 if ((word_start != word_start_not_found && | 670 if ((word_start != word_start_not_found && |
| 565 direction == ui::FORWARDS_DIRECTION) || | 671 direction == ui::FORWARDS_DIRECTION) || |
| 566 (start < child_len && direction == ui::BACKWARDS_DIRECTION)) { | 672 (start < child_len && direction == ui::BACKWARDS_DIRECTION)) { |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 break; | 1171 break; |
| 1066 | 1172 |
| 1067 manager = root->GetParent()->manager(); | 1173 manager = root->GetParent()->manager(); |
| 1068 root = manager->GetRoot(); | 1174 root = manager->GetRoot(); |
| 1069 } | 1175 } |
| 1070 | 1176 |
| 1071 return bounds; | 1177 return bounds; |
| 1072 } | 1178 } |
| 1073 | 1179 |
| 1074 } // namespace content | 1180 } // namespace content |
| OLD | NEW |