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_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 #include <algorithm> | |
| 9 | 10 |
| 10 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
| 12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/win/enum_variant.h" | 15 #include "base/win/enum_variant.h" |
| 15 #include "base/win/scoped_comptr.h" | 16 #include "base/win/scoped_comptr.h" |
| 16 #include "base/win/windows_version.h" | 17 #include "base/win/windows_version.h" |
| 17 #include "content/browser/accessibility/browser_accessibility_manager_win.h" | 18 #include "content/browser/accessibility/browser_accessibility_manager_win.h" |
| 18 #include "content/browser/accessibility/browser_accessibility_state_impl.h" | 19 #include "content/browser/accessibility/browser_accessibility_state_impl.h" |
| (...skipping 3271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3290 NOTREACHED(); | 3291 NOTREACHED(); |
| 3291 return ui::CHAR_BOUNDARY; | 3292 return ui::CHAR_BOUNDARY; |
| 3292 } | 3293 } |
| 3293 } | 3294 } |
| 3294 | 3295 |
| 3295 LONG BrowserAccessibilityWin::FindBoundary( | 3296 LONG BrowserAccessibilityWin::FindBoundary( |
| 3296 const base::string16& text, | 3297 const base::string16& text, |
| 3297 IA2TextBoundaryType ia2_boundary, | 3298 IA2TextBoundaryType ia2_boundary, |
| 3298 LONG start_offset, | 3299 LONG start_offset, |
| 3299 ui::TextBoundaryDirection direction) { | 3300 ui::TextBoundaryDirection direction) { |
| 3301 if (ia2_boundary == IA2_TEXT_BOUNDARY_WORD) | |
| 3302 return FindWordStartBoundary(text, start_offset, direction); | |
| 3303 | |
| 3300 HandleSpecialTextOffset(text, &start_offset); | 3304 HandleSpecialTextOffset(text, &start_offset); |
| 3301 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); | 3305 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); |
| 3302 const std::vector<int32>& line_breaks = GetIntListAttribute( | 3306 const std::vector<int32>& line_breaks = GetIntListAttribute( |
| 3303 ui::AX_ATTR_LINE_BREAKS); | 3307 ui::AX_ATTR_LINE_BREAKS); |
| 3304 return ui::FindAccessibleTextBoundary( | 3308 return ui::FindAccessibleTextBoundary( |
| 3305 text, line_breaks, boundary, start_offset, direction); | 3309 text, line_breaks, boundary, start_offset, direction); |
| 3306 } | 3310 } |
| 3307 | 3311 |
| 3312 LONG BrowserAccessibilityWin::FindWordStartBoundary( | |
|
dmazzoni
2014/10/15 22:03:10
Please move this to browser_accessibility.cc inste
| |
| 3313 const base::string16& text, | |
| 3314 LONG start_offset, | |
| 3315 ui::TextBoundaryDirection direction) { | |
| 3316 HandleSpecialTextOffset(text, &start_offset); | |
| 3317 if (!IsEditableText()) { | |
| 3318 // We don't actually need the line breaks. | |
| 3319 const std::vector<int32> line_breaks; | |
| 3320 return ui::FindAccessibleTextBoundary( | |
| 3321 text, line_breaks, ui::WORD_START_BOUNDARY, start_offset, direction); | |
| 3322 } | |
| 3323 | |
| 3324 LONG word_start = 0; | |
| 3325 LONG child_start = 0; | |
| 3326 LONG child_end = 0; | |
| 3327 | |
| 3328 for (size_t i = 0; i < InternalChildCount(); ++i) { | |
| 3329 // The next child starts where the previous one ended. | |
| 3330 child_start = child_end; | |
| 3331 BrowserAccessibilityWin* child = InternalGetChild( | |
| 3332 i)->ToBrowserAccessibilityWin(); | |
| 3333 DCHECK_EQ(child->GetRole(), ui::AX_ROLE_INLINE_TEXT_BOX); | |
| 3334 const base::string16& child_text = child->TextForIAccessibleText(); | |
| 3335 LONG child_len = static_cast<LONG>(child_text.length()); | |
| 3336 child_end += child_len; // End is one passed the last character. | |
| 3337 | |
| 3338 if (start_offset >= child_end) | |
| 3339 continue; | |
| 3340 | |
| 3341 const std::vector<int32>& word_starts = child->GetIntListAttribute( | |
| 3342 ui::AX_ATTR_WORD_STARTS); | |
| 3343 if (!word_starts.empty()) { | |
|
dmazzoni
2014/10/15 22:03:10
When possible, reverse the direction of a test to
| |
| 3344 int local_start = static_cast<int32>(start_offset, child_start); | |
| 3345 if (direction == ui::FORWARDS_DIRECTION) { | |
| 3346 std::vector<int32>::const_iterator iter = std::upper_bound( | |
| 3347 word_starts.cbegin(), word_starts.cend(), local_start); | |
| 3348 if (iter != word_starts.cend()) { | |
| 3349 word_start = *iter; | |
| 3350 break; | |
| 3351 } else { | |
| 3352 // In case there are no more children or remaining children have no | |
| 3353 // text, e.g., an image. | |
| 3354 word_start = child_end; | |
| 3355 continue; | |
| 3356 } | |
| 3357 } else if (direction == ui::BACKWARDS_DIRECTION) { | |
| 3358 std::vector<int32>::const_iterator iter = std::lower_bound( | |
| 3359 word_starts.cbegin(), word_starts.cend(), local_start); | |
| 3360 if (iter != word_starts.cbegin() { | |
| 3361 --iter; | |
| 3362 word_start = *iter; | |
| 3363 break; | |
| 3364 } else { | |
| 3365 // Return the start of the last word in the previous child. | |
| 3366 for (int j = i - 1; j >= 0; --j) { | |
| 3367 child = InternalGetChild(j).ToBrowserAccessibilityWin(); | |
| 3368 word_starts = child->GetIntListAttribute(ui::AX_ATTR_WORD_STARTS); | |
| 3369 if (!word_starts.empty()) | |
| 3370 word_start = word_starts[word_starts.length() - 1]; | |
| 3371 } | |
| 3372 break; | |
| 3373 } | |
| 3374 } | |
| 3375 } | |
| 3376 } | |
| 3377 | |
| 3378 return word_start; | |
| 3379 } | |
| 3380 | |
| 3308 BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32 id) { | 3381 BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32 id) { |
| 3309 return manager()->GetFromID(id)->ToBrowserAccessibilityWin(); | 3382 return manager()->GetFromID(id)->ToBrowserAccessibilityWin(); |
| 3310 } | 3383 } |
| 3311 | 3384 |
| 3312 void BrowserAccessibilityWin::InitRoleAndState() { | 3385 void BrowserAccessibilityWin::InitRoleAndState() { |
| 3313 ia_state_ = 0; | 3386 ia_state_ = 0; |
| 3314 ia2_state_ = IA2_STATE_OPAQUE; | 3387 ia2_state_ = IA2_STATE_OPAQUE; |
| 3315 ia2_attributes_.clear(); | 3388 ia2_attributes_.clear(); |
| 3316 | 3389 |
| 3317 if (HasState(ui::AX_STATE_BUSY)) | 3390 if (HasState(ui::AX_STATE_BUSY)) |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3847 // The role should always be set. | 3920 // The role should always be set. |
| 3848 DCHECK(!role_name_.empty() || ia_role_); | 3921 DCHECK(!role_name_.empty() || ia_role_); |
| 3849 | 3922 |
| 3850 // If we didn't explicitly set the IAccessible2 role, make it the same | 3923 // If we didn't explicitly set the IAccessible2 role, make it the same |
| 3851 // as the MSAA role. | 3924 // as the MSAA role. |
| 3852 if (!ia2_role_) | 3925 if (!ia2_role_) |
| 3853 ia2_role_ = ia_role_; | 3926 ia2_role_ = ia_role_; |
| 3854 } | 3927 } |
| 3855 | 3928 |
| 3856 } // namespace content | 3929 } // namespace content |
| OLD | NEW |