| 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 <execinfo.h> | 5 #include <execinfo.h> |
| 6 #include <stddef.h> | 6 #include <stddef.h> |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #import "content/browser/accessibility/browser_accessibility_cocoa.h" | 9 #import "content/browser/accessibility/browser_accessibility_cocoa.h" |
| 10 | 10 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 // Actions. | 86 // Actions. |
| 87 NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible"; | 87 NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible"; |
| 88 | 88 |
| 89 // A mapping from an accessibility attribute to its method name. | 89 // A mapping from an accessibility attribute to its method name. |
| 90 NSDictionary* attributeToMethodNameMap = nil; | 90 NSDictionary* attributeToMethodNameMap = nil; |
| 91 | 91 |
| 92 struct AXTextMarkerData { | 92 struct AXTextMarkerData { |
| 93 AXTreeIDRegistry::AXTreeID tree_id; | 93 AXTreeIDRegistry::AXTreeID tree_id; |
| 94 int32_t node_id; | 94 int32_t node_id; |
| 95 int offset; | 95 int offset; |
| 96 ui::AXTextAffinity affinity; |
| 96 }; | 97 }; |
| 97 | 98 |
| 98 // VoiceOver uses -1 to mean "no limit" for AXResultsLimit. | 99 // VoiceOver uses -1 to mean "no limit" for AXResultsLimit. |
| 99 const int kAXResultsLimitNoLimit = -1; | 100 const int kAXResultsLimitNoLimit = -1; |
| 100 | 101 |
| 101 extern "C" { | 102 extern "C" { |
| 102 | 103 |
| 103 // See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5, | 104 // See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5, |
| 104 // 10.6, and 10.7. It allows accessibility clients to observe events posted on | 105 // 10.6, and 10.7. It allows accessibility clients to observe events posted on |
| 105 // this object. | 106 // this object. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 123 AXTextMarkerRef AXTextMarkerRangeCopyStartMarker( | 124 AXTextMarkerRef AXTextMarkerRangeCopyStartMarker( |
| 124 AXTextMarkerRangeRef text_marker_range); | 125 AXTextMarkerRangeRef text_marker_range); |
| 125 | 126 |
| 126 AXTextMarkerRef AXTextMarkerRangeCopyEndMarker( | 127 AXTextMarkerRef AXTextMarkerRangeCopyEndMarker( |
| 127 AXTextMarkerRangeRef text_marker_range); | 128 AXTextMarkerRangeRef text_marker_range); |
| 128 | 129 |
| 129 #endif // MAC_OS_X_VERSION_10_11 | 130 #endif // MAC_OS_X_VERSION_10_11 |
| 130 | 131 |
| 131 } // extern "C" | 132 } // extern "C" |
| 132 | 133 |
| 133 id CreateTextMarker(const BrowserAccessibility& object, int offset) { | 134 id CreateTextMarker(const BrowserAccessibility& object, |
| 135 int offset, |
| 136 ui::AXTextAffinity affinity) { |
| 134 AXTextMarkerData marker_data; | 137 AXTextMarkerData marker_data; |
| 135 marker_data.tree_id = object.manager() ? object.manager()->ax_tree_id() : -1; | 138 marker_data.tree_id = object.manager() ? object.manager()->ax_tree_id() : -1; |
| 136 marker_data.node_id = object.GetId(); | 139 marker_data.node_id = object.GetId(); |
| 137 marker_data.offset = offset; | 140 marker_data.offset = offset; |
| 141 marker_data.affinity = affinity; |
| 138 return (id)base::mac::CFTypeRefToNSObjectAutorelease(AXTextMarkerCreate( | 142 return (id)base::mac::CFTypeRefToNSObjectAutorelease(AXTextMarkerCreate( |
| 139 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(&marker_data), | 143 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(&marker_data), |
| 140 sizeof(marker_data))); | 144 sizeof(marker_data))); |
| 141 } | 145 } |
| 142 | 146 |
| 143 id CreateTextMarkerRange(const BrowserAccessibility& start_object, | 147 id CreateTextMarkerRange(const BrowserAccessibility& start_object, |
| 144 int start_offset, | 148 int start_offset, |
| 149 ui::AXTextAffinity start_affinity, |
| 145 const BrowserAccessibility& end_object, | 150 const BrowserAccessibility& end_object, |
| 146 int end_offset) { | 151 int end_offset, |
| 147 id start_marker = CreateTextMarker(start_object, start_offset); | 152 ui::AXTextAffinity end_affinity) { |
| 148 id end_marker = CreateTextMarker(end_object, end_offset); | 153 id start_marker = CreateTextMarker( |
| 154 start_object, start_offset, start_affinity); |
| 155 id end_marker = CreateTextMarker(end_object, end_offset, end_affinity); |
| 149 return (id)base::mac::CFTypeRefToNSObjectAutorelease( | 156 return (id)base::mac::CFTypeRefToNSObjectAutorelease( |
| 150 AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker)); | 157 AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker)); |
| 151 } | 158 } |
| 152 | 159 |
| 153 bool GetTextMarkerData(AXTextMarkerRef text_marker, | 160 bool GetTextMarkerData(AXTextMarkerRef text_marker, |
| 154 BrowserAccessibility** object, | 161 BrowserAccessibility** object, |
| 155 int* offset) { | 162 int* offset, |
| 163 ui::AXTextAffinity* affinity) { |
| 156 DCHECK(text_marker); | 164 DCHECK(text_marker); |
| 157 DCHECK(object && offset); | 165 DCHECK(object && offset); |
| 158 const auto* marker_data = reinterpret_cast<const AXTextMarkerData*>( | 166 const auto* marker_data = reinterpret_cast<const AXTextMarkerData*>( |
| 159 AXTextMarkerGetBytePtr(text_marker)); | 167 AXTextMarkerGetBytePtr(text_marker)); |
| 160 if (!marker_data) | 168 if (!marker_data) |
| 161 return false; | 169 return false; |
| 162 | 170 |
| 163 const BrowserAccessibilityManager* manager = | 171 const BrowserAccessibilityManager* manager = |
| 164 BrowserAccessibilityManager::FromID(marker_data->tree_id); | 172 BrowserAccessibilityManager::FromID(marker_data->tree_id); |
| 165 if (!manager) | 173 if (!manager) |
| 166 return false; | 174 return false; |
| 167 | 175 |
| 168 *object = manager->GetFromID(marker_data->node_id); | 176 *object = manager->GetFromID(marker_data->node_id); |
| 169 if (!*object) | 177 if (!*object) |
| 170 return false; | 178 return false; |
| 171 | 179 |
| 172 *offset = marker_data->offset; | 180 *offset = marker_data->offset; |
| 173 if (*offset < 0) | 181 if (*offset < 0) |
| 174 return false; | 182 return false; |
| 175 | 183 |
| 184 *affinity = marker_data->affinity; |
| 185 |
| 176 return true; | 186 return true; |
| 177 } | 187 } |
| 178 | 188 |
| 179 bool GetTextMarkerRange(AXTextMarkerRangeRef marker_range, | 189 bool GetTextMarkerRange(AXTextMarkerRangeRef marker_range, |
| 180 BrowserAccessibility** start_object, | 190 BrowserAccessibility** start_object, |
| 181 int* start_offset, | 191 int* start_offset, |
| 192 ui::AXTextAffinity* start_affinity, |
| 182 BrowserAccessibility** end_object, | 193 BrowserAccessibility** end_object, |
| 183 int* end_offset) { | 194 int* end_offset, |
| 195 ui::AXTextAffinity* end_affinity) { |
| 184 DCHECK(marker_range); | 196 DCHECK(marker_range); |
| 185 DCHECK(start_object && start_offset); | 197 DCHECK(start_object && start_offset); |
| 186 DCHECK(end_object && end_offset); | 198 DCHECK(end_object && end_offset); |
| 187 | 199 |
| 188 base::ScopedCFTypeRef<AXTextMarkerRef> start_marker( | 200 base::ScopedCFTypeRef<AXTextMarkerRef> start_marker( |
| 189 AXTextMarkerRangeCopyStartMarker(marker_range)); | 201 AXTextMarkerRangeCopyStartMarker(marker_range)); |
| 190 base::ScopedCFTypeRef<AXTextMarkerRef> end_marker( | 202 base::ScopedCFTypeRef<AXTextMarkerRef> end_marker( |
| 191 AXTextMarkerRangeCopyEndMarker(marker_range)); | 203 AXTextMarkerRangeCopyEndMarker(marker_range)); |
| 192 if (!start_marker.get() || !end_marker.get()) | 204 if (!start_marker.get() || !end_marker.get()) |
| 193 return false; | 205 return false; |
| 194 | 206 |
| 195 return GetTextMarkerData(start_marker.get(), start_object, start_offset) && | 207 return GetTextMarkerData(start_marker.get(), |
| 196 GetTextMarkerData(end_marker.get(), end_object, end_offset); | 208 start_object, start_offset, start_affinity) && |
| 209 GetTextMarkerData(end_marker.get(), |
| 210 end_object, end_offset, end_affinity); |
| 197 } | 211 } |
| 198 | 212 |
| 199 void AddMisspelledTextAttributes( | 213 void AddMisspelledTextAttributes( |
| 200 const std::vector<const BrowserAccessibility*>& text_only_objects, | 214 const std::vector<const BrowserAccessibility*>& text_only_objects, |
| 201 NSMutableAttributedString* attributed_string) { | 215 NSMutableAttributedString* attributed_string) { |
| 202 [attributed_string beginEditing]; | 216 [attributed_string beginEditing]; |
| 203 for (const BrowserAccessibility* text_object : text_only_objects) { | 217 for (const BrowserAccessibility* text_object : text_only_objects) { |
| 204 const std::vector<int32_t>& marker_types = | 218 const std::vector<int32_t>& marker_types = |
| 205 text_object->GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES); | 219 text_object->GetIntListAttribute(ui::AX_ATTR_MARKER_TYPES); |
| 206 const std::vector<int>& marker_starts = | 220 const std::vector<int>& marker_starts = |
| (...skipping 16 matching lines...) Expand all Loading... |
| 223 range:NSMakeRange(misspelling_start, misspelling_length)]; | 237 range:NSMakeRange(misspelling_start, misspelling_length)]; |
| 224 } | 238 } |
| 225 } | 239 } |
| 226 [attributed_string endEditing]; | 240 [attributed_string endEditing]; |
| 227 } | 241 } |
| 228 | 242 |
| 229 NSString* GetTextForTextMarkerRange(AXTextMarkerRangeRef marker_range) { | 243 NSString* GetTextForTextMarkerRange(AXTextMarkerRangeRef marker_range) { |
| 230 BrowserAccessibility* start_object; | 244 BrowserAccessibility* start_object; |
| 231 BrowserAccessibility* end_object; | 245 BrowserAccessibility* end_object; |
| 232 int start_offset, end_offset; | 246 int start_offset, end_offset; |
| 233 if (!GetTextMarkerRange(marker_range, &start_object, &start_offset, | 247 ui::AXTextAffinity start_affinity, end_affinity; |
| 234 &end_object, &end_offset)) { | 248 if (!GetTextMarkerRange(marker_range, |
| 249 &start_object, &start_offset, &start_affinity, |
| 250 &end_object, &end_offset, &end_affinity)) { |
| 235 return nil; | 251 return nil; |
| 236 } | 252 } |
| 237 DCHECK(start_object && end_object); | 253 DCHECK(start_object && end_object); |
| 238 DCHECK_GE(start_offset, 0); | 254 DCHECK_GE(start_offset, 0); |
| 239 DCHECK_GE(end_offset, 0); | 255 DCHECK_GE(end_offset, 0); |
| 240 | 256 |
| 241 return base::SysUTF16ToNSString(BrowserAccessibilityManager::GetTextForRange( | 257 return base::SysUTF16ToNSString(BrowserAccessibilityManager::GetTextForRange( |
| 242 *start_object, start_offset, *end_object, end_offset)); | 258 *start_object, start_offset, *end_object, end_offset)); |
| 243 } | 259 } |
| 244 | 260 |
| 245 NSAttributedString* GetAttributedTextForTextMarkerRange( | 261 NSAttributedString* GetAttributedTextForTextMarkerRange( |
| 246 AXTextMarkerRangeRef marker_range) { | 262 AXTextMarkerRangeRef marker_range) { |
| 247 BrowserAccessibility* start_object; | 263 BrowserAccessibility* start_object; |
| 248 BrowserAccessibility* end_object; | 264 BrowserAccessibility* end_object; |
| 249 int start_offset, end_offset; | 265 int start_offset, end_offset; |
| 250 if (!GetTextMarkerRange(marker_range, &start_object, &start_offset, | 266 ui::AXTextAffinity start_affinity, end_affinity; |
| 251 &end_object, &end_offset)) { | 267 if (!GetTextMarkerRange(marker_range, |
| 268 &start_object, &start_offset, &start_affinity, |
| 269 &end_object, &end_offset, &end_affinity)) { |
| 252 return nil; | 270 return nil; |
| 253 } | 271 } |
| 254 | 272 |
| 255 NSString* text = base::SysUTF16ToNSString( | 273 NSString* text = base::SysUTF16ToNSString( |
| 256 BrowserAccessibilityManager::GetTextForRange(*start_object, *end_object)); | 274 BrowserAccessibilityManager::GetTextForRange(*start_object, *end_object)); |
| 257 if ([text length] == 0) | 275 if ([text length] == 0) |
| 258 return nil; | 276 return nil; |
| 259 | 277 |
| 260 // Be permissive with the start and end offsets. | 278 // Be permissive with the start and end offsets. |
| 261 if (start_object == end_object && end_offset < start_offset) | 279 if (start_object == end_object && end_offset < start_offset) |
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 BrowserAccessibilityManager::PreviousTextOnlyObject(last_text_object); | 907 BrowserAccessibilityManager::PreviousTextOnlyObject(last_text_object); |
| 890 } | 908 } |
| 891 while (last_text_object) { | 909 while (last_text_object) { |
| 892 last_text_object = | 910 last_text_object = |
| 893 BrowserAccessibilityManager::PreviousTextOnlyObject(last_text_object); | 911 BrowserAccessibilityManager::PreviousTextOnlyObject(last_text_object); |
| 894 } | 912 } |
| 895 if (!last_text_object) | 913 if (!last_text_object) |
| 896 return nil; | 914 return nil; |
| 897 | 915 |
| 898 return CreateTextMarker(*last_text_object, | 916 return CreateTextMarker(*last_text_object, |
| 899 last_text_object->GetText().length()); | 917 last_text_object->GetText().length(), |
| 918 ui::AX_TEXT_AFFINITY_DOWNSTREAM); |
| 900 } | 919 } |
| 901 | 920 |
| 902 - (NSNumber*)expanded { | 921 - (NSNumber*)expanded { |
| 903 if (![self instanceActive]) | 922 if (![self instanceActive]) |
| 904 return nil; | 923 return nil; |
| 905 return [NSNumber numberWithBool: | 924 return [NSNumber numberWithBool: |
| 906 GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)]; | 925 GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)]; |
| 907 } | 926 } |
| 908 | 927 |
| 909 - (NSNumber*)focused { | 928 - (NSNumber*)focused { |
| (...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1567 int32_t focusId = manager->GetTreeData().sel_focus_object_id; | 1586 int32_t focusId = manager->GetTreeData().sel_focus_object_id; |
| 1568 const BrowserAccessibility* focusObject = manager->GetFromID(focusId); | 1587 const BrowserAccessibility* focusObject = manager->GetFromID(focusId); |
| 1569 if (!focusObject) | 1588 if (!focusObject) |
| 1570 return nil; | 1589 return nil; |
| 1571 | 1590 |
| 1572 int anchorOffset = manager->GetTreeData().sel_anchor_offset; | 1591 int anchorOffset = manager->GetTreeData().sel_anchor_offset; |
| 1573 int focusOffset = manager->GetTreeData().sel_focus_offset; | 1592 int focusOffset = manager->GetTreeData().sel_focus_offset; |
| 1574 if (anchorOffset < 0 || focusOffset < 0) | 1593 if (anchorOffset < 0 || focusOffset < 0) |
| 1575 return nil; | 1594 return nil; |
| 1576 | 1595 |
| 1577 return CreateTextMarkerRange(*anchorObject, anchorOffset, *focusObject, | 1596 ui::AXTextAffinity anchorAffinity = |
| 1578 focusOffset); | 1597 manager->GetTreeData().sel_anchor_affinity; |
| 1598 ui::AXTextAffinity focusAffinity = manager->GetTreeData().sel_focus_affinity; |
| 1599 |
| 1600 return CreateTextMarkerRange(*anchorObject, anchorOffset, anchorAffinity, |
| 1601 *focusObject, focusOffset, focusAffinity); |
| 1579 } | 1602 } |
| 1580 | 1603 |
| 1581 - (NSValue*)size { | 1604 - (NSValue*)size { |
| 1582 if (![self instanceActive]) | 1605 if (![self instanceActive]) |
| 1583 return nil; | 1606 return nil; |
| 1584 gfx::Rect bounds = browserAccessibility_->GetLocalBoundsRect(); | 1607 gfx::Rect bounds = browserAccessibility_->GetLocalBoundsRect(); |
| 1585 return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())]; | 1608 return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())]; |
| 1586 } | 1609 } |
| 1587 | 1610 |
| 1588 - (NSString*)sortDirection { | 1611 - (NSString*)sortDirection { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1626 first_text_object = | 1649 first_text_object = |
| 1627 BrowserAccessibilityManager::NextTextOnlyObject(first_text_object); | 1650 BrowserAccessibilityManager::NextTextOnlyObject(first_text_object); |
| 1628 } | 1651 } |
| 1629 while (first_text_object) { | 1652 while (first_text_object) { |
| 1630 first_text_object = | 1653 first_text_object = |
| 1631 BrowserAccessibilityManager::NextTextOnlyObject(first_text_object); | 1654 BrowserAccessibilityManager::NextTextOnlyObject(first_text_object); |
| 1632 } | 1655 } |
| 1633 if (!first_text_object) | 1656 if (!first_text_object) |
| 1634 return nil; | 1657 return nil; |
| 1635 | 1658 |
| 1636 return CreateTextMarker(*first_text_object, 0); | 1659 return CreateTextMarker(*first_text_object, 0, ui::AX_TEXT_AFFINITY_UPSTREAM); |
| 1637 } | 1660 } |
| 1638 | 1661 |
| 1639 // Returns a subrole based upon the role. | 1662 // Returns a subrole based upon the role. |
| 1640 - (NSString*) subrole { | 1663 - (NSString*) subrole { |
| 1641 if (![self instanceActive]) | 1664 if (![self instanceActive]) |
| 1642 return nil; | 1665 return nil; |
| 1643 ui::AXRole browserAccessibilityRole = [self internalRole]; | 1666 ui::AXRole browserAccessibilityRole = [self internalRole]; |
| 1644 if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD && | 1667 if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD && |
| 1645 GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) { | 1668 GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) { |
| 1646 return NSAccessibilitySecureTextFieldSubrole; | 1669 return NSAccessibilitySecureTextFieldSubrole; |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2025 if (colIndex > column) | 2048 if (colIndex > column) |
| 2026 break; | 2049 break; |
| 2027 } | 2050 } |
| 2028 } | 2051 } |
| 2029 return nil; | 2052 return nil; |
| 2030 } | 2053 } |
| 2031 | 2054 |
| 2032 if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) { | 2055 if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) { |
| 2033 BrowserAccessibility* object; | 2056 BrowserAccessibility* object; |
| 2034 int offset; | 2057 int offset; |
| 2035 if (GetTextMarkerData(parameter, &object, &offset)) | 2058 ui::AXTextAffinity affinity; |
| 2059 if (GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2036 return ToBrowserAccessibilityCocoa(object); | 2060 return ToBrowserAccessibilityCocoa(object); |
| 2037 | 2061 |
| 2038 return nil; | 2062 return nil; |
| 2039 } | 2063 } |
| 2040 | 2064 |
| 2041 if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) { | 2065 if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) { |
| 2042 return CreateTextMarkerRange(*browserAccessibility_, 0, | 2066 return CreateTextMarkerRange(*browserAccessibility_, 0, |
| 2067 ui::AX_TEXT_AFFINITY_UPSTREAM, |
| 2043 *browserAccessibility_, | 2068 *browserAccessibility_, |
| 2044 browserAccessibility_->GetText().length()); | 2069 browserAccessibility_->GetText().length(), |
| 2070 ui::AX_TEXT_AFFINITY_DOWNSTREAM); |
| 2045 } | 2071 } |
| 2046 | 2072 |
| 2047 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) | 2073 if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) |
| 2048 GetTextForTextMarkerRange(parameter); | 2074 GetTextForTextMarkerRange(parameter); |
| 2049 | 2075 |
| 2050 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) | 2076 if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) |
| 2051 return GetAttributedTextForTextMarkerRange(parameter); | 2077 return GetAttributedTextForTextMarkerRange(parameter); |
| 2052 | 2078 |
| 2053 if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) { | 2079 if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) { |
| 2054 BrowserAccessibility* object; | 2080 BrowserAccessibility* object; |
| 2055 int offset; | 2081 int offset; |
| 2056 if (!GetTextMarkerData(parameter, &object, &offset)) | 2082 ui::AXTextAffinity affinity; |
| 2083 if (!GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2057 return nil; | 2084 return nil; |
| 2058 | 2085 |
| 2059 DCHECK(object); | 2086 DCHECK(object); |
| 2060 if ((object->IsSimpleTextControl() || object->IsTextOnlyObject()) && | 2087 if ((object->IsSimpleTextControl() || object->IsTextOnlyObject()) && |
| 2061 offset < static_cast<int>(object->GetText().length())) { | 2088 offset < static_cast<int>(object->GetText().length())) { |
| 2062 ++offset; | 2089 ++offset; |
| 2063 } else { | 2090 } else { |
| 2064 do { | 2091 do { |
| 2065 object = BrowserAccessibilityManager::NextTextOnlyObject(object); | 2092 object = BrowserAccessibilityManager::NextTextOnlyObject(object); |
| 2066 } while ( | 2093 } while ( |
| 2067 object && | 2094 object && |
| 2068 !(object->IsTextOnlyObject() && object->GetText().length() == 0)); | 2095 !(object->IsTextOnlyObject() && object->GetText().length() == 0)); |
| 2069 if (!object) | 2096 if (!object) |
| 2070 return nil; | 2097 return nil; |
| 2071 | 2098 |
| 2072 offset = 0; | 2099 offset = 0; |
| 2073 } | 2100 } |
| 2074 | 2101 |
| 2075 return CreateTextMarker(*object, offset); | 2102 return CreateTextMarker(*object, offset, ui::AX_TEXT_AFFINITY_DOWNSTREAM); |
| 2076 } | 2103 } |
| 2077 | 2104 |
| 2078 if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) { | 2105 if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) { |
| 2079 BrowserAccessibility* object; | 2106 BrowserAccessibility* object; |
| 2080 int offset; | 2107 int offset; |
| 2081 if (!GetTextMarkerData(parameter, &object, &offset)) | 2108 ui::AXTextAffinity affinity; |
| 2109 if (!GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2082 return nil; | 2110 return nil; |
| 2083 | 2111 |
| 2084 DCHECK(object); | 2112 DCHECK(object); |
| 2085 if ((object->IsSimpleTextControl() || object->IsTextOnlyObject()) && | 2113 if ((object->IsSimpleTextControl() || object->IsTextOnlyObject()) && |
| 2086 offset > 0) { | 2114 offset > 0) { |
| 2087 --offset; | 2115 --offset; |
| 2088 } else { | 2116 } else { |
| 2089 do { | 2117 do { |
| 2090 object = BrowserAccessibilityManager::PreviousTextOnlyObject(object); | 2118 object = BrowserAccessibilityManager::PreviousTextOnlyObject(object); |
| 2091 } while ( | 2119 } while ( |
| 2092 object && | 2120 object && |
| 2093 !(object->IsTextOnlyObject() && object->GetText().length() == 0)); | 2121 !(object->IsTextOnlyObject() && object->GetText().length() == 0)); |
| 2094 if (!object) | 2122 if (!object) |
| 2095 return nil; | 2123 return nil; |
| 2096 | 2124 |
| 2097 offset = object->GetText().length() - 1; | 2125 offset = object->GetText().length() - 1; |
| 2098 } | 2126 } |
| 2099 | 2127 |
| 2100 return CreateTextMarker(*object, offset); | 2128 return CreateTextMarker(*object, offset, ui::AX_TEXT_AFFINITY_DOWNSTREAM); |
| 2101 } | 2129 } |
| 2102 | 2130 |
| 2103 // Currently we approximate end offsets of words and do not actually calculate | 2131 // Currently we approximate end offsets of words and do not actually calculate |
| 2104 // end offsets of lines, but use the start offset of the next line instead. | 2132 // end offsets of lines, but use the start offset of the next line instead. |
| 2105 // This seems to work in simple text fields. | 2133 // This seems to work in simple text fields. |
| 2106 // TODO(nektar): Fix end offsets of words and lines. | 2134 // TODO(nektar): Fix end offsets of words and lines. |
| 2107 if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) { | 2135 if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) { |
| 2108 BrowserAccessibility* object; | 2136 BrowserAccessibility* object; |
| 2109 int original_offset; | 2137 int original_offset; |
| 2110 if (!GetTextMarkerData(parameter, &object, &original_offset)) | 2138 ui::AXTextAffinity affinity; |
| 2139 if (!GetTextMarkerData(parameter, &object, &original_offset, &affinity)) |
| 2111 return nil; | 2140 return nil; |
| 2112 | 2141 |
| 2113 int start_offset = | 2142 int start_offset = |
| 2114 object->GetWordStartBoundary(original_offset, ui::BACKWARDS_DIRECTION); | 2143 object->GetWordStartBoundary(original_offset, ui::BACKWARDS_DIRECTION); |
| 2115 DCHECK_GE(start_offset, 0); | 2144 DCHECK_GE(start_offset, 0); |
| 2116 | 2145 |
| 2117 int end_offset = | 2146 int end_offset = |
| 2118 object->GetWordStartBoundary(start_offset, ui::FORWARDS_DIRECTION); | 2147 object->GetWordStartBoundary(start_offset, ui::FORWARDS_DIRECTION); |
| 2119 DCHECK_GE(end_offset, 0); | 2148 DCHECK_GE(end_offset, 0); |
| 2120 if (start_offset < end_offset && | 2149 if (start_offset < end_offset && |
| 2121 end_offset < static_cast<int>(object->GetText().length())) { | 2150 end_offset < static_cast<int>(object->GetText().length())) { |
| 2122 --end_offset; | 2151 --end_offset; |
| 2123 } | 2152 } |
| 2124 return CreateTextMarkerRange(*object, start_offset, *object, end_offset); | 2153 return CreateTextMarkerRange(*object, start_offset, affinity, |
| 2154 *object, end_offset, affinity); |
| 2125 } | 2155 } |
| 2126 | 2156 |
| 2127 if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) { | 2157 if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) { |
| 2128 BrowserAccessibility* object; | 2158 BrowserAccessibility* object; |
| 2129 int original_offset; | 2159 int original_offset; |
| 2130 if (!GetTextMarkerData(parameter, &object, &original_offset)) | 2160 ui::AXTextAffinity affinity; |
| 2161 if (!GetTextMarkerData(parameter, &object, &original_offset, &affinity)) |
| 2131 return nil; | 2162 return nil; |
| 2132 | 2163 |
| 2133 int start_offset = | 2164 int start_offset = |
| 2134 object->GetWordStartBoundary(original_offset, ui::FORWARDS_DIRECTION); | 2165 object->GetWordStartBoundary(original_offset, ui::FORWARDS_DIRECTION); |
| 2135 DCHECK_GE(start_offset, 0); | 2166 DCHECK_GE(start_offset, 0); |
| 2136 | 2167 |
| 2137 int end_offset = | 2168 int end_offset = |
| 2138 object->GetWordStartBoundary(start_offset, ui::FORWARDS_DIRECTION); | 2169 object->GetWordStartBoundary(start_offset, ui::FORWARDS_DIRECTION); |
| 2139 DCHECK_GE(end_offset, 0); | 2170 DCHECK_GE(end_offset, 0); |
| 2140 if (start_offset < end_offset && | 2171 if (start_offset < end_offset && |
| 2141 end_offset < static_cast<int>(object->GetText().length())) { | 2172 end_offset < static_cast<int>(object->GetText().length())) { |
| 2142 --end_offset; | 2173 --end_offset; |
| 2143 } | 2174 } |
| 2144 return CreateTextMarkerRange(*object, start_offset, *object, end_offset); | 2175 return CreateTextMarkerRange(*object, start_offset, affinity, |
| 2176 *object, end_offset, affinity); |
| 2145 } | 2177 } |
| 2146 | 2178 |
| 2147 if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) { | 2179 if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) { |
| 2148 BrowserAccessibility* object; | 2180 BrowserAccessibility* object; |
| 2149 int offset; | 2181 int offset; |
| 2150 if (!GetTextMarkerData(parameter, &object, &offset)) | 2182 ui::AXTextAffinity affinity; |
| 2183 if (!GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2151 return nil; | 2184 return nil; |
| 2152 | 2185 |
| 2153 offset = object->GetWordStartBoundary(offset, ui::FORWARDS_DIRECTION); | 2186 offset = object->GetWordStartBoundary(offset, ui::FORWARDS_DIRECTION); |
| 2154 DCHECK_GE(offset, 0); | 2187 DCHECK_GE(offset, 0); |
| 2155 if (offset > 0 && offset < static_cast<int>(object->GetText().length())) | 2188 if (offset > 0 && offset < static_cast<int>(object->GetText().length())) |
| 2156 --offset; | 2189 --offset; |
| 2157 return CreateTextMarker(*object, offset); | 2190 return CreateTextMarker(*object, offset, affinity); |
| 2158 } | 2191 } |
| 2159 | 2192 |
| 2160 if ([attribute | 2193 if ([attribute |
| 2161 isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) { | 2194 isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) { |
| 2162 BrowserAccessibility* object; | 2195 BrowserAccessibility* object; |
| 2163 int offset; | 2196 int offset; |
| 2164 if (!GetTextMarkerData(parameter, &object, &offset)) | 2197 ui::AXTextAffinity affinity; |
| 2198 if (!GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2165 return nil; | 2199 return nil; |
| 2166 | 2200 |
| 2167 offset = object->GetWordStartBoundary(offset, ui::BACKWARDS_DIRECTION); | 2201 offset = object->GetWordStartBoundary(offset, ui::BACKWARDS_DIRECTION); |
| 2168 DCHECK_GE(offset, 0); | 2202 DCHECK_GE(offset, 0); |
| 2169 return CreateTextMarker(*object, offset); | 2203 return CreateTextMarker(*object, offset, affinity); |
| 2170 } | 2204 } |
| 2171 | 2205 |
| 2172 if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) { | 2206 if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) { |
| 2173 BrowserAccessibility* object; | 2207 BrowserAccessibility* object; |
| 2174 int offset; | 2208 int offset; |
| 2175 if (!GetTextMarkerData(parameter, &object, &offset)) | 2209 ui::AXTextAffinity affinity; |
| 2210 if (!GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2176 return nil; | 2211 return nil; |
| 2177 | 2212 |
| 2178 offset = object->GetLineStartBoundary(offset, ui::FORWARDS_DIRECTION); | 2213 offset = object->GetLineStartBoundary( |
| 2214 offset, ui::FORWARDS_DIRECTION, affinity); |
| 2179 DCHECK_GE(offset, 0); | 2215 DCHECK_GE(offset, 0); |
| 2180 return CreateTextMarker(*object, offset); | 2216 return CreateTextMarker(*object, offset, affinity); |
| 2181 } | 2217 } |
| 2182 | 2218 |
| 2183 if ([attribute | 2219 if ([attribute |
| 2184 isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) { | 2220 isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) { |
| 2185 BrowserAccessibility* object; | 2221 BrowserAccessibility* object; |
| 2186 int offset; | 2222 int offset; |
| 2187 if (!GetTextMarkerData(parameter, &object, &offset)) | 2223 ui::AXTextAffinity affinity; |
| 2224 if (!GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2188 return nil; | 2225 return nil; |
| 2189 | 2226 |
| 2190 offset = object->GetLineStartBoundary(offset, ui::BACKWARDS_DIRECTION); | 2227 offset = object->GetLineStartBoundary( |
| 2228 offset, ui::BACKWARDS_DIRECTION, affinity); |
| 2191 DCHECK_GE(offset, 0); | 2229 DCHECK_GE(offset, 0); |
| 2192 return CreateTextMarker(*object, offset); | 2230 return CreateTextMarker(*object, offset, affinity); |
| 2193 } | 2231 } |
| 2194 | 2232 |
| 2195 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) { | 2233 if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) { |
| 2196 NSString* text = GetTextForTextMarkerRange(parameter); | 2234 NSString* text = GetTextForTextMarkerRange(parameter); |
| 2197 return [NSNumber numberWithInt:[text length]]; | 2235 return [NSNumber numberWithInt:[text length]]; |
| 2198 } | 2236 } |
| 2199 | 2237 |
| 2200 if ([attribute isEqualToString: | 2238 if ([attribute isEqualToString: |
| 2201 NSAccessibilityBoundsForRangeParameterizedAttribute]) { | 2239 NSAccessibilityBoundsForRangeParameterizedAttribute]) { |
| 2202 if ([self internalRole] != ui::AX_ROLE_STATIC_TEXT) | 2240 if ([self internalRole] != ui::AX_ROLE_STATIC_TEXT) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2231 return result; | 2269 return result; |
| 2232 } | 2270 } |
| 2233 return nil; | 2271 return nil; |
| 2234 } | 2272 } |
| 2235 | 2273 |
| 2236 if ([attribute | 2274 if ([attribute |
| 2237 isEqualToString: | 2275 isEqualToString: |
| 2238 NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttrib
ute]) { | 2276 NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttrib
ute]) { |
| 2239 BrowserAccessibility* object; | 2277 BrowserAccessibility* object; |
| 2240 int offset; | 2278 int offset; |
| 2241 if (!GetTextMarkerData(parameter, &object, &offset)) | 2279 ui::AXTextAffinity affinity; |
| 2280 if (!GetTextMarkerData(parameter, &object, &offset, &affinity)) |
| 2242 return nil; | 2281 return nil; |
| 2243 | 2282 |
| 2244 DCHECK(object); | 2283 DCHECK(object); |
| 2245 int start_offset = | 2284 int start_offset = |
| 2246 object->GetLineStartBoundary(offset, ui::BACKWARDS_DIRECTION); | 2285 object->GetLineStartBoundary(offset, ui::BACKWARDS_DIRECTION, affinity); |
| 2247 int end_offset = | 2286 int end_offset = |
| 2248 object->GetLineStartBoundary(offset, ui::FORWARDS_DIRECTION); | 2287 object->GetLineStartBoundary(offset, ui::FORWARDS_DIRECTION, affinity); |
| 2249 return CreateTextMarkerRange(*object, start_offset, *object, end_offset); | 2288 return CreateTextMarkerRange( |
| 2289 *object, start_offset, ui::AX_TEXT_AFFINITY_UPSTREAM, |
| 2290 *object, end_offset, ui::AX_TEXT_AFFINITY_DOWNSTREAM); |
| 2250 } | 2291 } |
| 2251 | 2292 |
| 2252 return nil; | 2293 return nil; |
| 2253 } | 2294 } |
| 2254 | 2295 |
| 2255 // Returns an array of parameterized attributes names that this object will | 2296 // Returns an array of parameterized attributes names that this object will |
| 2256 // respond to. | 2297 // respond to. |
| 2257 - (NSArray*)accessibilityParameterizedAttributeNames { | 2298 - (NSArray*)accessibilityParameterizedAttributeNames { |
| 2258 if (![self instanceActive]) | 2299 if (![self instanceActive]) |
| 2259 return nil; | 2300 return nil; |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2715 if (![self instanceActive]) | 2756 if (![self instanceActive]) |
| 2716 return [super hash]; | 2757 return [super hash]; |
| 2717 return browserAccessibility_->GetId(); | 2758 return browserAccessibility_->GetId(); |
| 2718 } | 2759 } |
| 2719 | 2760 |
| 2720 - (BOOL)accessibilityShouldUseUniqueId { | 2761 - (BOOL)accessibilityShouldUseUniqueId { |
| 2721 return YES; | 2762 return YES; |
| 2722 } | 2763 } |
| 2723 | 2764 |
| 2724 @end | 2765 @end |
| OLD | NEW |