Chromium Code Reviews| 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 int32_t previous_on_line_id; | |
| 195 if (GetIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID, &previous_on_line_id)) { | |
| 196 const BrowserAccessibility* previous_on_line = | |
| 197 manager()->GetFromID(previous_on_line_id); | |
| 198 // In the case of static text objects, the object designated to be the | |
| 199 // previous object on this line might be a child of the previous sibling, | |
| 200 // i.e. the last inline text box of the previous static text object. | |
| 201 return previous_on_line && | |
| 202 previous_on_line->IsDescendantOf(previous_sibling); | |
| 203 } | |
| 204 return false; | |
| 205 } | |
| 206 | |
| 207 bool BrowserAccessibility::IsNextSiblingOnSameLine() const { | |
| 208 const BrowserAccessibility* next_sibling = GetNextSibling(); | |
| 209 if (!next_sibling) | |
| 210 return false; | |
| 211 | |
| 212 int32_t next_on_line_id; | |
| 213 if (GetIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID, &next_on_line_id)) { | |
| 214 const BrowserAccessibility* next_on_line = | |
| 215 manager()->GetFromID(next_on_line_id); | |
| 216 // In the case of static text objects, the object designated to be the next | |
| 217 // object on this line might be a child of the next sibling, i.e. the first | |
| 218 // inline text box of the next static text object. | |
| 219 return next_on_line && next_on_line->IsDescendantOf(next_sibling); | |
| 220 } | |
| 221 return false; | |
| 222 } | |
| 223 | |
| 189 BrowserAccessibility* BrowserAccessibility::PlatformDeepestFirstChild() const { | 224 BrowserAccessibility* BrowserAccessibility::PlatformDeepestFirstChild() const { |
| 190 if (!PlatformChildCount()) | 225 if (!PlatformChildCount()) |
| 191 return nullptr; | 226 return nullptr; |
| 192 | 227 |
| 193 BrowserAccessibility* deepest_child = PlatformGetChild(0); | 228 BrowserAccessibility* deepest_child = PlatformGetChild(0); |
| 194 while (deepest_child->PlatformChildCount()) | 229 while (deepest_child->PlatformChildCount()) |
| 195 deepest_child = deepest_child->PlatformGetChild(0); | 230 deepest_child = deepest_child->PlatformGetChild(0); |
| 196 | 231 |
| 197 return deepest_child; | 232 return deepest_child; |
| 198 } | 233 } |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 base::string16 BrowserAccessibility::GetValue() const { | 496 base::string16 BrowserAccessibility::GetValue() const { |
| 462 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); | 497 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); |
| 463 // Some screen readers like Jaws and older versions of VoiceOver require a | 498 // 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 | 499 // value to be set in text fields with rich content, even though the same |
| 465 // information is available on the children. | 500 // information is available on the children. |
| 466 if (value.empty() && (IsSimpleTextControl() || IsRichTextControl())) | 501 if (value.empty() && (IsSimpleTextControl() || IsRichTextControl())) |
| 467 value = GetInnerText(); | 502 value = GetInnerText(); |
| 468 return value; | 503 return value; |
| 469 } | 504 } |
| 470 | 505 |
| 506 int BrowserAccessibility::GetLineStartBoundary( | |
| 507 int start, | |
| 508 ui::TextBoundaryDirection direction) const { | |
| 509 DCHECK_GE(start, 0); | |
| 510 DCHECK_LE(start, static_cast<int>(GetText().length())); | |
| 511 | |
| 512 if (IsSimpleTextControl()) { | |
| 513 const std::vector<int32_t>& line_breaks = | |
| 514 GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS); | |
| 515 return ui::FindAccessibleTextBoundary(GetText(), line_breaks, | |
| 516 ui::LINE_BOUNDARY, start, direction); | |
| 517 } | |
| 518 | |
| 519 // Keeps track of the start offset of each consecutive line. | |
| 520 int line_start = 0; | |
| 521 // Keeps track of the length of each consecutive line. | |
| 522 int line_length = 0; | |
| 523 for (size_t i = 0; i < InternalChildCount(); ++i) { | |
| 524 const BrowserAccessibility* child = InternalGetChild(i); | |
| 525 DCHECK(child); | |
| 526 // Child objects are of length one, since they are represented by a | |
| 527 // single embedded object character. The exception is text-only objects. | |
| 528 int child_length = 1; | |
| 529 if (child->IsTextOnlyObject()) | |
| 530 child_length = static_cast<int>(child->GetText().length()); | |
| 531 line_length += child_length; | |
| 532 start -= child_length; | |
| 533 | |
| 534 // Stop when we reach both the object containing our start offset and the | |
| 535 // end of the line on which this object is located. | |
| 536 if (start < 0 && !IsNextSiblingOnSameLine()) | |
| 537 break; | |
| 538 | |
| 539 if (!IsNextSiblingOnSameLine()) { | |
| 540 line_start += line_length; | |
| 541 line_length = 0; | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 switch (direction) { | |
| 546 case ui::FORWARDS_DIRECTION: | |
| 547 return line_start + line_length; | |
| 548 case ui::BACKWARDS_DIRECTION: | |
| 549 return line_start; | |
| 550 default: | |
| 551 NOTREACHED(); | |
| 552 } | |
| 553 return static_cast<int>(GetText().length()); | |
| 554 ; | |
|
dmazzoni
2016/04/22 15:34:49
nit: extra semicolon?
| |
| 555 } | |
| 556 | |
| 471 int BrowserAccessibility::GetWordStartBoundary( | 557 int BrowserAccessibility::GetWordStartBoundary( |
| 472 int start, ui::TextBoundaryDirection direction) const { | 558 int start, ui::TextBoundaryDirection direction) const { |
| 473 DCHECK_GE(start, -1); | 559 DCHECK_GE(start, -1); |
| 474 // Special offset that indicates that a word boundary has not been found. | 560 // Special offset that indicates that a word boundary has not been found. |
| 475 int word_start_not_found = static_cast<int>(GetText().size()); | 561 int word_start_not_found = static_cast<int>(GetText().size()); |
| 476 int word_start = word_start_not_found; | 562 int word_start = word_start_not_found; |
| 477 | 563 |
| 478 switch (GetRole()) { | 564 switch (GetRole()) { |
| 479 case ui::AX_ROLE_STATIC_TEXT: { | 565 case ui::AX_ROLE_STATIC_TEXT: { |
| 480 int prev_word_start = word_start_not_found; | 566 int prev_word_start = word_start_not_found; |
| 481 int child_start = 0; | 567 int child_start = 0; |
| 482 int child_end = 0; | 568 int child_end = 0; |
| 483 | 569 |
| 484 // Go through the inline text boxes. | 570 // Go through the inline text boxes. |
| 485 for (size_t i = 0; i < InternalChildCount(); ++i) { | 571 for (size_t i = 0; i < InternalChildCount(); ++i) { |
| 486 // The next child starts where the previous one ended. | 572 // The next child starts where the previous one ended. |
| 487 child_start = child_end; | 573 child_start = child_end; |
| 488 BrowserAccessibility* child = InternalGetChild(i); | 574 const BrowserAccessibility* child = InternalGetChild(i); |
| 489 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); | 575 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); |
| 490 int child_len = static_cast<int>(child->GetText().size()); | 576 int child_len = static_cast<int>(child->GetText().size()); |
| 491 child_end += child_len; // End is one past the last character. | 577 child_end += child_len; // End is one past the last character. |
| 492 | 578 |
| 493 const std::vector<int32_t>& word_starts = | 579 const std::vector<int32_t>& word_starts = |
| 494 child->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS); | 580 child->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS); |
| 495 if (word_starts.empty()) { | 581 if (word_starts.empty()) { |
| 496 word_start = child_end; | 582 word_start = child_end; |
| 497 continue; | 583 continue; |
| 498 } | 584 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 if (IsSimpleTextControl() && InternalChildCount() == 1) { | 632 if (IsSimpleTextControl() && InternalChildCount() == 1) { |
| 547 this_object = InternalGetChild(0); | 633 this_object = InternalGetChild(0); |
| 548 } | 634 } |
| 549 int child_start = 0; | 635 int child_start = 0; |
| 550 for (size_t i = 0; i < this_object->InternalChildCount(); ++i) { | 636 for (size_t i = 0; i < this_object->InternalChildCount(); ++i) { |
| 551 BrowserAccessibility* child = this_object->InternalGetChild(i); | 637 BrowserAccessibility* child = this_object->InternalGetChild(i); |
| 552 // Child objects are of length one, since they are represented by a | 638 // Child objects are of length one, since they are represented by a |
| 553 // single embedded object character. The exception is text-only objects. | 639 // single embedded object character. The exception is text-only objects. |
| 554 int child_len = 1; | 640 int child_len = 1; |
| 555 if (child->IsTextOnlyObject()) { | 641 if (child->IsTextOnlyObject()) { |
| 556 child_len = static_cast<int>(child->GetText().size()); | 642 child_len = static_cast<int>(child->GetText().length()); |
| 557 int child_word_start = child->GetWordStartBoundary(start, direction); | 643 int child_word_start = child->GetWordStartBoundary(start, direction); |
| 558 if (child_word_start < child_len) { | 644 if (child_word_start < child_len) { |
| 559 // We have found a possible word boundary. | 645 // We have found a possible word boundary. |
| 560 word_start = child_start + child_word_start; | 646 word_start = child_start + child_word_start; |
| 561 } | 647 } |
| 562 | 648 |
| 563 // Decide when to stop searching. | 649 // Decide when to stop searching. |
| 564 if ((word_start != word_start_not_found && | 650 if ((word_start != word_start_not_found && |
| 565 direction == ui::FORWARDS_DIRECTION) || | 651 direction == ui::FORWARDS_DIRECTION) || |
| 566 (start < child_len && direction == ui::BACKWARDS_DIRECTION)) { | 652 (start < child_len && direction == ui::BACKWARDS_DIRECTION)) { |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1065 break; | 1151 break; |
| 1066 | 1152 |
| 1067 manager = root->GetParent()->manager(); | 1153 manager = root->GetParent()->manager(); |
| 1068 root = manager->GetRoot(); | 1154 root = manager->GetRoot(); |
| 1069 } | 1155 } |
| 1070 | 1156 |
| 1071 return bounds; | 1157 return bounds; |
| 1072 } | 1158 } |
| 1073 | 1159 |
| 1074 } // namespace content | 1160 } // namespace content |
| OLD | NEW |