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

Side by Side Diff: content/browser/accessibility/browser_accessibility_cocoa.mm

Issue 2191833003: Use text affinity to return correct accessible line boundaries. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix bug in browser_accessibility_win.cc Created 4 years, 4 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 <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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698