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

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

Issue 2217363002: Use relative bounding boxes throughout Chrome accessibility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback from aboxhall 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 "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 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 } 332 }
333 333
334 const ui::AXNodeData& BrowserAccessibility::GetData() const { 334 const ui::AXNodeData& BrowserAccessibility::GetData() const {
335 CR_DEFINE_STATIC_LOCAL(ui::AXNodeData, empty_data, ()); 335 CR_DEFINE_STATIC_LOCAL(ui::AXNodeData, empty_data, ());
336 if (node_) 336 if (node_)
337 return node_->data(); 337 return node_->data();
338 else 338 else
339 return empty_data; 339 return empty_data;
340 } 340 }
341 341
342 gfx::Rect BrowserAccessibility::GetLocation() const { 342 gfx::RectF BrowserAccessibility::GetLocation() const {
343 return gfx::ToEnclosingRect(GetData().location); 343 return GetData().location;
344 } 344 }
345 345
346 int32_t BrowserAccessibility::GetRole() const { 346 int32_t BrowserAccessibility::GetRole() const {
347 return GetData().role; 347 return GetData().role;
348 } 348 }
349 349
350 int32_t BrowserAccessibility::GetState() const { 350 int32_t BrowserAccessibility::GetState() const {
351 return GetData().state; 351 return GetData().state;
352 } 352 }
353 353
354 const BrowserAccessibility::HtmlAttributes& 354 const BrowserAccessibility::HtmlAttributes&
355 BrowserAccessibility::GetHtmlAttributes() const { 355 BrowserAccessibility::GetHtmlAttributes() const {
356 return GetData().html_attributes; 356 return GetData().html_attributes;
357 } 357 }
358 358
359 gfx::Rect BrowserAccessibility::GetLocalBoundsRect() const { 359 gfx::Rect BrowserAccessibility::GetFrameBoundsRect() const {
360 gfx::Rect bounds = GetLocation(); 360 gfx::RectF bounds = GetLocation();
361 FixEmptyBounds(&bounds); 361 FixEmptyBounds(&bounds);
362 return ElementBoundsToLocalBounds(bounds); 362 return RelativeToAbsoluteBounds(bounds, true);
363 } 363 }
364 364
365 gfx::Rect BrowserAccessibility::GetGlobalBoundsRect() const { 365 gfx::Rect BrowserAccessibility::GetPageBoundsRect() const {
366 gfx::Rect bounds = GetLocalBoundsRect(); 366 gfx::RectF bounds = GetLocation();
367 FixEmptyBounds(&bounds);
368 return RelativeToAbsoluteBounds(bounds, false);
369 }
370
371 gfx::Rect BrowserAccessibility::GetScreenBoundsRect() const {
372 gfx::Rect bounds = GetPageBoundsRect();
367 373
368 // Adjust the bounds by the top left corner of the containing view's bounds 374 // Adjust the bounds by the top left corner of the containing view's bounds
369 // in screen coordinates. 375 // in screen coordinates.
370 bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin()); 376 bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin());
371 377
372 return bounds; 378 return bounds;
373 } 379 }
374 380
375 gfx::Rect BrowserAccessibility::GetLocalBoundsForRange(int start, int len) 381 gfx::Rect BrowserAccessibility::GetPageBoundsForRange(int start, int len)
376 const { 382 const {
377 DCHECK_GE(start, 0); 383 DCHECK_GE(start, 0);
378 DCHECK_GE(len, 0); 384 DCHECK_GE(len, 0);
379 385
380 // Standard text fields such as textarea have an embedded div inside them that 386 // Standard text fields such as textarea have an embedded div inside them that
381 // holds all the text. 387 // holds all the text.
382 // TODO(nektar): This is fragile! Replace with code that flattens tree. 388 // TODO(nektar): This is fragile! Replace with code that flattens tree.
383 if (IsSimpleTextControl() && InternalChildCount() == 1) 389 if (IsSimpleTextControl() && InternalChildCount() == 1)
384 return InternalGetChild(0)->GetLocalBoundsForRange(start, len); 390 return InternalGetChild(0)->GetPageBoundsForRange(start, len);
385 391
386 if (GetRole() != ui::AX_ROLE_STATIC_TEXT) { 392 if (GetRole() != ui::AX_ROLE_STATIC_TEXT) {
387 gfx::Rect bounds; 393 gfx::Rect bounds;
388 for (size_t i = 0; i < InternalChildCount() && len > 0; ++i) { 394 for (size_t i = 0; i < InternalChildCount() && len > 0; ++i) {
389 BrowserAccessibility* child = InternalGetChild(i); 395 BrowserAccessibility* child = InternalGetChild(i);
390 // Child objects are of length one, since they are represented by a single 396 // Child objects are of length one, since they are represented by a single
391 // embedded object character. The exception is text-only objects. 397 // embedded object character. The exception is text-only objects.
392 int child_length_in_parent = 1; 398 int child_length_in_parent = 1;
393 if (child->IsTextOnlyObject()) 399 if (child->IsTextOnlyObject())
394 child_length_in_parent = static_cast<int>(child->GetText().size()); 400 child_length_in_parent = static_cast<int>(child->GetText().size());
395 if (start < child_length_in_parent) { 401 if (start < child_length_in_parent) {
396 gfx::Rect child_rect; 402 gfx::Rect child_rect;
397 if (child->IsTextOnlyObject()) { 403 if (child->IsTextOnlyObject()) {
398 child_rect = child->GetLocalBoundsForRange(start, len); 404 child_rect = child->GetPageBoundsForRange(start, len);
399 } else { 405 } else {
400 child_rect = child->GetLocalBoundsForRange( 406 child_rect = child->GetPageBoundsForRange(
401 0, static_cast<int>(child->GetText().size())); 407 0, static_cast<int>(child->GetText().size()));
402 } 408 }
403 bounds.Union(child_rect); 409 bounds.Union(child_rect);
404 len -= (child_length_in_parent - start); 410 len -= (child_length_in_parent - start);
405 } 411 }
406 if (start > child_length_in_parent) 412 if (start > child_length_in_parent)
407 start -= child_length_in_parent; 413 start -= child_length_in_parent;
408 else 414 else
409 start = 0; 415 start = 0;
410 } 416 }
411 return ElementBoundsToLocalBounds(bounds); 417 return RelativeToAbsoluteBounds(gfx::RectF(bounds), false);
412 } 418 }
413 419
414 int end = start + len; 420 int end = start + len;
415 int child_start = 0; 421 int child_start = 0;
416 int child_end = 0; 422 int child_end = 0;
417 gfx::Rect bounds; 423 gfx::Rect bounds;
418 for (size_t i = 0; i < InternalChildCount() && child_end < start + len; ++i) { 424 for (size_t i = 0; i < InternalChildCount() && child_end < start + len; ++i) {
419 BrowserAccessibility* child = InternalGetChild(i); 425 BrowserAccessibility* child = InternalGetChild(i);
420 if (child->GetRole() != ui::AX_ROLE_INLINE_TEXT_BOX) { 426 if (child->GetRole() != ui::AX_ROLE_INLINE_TEXT_BOX) {
421 DLOG(WARNING) << "BrowserAccessibility objects with role STATIC_TEXT " << 427 DLOG(WARNING) << "BrowserAccessibility objects with role STATIC_TEXT " <<
(...skipping 22 matching lines...) Expand all
444 450
445 const std::vector<int32_t>& character_offsets = 451 const std::vector<int32_t>& character_offsets =
446 child->GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS); 452 child->GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS);
447 if (static_cast<int>(character_offsets.size()) != child_length) 453 if (static_cast<int>(character_offsets.size()) != child_length)
448 continue; 454 continue;
449 int start_pixel_offset = 455 int start_pixel_offset =
450 local_start > 0 ? character_offsets[local_start - 1] : 0; 456 local_start > 0 ? character_offsets[local_start - 1] : 0;
451 int end_pixel_offset = 457 int end_pixel_offset =
452 local_end > 0 ? character_offsets[local_end - 1] : 0; 458 local_end > 0 ? character_offsets[local_end - 1] : 0;
453 459
454 gfx::Rect child_rect = child->GetLocation(); 460 gfx::Rect child_rect = gfx::ToEnclosingRect(child->GetLocation());
455 auto text_direction = static_cast<ui::AXTextDirection>( 461 auto text_direction = static_cast<ui::AXTextDirection>(
456 child->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION)); 462 child->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION));
457 gfx::Rect child_overlap_rect; 463 gfx::Rect child_overlap_rect;
458 switch (text_direction) { 464 switch (text_direction) {
459 case ui::AX_TEXT_DIRECTION_NONE: 465 case ui::AX_TEXT_DIRECTION_NONE:
460 case ui::AX_TEXT_DIRECTION_LTR: { 466 case ui::AX_TEXT_DIRECTION_LTR: {
461 int left = child_rect.x() + start_pixel_offset; 467 int left = child_rect.x() + start_pixel_offset;
462 int right = child_rect.x() + end_pixel_offset; 468 int right = child_rect.x() + end_pixel_offset;
463 child_overlap_rect = gfx::Rect(left, child_rect.y(), 469 child_overlap_rect = gfx::Rect(left, child_rect.y(),
464 right - left, child_rect.height()); 470 right - left, child_rect.height());
(...skipping 23 matching lines...) Expand all
488 default: 494 default:
489 NOTREACHED(); 495 NOTREACHED();
490 } 496 }
491 497
492 if (bounds.width() == 0 && bounds.height() == 0) 498 if (bounds.width() == 0 && bounds.height() == 0)
493 bounds = child_overlap_rect; 499 bounds = child_overlap_rect;
494 else 500 else
495 bounds.Union(child_overlap_rect); 501 bounds.Union(child_overlap_rect);
496 } 502 }
497 503
498 return ElementBoundsToLocalBounds(bounds); 504 return RelativeToAbsoluteBounds(gfx::RectF(bounds), false);
499 } 505 }
500 506
501 gfx::Rect BrowserAccessibility::GetGlobalBoundsForRange(int start, int len) 507 gfx::Rect BrowserAccessibility::GetScreenBoundsForRange(int start, int len)
502 const { 508 const {
503 gfx::Rect bounds = GetLocalBoundsForRange(start, len); 509 gfx::Rect bounds = GetPageBoundsForRange(start, len);
504 510
505 // Adjust the bounds by the top left corner of the containing view's bounds 511 // Adjust the bounds by the top left corner of the containing view's bounds
506 // in screen coordinates. 512 // in screen coordinates.
507 bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin()); 513 bounds.Offset(manager_->GetViewBounds().OffsetFromOrigin());
508 514
509 return bounds; 515 return bounds;
510 } 516 }
511 517
512 base::string16 BrowserAccessibility::GetValue() const { 518 base::string16 BrowserAccessibility::GetValue() const {
513 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); 519 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE);
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 // the absence of any other information, we assume the object that occurs 730 // the absence of any other information, we assume the object that occurs
725 // later in the tree is on top of one that comes before it. 731 // later in the tree is on top of one that comes before it.
726 for (int i = static_cast<int>(PlatformChildCount()) - 1; i >= 0; --i) { 732 for (int i = static_cast<int>(PlatformChildCount()) - 1; i >= 0; --i) {
727 BrowserAccessibility* child = PlatformGetChild(i); 733 BrowserAccessibility* child = PlatformGetChild(i);
728 734
729 // Skip table columns because cells are only contained in rows, 735 // Skip table columns because cells are only contained in rows,
730 // not columns. 736 // not columns.
731 if (child->GetRole() == ui::AX_ROLE_COLUMN) 737 if (child->GetRole() == ui::AX_ROLE_COLUMN)
732 continue; 738 continue;
733 739
734 if (child->GetGlobalBoundsRect().Contains(point)) { 740 if (child->GetScreenBoundsRect().Contains(point)) {
735 BrowserAccessibility* result = child->BrowserAccessibilityForPoint(point); 741 BrowserAccessibility* result = child->BrowserAccessibilityForPoint(point);
736 if (result == child && !child_result) 742 if (result == child && !child_result)
737 child_result = result; 743 child_result = result;
738 if (result != child && !descendant_result) 744 if (result != child && !descendant_result)
739 descendant_result = result; 745 descendant_result = result;
740 } 746 }
741 747
742 if (child_result && descendant_result) 748 if (child_result && descendant_result)
743 break; 749 break;
744 } 750 }
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 base::string16 BrowserAccessibility::GetInnerText() const { 1145 base::string16 BrowserAccessibility::GetInnerText() const {
1140 if (IsTextOnlyObject()) 1146 if (IsTextOnlyObject())
1141 return GetString16Attribute(ui::AX_ATTR_NAME); 1147 return GetString16Attribute(ui::AX_ATTR_NAME);
1142 1148
1143 base::string16 text; 1149 base::string16 text;
1144 for (size_t i = 0; i < InternalChildCount(); ++i) 1150 for (size_t i = 0; i < InternalChildCount(); ++i)
1145 text += InternalGetChild(i)->GetInnerText(); 1151 text += InternalGetChild(i)->GetInnerText();
1146 return text; 1152 return text;
1147 } 1153 }
1148 1154
1149 void BrowserAccessibility::FixEmptyBounds(gfx::Rect* bounds) const 1155 void BrowserAccessibility::FixEmptyBounds(gfx::RectF* bounds) const
1150 { 1156 {
1151 if (bounds->width() > 0 && bounds->height() > 0) 1157 if (bounds->width() > 0 && bounds->height() > 0)
1152 return; 1158 return;
1153 1159
1154 for (size_t i = 0; i < InternalChildCount(); ++i) { 1160 for (size_t i = 0; i < InternalChildCount(); ++i) {
1155 // Compute the bounds of each child - this calls FixEmptyBounds 1161 // Compute the bounds of each child - this calls FixEmptyBounds
1156 // recursively if necessary. 1162 // recursively if necessary.
1157 BrowserAccessibility* child = InternalGetChild(i); 1163 BrowserAccessibility* child = InternalGetChild(i);
1158 gfx::Rect child_bounds = child->GetLocalBoundsRect(); 1164 gfx::Rect child_bounds = child->GetPageBoundsRect();
1159 1165
1160 // Ignore children that don't have valid bounds themselves. 1166 // Ignore children that don't have valid bounds themselves.
1161 if (child_bounds.width() == 0 || child_bounds.height() == 0) 1167 if (child_bounds.width() == 0 || child_bounds.height() == 0)
1162 continue; 1168 continue;
1163 1169
1164 // For the first valid child, just set the bounds to that child's bounds. 1170 // For the first valid child, just set the bounds to that child's bounds.
1165 if (bounds->width() == 0 || bounds->height() == 0) { 1171 if (bounds->width() == 0 || bounds->height() == 0) {
1166 *bounds = child_bounds; 1172 *bounds = gfx::RectF(child_bounds);
1167 continue; 1173 continue;
1168 } 1174 }
1169 1175
1170 // Union each additional child's bounds. 1176 // Union each additional child's bounds.
1171 bounds->Union(child_bounds); 1177 bounds->Union(gfx::RectF(child_bounds));
1172 } 1178 }
1173 } 1179 }
1174 1180
1175 gfx::Rect BrowserAccessibility::ElementBoundsToLocalBounds(gfx::Rect bounds) 1181 gfx::Rect BrowserAccessibility::RelativeToAbsoluteBounds(
1176 const { 1182 gfx::RectF bounds,
1177 BrowserAccessibilityManager* manager = this->manager(); 1183 bool frame_only) const {
1178 BrowserAccessibility* root = manager->GetRoot(); 1184 const BrowserAccessibility* node = this;
1179 while (manager && root) { 1185 while (node) {
1180 // Apply scroll offsets. 1186 if (node->GetData().transform)
1181 if (root != this && (root->GetParent() || 1187 node->GetData().transform->TransformRect(&bounds);
1182 manager->UseRootScrollOffsetsWhenComputingBounds())) { 1188
1189 const BrowserAccessibility* container =
1190 node->manager()->GetFromID(node->GetData().offset_container_id);
1191 if (!container) {
1192 if (node == node->manager()->GetRoot() && !frame_only) {
1193 container = node->GetParent();
1194 } else {
1195 container = node->manager()->GetRoot();
1196 }
1197 }
1198
1199 if (!container || container == node)
1200 break;
1201
1202 gfx::RectF container_bounds = container->GetLocation();
1203 bounds.Offset(container_bounds.x(), container_bounds.y());
1204
1205 if (container->manager()->UseRootScrollOffsetsWhenComputingBounds() ||
1206 container->GetParent()) {
1183 int sx = 0; 1207 int sx = 0;
1184 int sy = 0; 1208 int sy = 0;
1185 if (root->GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && 1209 if (container->GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) &&
1186 root->GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { 1210 container->GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) {
1187 bounds.Offset(-sx, -sy); 1211 bounds.Offset(-sx, -sy);
1188 } 1212 }
1189 } 1213 }
1190 1214
1191 // If the parent accessibility tree is in a different site instance, 1215 node = container;
1192 // ask the delegate to transform our coordinates into the root
1193 // coordinate space and then we're done.
1194 if (manager->delegate() &&
1195 root->GetParent() &&
1196 root->GetParent()->manager()->delegate()) {
1197 BrowserAccessibilityManager* parent_manager =
1198 root->GetParent()->manager();
1199 if (manager->delegate()->AccessibilityGetSiteInstance() !=
1200 parent_manager->delegate()->AccessibilityGetSiteInstance()) {
1201 return manager->delegate()->AccessibilityTransformToRootCoordSpace(
1202 bounds);
1203 }
1204 }
1205
1206 // Otherwise, apply the transform from this frame into the coordinate
1207 // space of its parent frame.
1208 if (root->GetData().transform) {
1209 gfx::RectF boundsf(bounds);
1210 root->GetData().transform->TransformRect(&boundsf);
1211 bounds = gfx::Rect(boundsf.x(), boundsf.y(),
1212 boundsf.width(), boundsf.height());
1213 }
1214
1215 if (!root->GetParent())
1216 break;
1217
1218 manager = root->GetParent()->manager();
1219 root = manager->GetRoot();
1220 } 1216 }
1221 1217
1222 return bounds; 1218 return gfx::ToEnclosingRect(bounds);
1223 } 1219 }
1224 1220
1225 } // namespace content 1221 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/accessibility/browser_accessibility.h ('k') | content/browser/accessibility/browser_accessibility_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698