Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: content/browser/accessibility/browser_accessibility_win.cc

Issue 2806773002: Switched to using |AXPosition| for calculating word and line boundaries on Windows. (Closed)
Patch Set: Fixed line boundaries. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_win.h" 5 #include "content/browser/accessibility/browser_accessibility_win.h"
6 6
7 #include <UIAutomationClient.h> 7 #include <UIAutomationClient.h>
8 #include <UIAutomationCoreApi.h> 8 #include <UIAutomationCoreApi.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 2468 matching lines...) Expand 10 before | Expand all | Expand 10 after
2479 BSTR* text) { 2479 BSTR* text) {
2480 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AT_OFFSET); 2480 WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_TEXT_AT_OFFSET);
2481 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes | 2481 AddAccessibilityModeFlags(kScreenReaderAndHTMLAccessibilityModes |
2482 AccessibilityMode::kInlineTextBoxes); 2482 AccessibilityMode::kInlineTextBoxes);
2483 if (!instance_active()) 2483 if (!instance_active())
2484 return E_FAIL; 2484 return E_FAIL;
2485 2485
2486 if (!start_offset || !end_offset || !text) 2486 if (!start_offset || !end_offset || !text)
2487 return E_INVALIDARG; 2487 return E_INVALIDARG;
2488 2488
2489 const base::string16& text_str = GetText();
2490 HandleSpecialTextOffset(&offset); 2489 HandleSpecialTextOffset(&offset);
2491 if (offset < 0) 2490 if (offset < 0)
2492 return E_INVALIDARG; 2491 return E_INVALIDARG;
2493 2492
2493 const base::string16& text_str = GetText();
2494 LONG text_len = text_str.length(); 2494 LONG text_len = text_str.length();
2495 if (offset > text_len) 2495 if (offset > text_len)
2496 return E_INVALIDARG; 2496 return E_INVALIDARG;
2497 2497
2498 // The IAccessible2 spec says we don't have to implement the "sentence" 2498 // The IAccessible2 spec says we don't have to implement the "sentence"
2499 // boundary type, we can just let the screenreader handle it. 2499 // boundary type, we can just let the screenreader handle it.
2500 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) { 2500 if (boundary_type == IA2_TEXT_BOUNDARY_SENTENCE) {
2501 *start_offset = 0; 2501 *start_offset = 0;
2502 *end_offset = 0; 2502 *end_offset = 0;
2503 *text = NULL; 2503 *text = NULL;
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after
3882 start_offset += child->GetText().length(); 3882 start_offset += child->GetText().length();
3883 else 3883 else
3884 start_offset += 1; 3884 start_offset += 1;
3885 } 3885 }
3886 3886
3887 win_attributes_->offset_to_text_attributes.swap(attributes_map); 3887 win_attributes_->offset_to_text_attributes.swap(attributes_map);
3888 } 3888 }
3889 3889
3890 // |offset| could either be a text character or a child index in case of 3890 // |offset| could either be a text character or a child index in case of
3891 // non-text objects. 3891 // non-text objects.
3892 // TODO(nektar): Remove this function once selection bugs are fixed in Blink.
3892 BrowserAccessibilityWin::AXPlatformPositionInstance 3893 BrowserAccessibilityWin::AXPlatformPositionInstance
3893 BrowserAccessibilityWin::CreatePositionAt(int offset) const { 3894 BrowserAccessibilityWin::CreatePositionForSelectionAt(int offset) const {
3894 if (!IsNativeTextControl() && !IsTextOnlyObject()) { 3895 if (!IsNativeTextControl() && !IsTextOnlyObject()) {
3895 DCHECK(manager_); 3896 DCHECK(manager_);
3896 const BrowserAccessibilityWin* child = this; 3897 const BrowserAccessibilityWin* child = this;
3897 // TODO(nektar): Make parents of text-only objects not include the text of 3898 // TODO(nektar): Make parents of text-only objects not include the text of
3898 // children in their hypertext. 3899 // children in their hypertext.
3899 for (size_t i = 0; i < InternalChildCount(); ++i) { 3900 for (size_t i = 0; i < InternalChildCount(); ++i) {
3900 int new_offset = offset; 3901 int new_offset = offset;
3901 child = ToBrowserAccessibilityWin(InternalGetChild(i)); 3902 child = ToBrowserAccessibilityWin(InternalGetChild(i));
3902 DCHECK(child); 3903 DCHECK(child);
3903 if (child->IsTextOnlyObject()) { 3904 if (child->IsTextOnlyObject()) {
3904 new_offset -= child->GetText().length(); 3905 new_offset -= child->GetText().length();
3905 } else { 3906 } else {
3906 new_offset -= 1; 3907 new_offset -= 1;
3907 } 3908 }
3908 if (new_offset <= 0) 3909 if (new_offset <= 0)
3909 break; 3910 break;
3910 offset = new_offset; 3911 offset = new_offset;
3911 } 3912 }
3912 AXPlatformPositionInstance position = 3913 AXPlatformPositionInstance position =
3913 AXPlatformPosition::CreateTextPosition(manager_->ax_tree_id(), 3914 AXPlatformPosition::CreateTextPosition(manager_->ax_tree_id(),
3914 child->GetId(), offset, 3915 child->GetId(), offset,
3915 ui::AX_TEXT_AFFINITY_DOWNSTREAM) 3916 ui::AX_TEXT_AFFINITY_DOWNSTREAM)
3916 ->AsLeafTextPosition(); 3917 ->AsLeafTextPosition();
3917 if (position->GetAnchor() && 3918 if (position->GetAnchor() &&
3918 position->GetAnchor()->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) { 3919 position->GetAnchor()->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) {
3919 return position->CreateParentPosition(); 3920 return position->CreateParentPosition();
3920 } 3921 }
3921 return position; 3922 return position;
3922 } 3923 }
3923 return BrowserAccessibility::CreatePositionAt(offset); 3924 return CreatePositionAt(offset);
3924 } 3925 }
3925 3926
3926 base::string16 BrowserAccessibilityWin::GetText() const { 3927 base::string16 BrowserAccessibilityWin::GetText() const {
3927 if (PlatformIsChildOfLeaf()) 3928 if (PlatformIsChildOfLeaf())
3928 return BrowserAccessibility::GetText(); 3929 return BrowserAccessibility::GetText();
3929 return win_attributes_->hypertext; 3930 return win_attributes_->hypertext;
3930 } 3931 }
3931 3932
3932 // 3933 //
3933 // Private methods. 3934 // Private methods.
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
4570 base::ReplaceChars(*output, L",", L"\\,", output); 4571 base::ReplaceChars(*output, L",", L"\\,", output);
4571 base::ReplaceChars(*output, L"=", L"\\=", output); 4572 base::ReplaceChars(*output, L"=", L"\\=", output);
4572 base::ReplaceChars(*output, L";", L"\\;", output); 4573 base::ReplaceChars(*output, L";", L"\\;", output);
4573 } 4574 }
4574 4575
4575 void BrowserAccessibilityWin::SetIA2HypertextSelection(LONG start_offset, 4576 void BrowserAccessibilityWin::SetIA2HypertextSelection(LONG start_offset,
4576 LONG end_offset) { 4577 LONG end_offset) {
4577 HandleSpecialTextOffset(&start_offset); 4578 HandleSpecialTextOffset(&start_offset);
4578 HandleSpecialTextOffset(&end_offset); 4579 HandleSpecialTextOffset(&end_offset);
4579 AXPlatformPositionInstance start_position = 4580 AXPlatformPositionInstance start_position =
4580 CreatePositionAt(static_cast<int>(start_offset)); 4581 CreatePositionForSelectionAt(static_cast<int>(start_offset));
4581 AXPlatformPositionInstance end_position = 4582 AXPlatformPositionInstance end_position =
4582 CreatePositionAt(static_cast<int>(end_offset)); 4583 CreatePositionForSelectionAt(static_cast<int>(end_offset));
4583 manager_->SetSelection(AXPlatformRange(start_position->AsTextPosition(), 4584 manager_->SetSelection(AXPlatformRange(start_position->AsTextPosition(),
4584 end_position->AsTextPosition())); 4585 end_position->AsTextPosition()));
4585 } 4586 }
4586 4587
4587 void BrowserAccessibilityWin::StringAttributeToIA2( 4588 void BrowserAccessibilityWin::StringAttributeToIA2(
4588 ui::AXStringAttribute attribute, 4589 ui::AXStringAttribute attribute,
4589 const char* ia2_attr) { 4590 const char* ia2_attr) {
4590 base::string16 value; 4591 base::string16 value;
4591 if (GetString16Attribute(attribute, &value)) { 4592 if (GetString16Attribute(attribute, &value)) {
4592 SanitizeStringAttributeForIA2(value, &value); 4593 SanitizeStringAttributeForIA2(value, &value);
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
4980 IA2TextBoundaryType ia2_boundary, 4981 IA2TextBoundaryType ia2_boundary,
4981 LONG start_offset, 4982 LONG start_offset,
4982 ui::TextBoundaryDirection direction) { 4983 ui::TextBoundaryDirection direction) {
4983 // If the boundary is relative to the caret, use the selection 4984 // If the boundary is relative to the caret, use the selection
4984 // affinity, otherwise default to downstream affinity. 4985 // affinity, otherwise default to downstream affinity.
4985 ui::AXTextAffinity affinity = start_offset == IA2_TEXT_OFFSET_CARET 4986 ui::AXTextAffinity affinity = start_offset == IA2_TEXT_OFFSET_CARET
4986 ? manager_->GetTreeData().sel_focus_affinity 4987 ? manager_->GetTreeData().sel_focus_affinity
4987 : ui::AX_TEXT_AFFINITY_DOWNSTREAM; 4988 : ui::AX_TEXT_AFFINITY_DOWNSTREAM;
4988 4989
4989 HandleSpecialTextOffset(&start_offset); 4990 HandleSpecialTextOffset(&start_offset);
4990 if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD) 4991 if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD) {
4991 return GetWordStartBoundary(static_cast<int>(start_offset), direction); 4992 switch (direction) {
4992 if (ia2_boundary == IA2_TEXT_BOUNDARY_LINE) { 4993 case ui::FORWARDS_DIRECTION: {
4993 return GetLineStartBoundary( 4994 AXPlatformPositionInstance position =
4994 static_cast<int>(start_offset), direction, affinity); 4995 CreatePositionAt(static_cast<int>(start_offset), affinity);
4996 AXPlatformPositionInstance next_word =
4997 position->CreateNextWordStartPosition();
4998 if (next_word->IsNullPosition())
4999 next_word = position->CreatePositionAtEndOfAnchor();
5000 return next_word->text_offset();
5001 }
5002 case ui::BACKWARDS_DIRECTION: {
5003 AXPlatformPositionInstance position =
5004 CreatePositionAt(static_cast<int>(start_offset), affinity);
5005 AXPlatformPositionInstance previous_word;
5006 if (!position->AtStartOfWord()) {
5007 previous_word = position->CreatePreviousWordStartPosition();
dmazzoni 2017/04/10 22:39:49 Just curious, should CreatePreviousWordStartPositi
5008 if (previous_word->IsNullPosition())
5009 previous_word = position->CreatePositionAtStartOfAnchor();
5010 } else {
5011 previous_word = std::move(position);
5012 }
5013 return previous_word->text_offset();
5014 }
5015 }
dmazzoni 2017/04/10 22:39:49 Maybe add a NOTREACHED() after the switch since th
4995 } 5016 }
4996 5017
5018 if (ia2_boundary == IA2_TEXT_BOUNDARY_LINE) {
5019 switch (direction) {
5020 case ui::FORWARDS_DIRECTION: {
5021 AXPlatformPositionInstance position =
5022 CreatePositionAt(static_cast<int>(start_offset), affinity);
5023 AXPlatformPositionInstance next_line =
5024 position->CreateNextLineStartPosition();
5025 if (next_line->IsNullPosition())
5026 next_line = position->CreatePositionAtEndOfAnchor();
5027 return next_line->text_offset();
5028 }
5029 case ui::BACKWARDS_DIRECTION: {
5030 AXPlatformPositionInstance position =
5031 CreatePositionAt(static_cast<int>(start_offset), affinity);
5032 AXPlatformPositionInstance previous_line;
5033 if (!position->AtStartOfLine()) {
5034 previous_line = position->CreatePreviousLineStartPosition();
5035 if (previous_line->IsNullPosition())
5036 previous_line = position->CreatePositionAtStartOfAnchor();
5037 } else {
5038 previous_line = std::move(position);
5039 }
5040 return previous_line->text_offset();
5041 }
5042 }
dmazzoni 2017/04/10 22:39:49 NOTREACHED
5043 }
5044
5045 // TODO(nektar): |AXPosition| can handle other types of boundaries as well.
4997 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); 5046 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
4998 return ui::FindAccessibleTextBoundary(text, GetLineStartOffsets(), boundary, 5047 return ui::FindAccessibleTextBoundary(text, GetLineStartOffsets(), boundary,
4999 start_offset, direction, affinity); 5048 start_offset, direction, affinity);
5000 } 5049 }
5001 5050
5002 LONG BrowserAccessibilityWin::FindStartOfStyle( 5051 LONG BrowserAccessibilityWin::FindStartOfStyle(
5003 LONG start_offset, 5052 LONG start_offset,
5004 ui::TextBoundaryDirection direction) const { 5053 ui::TextBoundaryDirection direction) const {
5005 LONG text_length = static_cast<LONG>(GetText().length()); 5054 LONG text_length = static_cast<LONG>(GetText().length());
5006 DCHECK_GE(start_offset, 0); 5055 DCHECK_GE(start_offset, 0);
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after
5833 return static_cast<BrowserAccessibilityWin*>(obj); 5882 return static_cast<BrowserAccessibilityWin*>(obj);
5834 } 5883 }
5835 5884
5836 const BrowserAccessibilityWin* 5885 const BrowserAccessibilityWin*
5837 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) { 5886 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) {
5838 DCHECK(!obj || obj->IsNative()); 5887 DCHECK(!obj || obj->IsNative());
5839 return static_cast<const BrowserAccessibilityWin*>(obj); 5888 return static_cast<const BrowserAccessibilityWin*>(obj);
5840 } 5889 }
5841 5890
5842 } // namespace content 5891 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698