Index: content/browser/accessibility/browser_accessibility.cc |
=================================================================== |
--- content/browser/accessibility/browser_accessibility.cc (revision 112818) |
+++ content/browser/accessibility/browser_accessibility.cc (working copy) |
@@ -163,6 +163,92 @@ |
return this; |
} |
+void BrowserAccessibility::ScrollToMakeVisible(const gfx::Rect& subfocus, |
+ const gfx::Rect& focus, |
+ const gfx::Rect& viewport) { |
+ int scroll_x = 0; |
+ int scroll_x_min = 0; |
+ int scroll_x_max = 0; |
+ int scroll_y = 0; |
+ int scroll_y_min = 0; |
+ int scroll_y_max = 0; |
+ if (!GetIntAttribute(WebAccessibility::ATTR_SCROLL_X, &scroll_x) || |
+ !GetIntAttribute(WebAccessibility::ATTR_SCROLL_X_MIN, &scroll_x_min) || |
+ !GetIntAttribute(WebAccessibility::ATTR_SCROLL_X_MAX, &scroll_x_max) || |
+ !GetIntAttribute(WebAccessibility::ATTR_SCROLL_Y, &scroll_y) || |
+ !GetIntAttribute(WebAccessibility::ATTR_SCROLL_Y_MIN, &scroll_y_min) || |
+ !GetIntAttribute(WebAccessibility::ATTR_SCROLL_Y_MAX, &scroll_y_max)) { |
+ return; |
+ } |
+ |
+ gfx::Rect final_viewport(0, 0, location_.width(), location_.height()); |
+ final_viewport.Intersect(viewport); |
+ |
+ int new_scroll_x = ComputeBestScrollOffset( |
+ scroll_x, |
+ subfocus.x(), subfocus.right(), |
+ focus.x(), focus.right(), |
+ final_viewport.x(), final_viewport.right()); |
+ new_scroll_x = std::max(new_scroll_x, scroll_x_min); |
+ new_scroll_x = std::min(new_scroll_x, scroll_x_max); |
+ |
+ int new_scroll_y = ComputeBestScrollOffset( |
+ scroll_y, |
+ subfocus.y(), subfocus.bottom(), |
+ focus.y(), focus.bottom(), |
+ final_viewport.y(), final_viewport.bottom()); |
+ new_scroll_y = std::max(new_scroll_y, scroll_y_min); |
+ new_scroll_y = std::min(new_scroll_y, scroll_y_max); |
+ |
+ manager_->ChangeScrollPosition(*this, new_scroll_x, new_scroll_y); |
+} |
+ |
+// static |
+int BrowserAccessibility::ComputeBestScrollOffset( |
+ int current_scroll_offset, |
+ int subfocus_min, int subfocus_max, |
+ int focus_min, int focus_max, |
+ int viewport_min, int viewport_max) { |
+ int viewport_size = viewport_max - viewport_min; |
+ |
+ // If the focus size is larger than the viewport size, shrink it in the |
+ // direction of subfocus. |
+ if (focus_max - focus_min > viewport_size) { |
+ // Subfocus must be within focus: |
+ subfocus_min = std::max(subfocus_min, focus_min); |
+ subfocus_max = std::min(subfocus_max, focus_max); |
+ |
+ // Subfocus must be no larger than the viewport size; favor top/left. |
+ if (subfocus_max - subfocus_min > viewport_size) |
+ subfocus_max = subfocus_min + viewport_size; |
+ |
+ if (subfocus_min + viewport_size > focus_max) { |
+ focus_min = focus_max - viewport_size; |
+ } else { |
+ focus_min = subfocus_min; |
+ focus_max = subfocus_min + viewport_size; |
+ } |
+ } |
+ |
+ // Exit now if the focus is already within the viewport. |
+ if (focus_min - current_scroll_offset >= viewport_min && |
+ focus_max - current_scroll_offset <= viewport_max) { |
+ return current_scroll_offset; |
+ } |
+ |
+ // Scroll left if we're too far to the right. |
+ if (focus_max - current_scroll_offset > viewport_max) |
+ return focus_max - viewport_max; |
+ |
+ // Scroll right if we're too far to the left. |
+ if (focus_min - current_scroll_offset < viewport_min) |
+ return focus_min - viewport_min; |
+ |
+ // This shouldn't happen. |
+ NOTREACHED(); |
+ return current_scroll_offset; |
+} |
+ |
void BrowserAccessibility::InternalAddReference() { |
ref_count_++; |
} |