summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
Diffstat (limited to 'content')
-rw-r--r--content/browser/accessibility/browser_accessibility.cc86
-rw-r--r--content/browser/accessibility/browser_accessibility.h47
-rw-r--r--content/browser/accessibility/browser_accessibility_win.cc158
-rw-r--r--content/browser/accessibility/browser_accessibility_win.h62
4 files changed, 318 insertions, 35 deletions
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 9bed3ac..d365628 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -163,6 +163,92 @@ BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
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_++;
}
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 5b86072..b07518b 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -108,6 +108,53 @@ class CONTENT_EXPORT BrowserAccessibility {
// (in global screen coordinates).
BrowserAccessibility* BrowserAccessibilityForPoint(const gfx::Point& point);
+ // Scrolls this element so that the |focus| rect (in local coordinates
+ // relative to this element) is scrolled to fit within the given
+ // |viewport| (which is clipped to the actual bounds of this
+ // object if you specify something larger). If the whole focus area
+ // doesn't fit, you can specify |subfocus|, which will prioritize
+ // a smaller area within |focus|.
+ //
+ // Note that "focus" doesn't necessarily mean the rectangle must correspond
+ // to a focused element on the page; assistive technology might request
+ // that any object be made visible.
+ void ScrollToMakeVisible(const gfx::Rect& subfocus,
+ const gfx::Rect& focus,
+ const gfx::Rect& viewport);
+
+ // This is a 1-dimensional scroll offset helper function that's applied
+ // separately in the horizontal and vertical directions, because the
+ // logic is the same. The goal is to compute the best scroll offset
+ // in order to make a focused item visible within a viewport.
+ //
+ // In case the whole focused item cannot fit, you can specify a
+ // subfocus - a smaller region within the focus that should
+ // be prioritized. If the whole focused item can fit, the subfocus is
+ // ignored.
+ //
+ // Example: the viewport is scrolled to the right just enough
+ // that the focus is in view.
+ // Before:
+ // +----------Viewport---------+
+ // +----Focus---+
+ // +--SubFocus--+
+ //
+ // After:
+ // +----------Viewport---------+
+ // +----Focus---+
+ // +--SubFocus--+
+ //
+ // When constraints cannot be fully satisfied, the min
+ // (left/top) position takes precedence over the max (right/bottom).
+ //
+ // Note that the return value represents the ideal new scroll offset.
+ // This may be out of range - the calling function should clip this
+ // to the available range.
+ static int ComputeBestScrollOffset(int current_scroll_offset,
+ int subfocus_min, int subfocus_max,
+ int focus_min, int focus_max,
+ int viewport_min, int viewport_max);
+
//
// Reference counting
//
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc
index 5ffacd4..4e88ac0 100644
--- a/content/browser/accessibility/browser_accessibility_win.cc
+++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -4,6 +4,8 @@
#include "content/browser/accessibility/browser_accessibility_win.h"
+#include <limits>
+
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
@@ -726,6 +728,90 @@ STDMETHODIMP BrowserAccessibilityWin::get_relations(
return S_OK;
}
+STDMETHODIMP BrowserAccessibilityWin::scrollTo(enum IA2ScrollType scroll_type) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ // TODO(dmazzoni): Extend this to scroll every scrollable element as
+ // needed, not just the root.
+ BrowserAccessibility* root = this;
+ while (root->parent())
+ root = root->parent();
+
+ gfx::Rect r = location_;
+ gfx::Rect view(std::numeric_limits<int>::min(),
+ std::numeric_limits<int>::min(),
+ std::numeric_limits<int>::max(),
+ std::numeric_limits<int>::max());
+ switch(scroll_type) {
+ case IA2_SCROLL_TYPE_TOP_LEFT:
+ root->ScrollToMakeVisible(
+ gfx::Rect(r.x(), r.y(), 0, 0), r, view);
+ break;
+ case IA2_SCROLL_TYPE_BOTTOM_RIGHT:
+ root->ScrollToMakeVisible(
+ gfx::Rect(r.right(), r.bottom(), 0, 0), r, view);
+ break;
+ case IA2_SCROLL_TYPE_TOP_EDGE:
+ root->ScrollToMakeVisible(
+ gfx::Rect(r.x(), r.y(), r.width(), 0), r, view);
+ break;
+ case IA2_SCROLL_TYPE_BOTTOM_EDGE:
+ root->ScrollToMakeVisible(
+ gfx::Rect(r.x(), r.bottom(), r.width(), 0), r, view);
+ break;
+ case IA2_SCROLL_TYPE_LEFT_EDGE:
+ root->ScrollToMakeVisible(
+ gfx::Rect(r.x(), r.y(), 0, r.height()), r, view);
+ break;
+ case IA2_SCROLL_TYPE_RIGHT_EDGE:
+ root->ScrollToMakeVisible(
+ gfx::Rect(r.right(), r.y(), 0, r.height()), r, view);
+ break;
+ case IA2_SCROLL_TYPE_ANYWHERE:
+ default:
+ root->ScrollToMakeVisible(r, r, view);
+ break;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::scrollToPoint(
+ enum IA2CoordinateType coordinate_type,
+ LONG x,
+ LONG y) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ // TODO(dmazzoni): Extend this to scroll every scrollable element as
+ // needed, not just the root.
+ BrowserAccessibility* root = this;
+ while (root->parent())
+ root = root->parent();
+
+ if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
+ gfx::Point top_left = manager_->GetViewBounds().origin();
+ x -= top_left.x();
+ y -= top_left.y();
+ } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
+ if (parent_) {
+ gfx::Rect parent_bounds = parent_->location();
+ x += parent_bounds.x();
+ y += parent_bounds.y();
+ }
+ } else {
+ return E_INVALIDARG;
+ }
+
+ gfx::Rect r = location_;
+ root->ScrollToMakeVisible(gfx::Rect(r.x(), r.y(), 0, 0),
+ r,
+ gfx::Rect(x, y, 0, 0));
+
+ return S_OK;
+}
+
STDMETHODIMP BrowserAccessibilityWin::get_groupPosition(
LONG* group_level,
LONG* similar_items_in_group,
@@ -1918,6 +2004,74 @@ STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint(
return S_OK;
}
+STDMETHODIMP BrowserAccessibilityWin::scrollSubstringTo(
+ LONG start_index,
+ LONG end_index,
+ enum IA2ScrollType scroll_type) {
+ // TODO(dmazzoni): adjust this for the start and end index, too.
+ return scrollTo(scroll_type);
+}
+
+STDMETHODIMP BrowserAccessibilityWin::scrollSubstringToPoint(
+ LONG start_index,
+ LONG end_index,
+ enum IA2CoordinateType coordinate_type,
+ LONG x, LONG y) {
+ // TODO(dmazzoni): adjust this for the start and end index, too.
+ return scrollToPoint(coordinate_type, x, y);
+}
+
+STDMETHODIMP BrowserAccessibilityWin::addSelection(
+ LONG start_offset, LONG end_offset) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ const string16& text_str = TextForIAccessibleText();
+ HandleSpecialTextOffset(text_str, &start_offset);
+ HandleSpecialTextOffset(text_str, &end_offset);
+
+ manager_->SetTextSelection(*this, start_offset, end_offset);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::removeSelection(LONG selection_index) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (selection_index != 0)
+ return E_INVALIDARG;
+
+ manager_->SetTextSelection(*this, 0, 0);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::setCaretOffset(LONG offset) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ const string16& text_str = TextForIAccessibleText();
+ HandleSpecialTextOffset(text_str, &offset);
+ manager_->SetTextSelection(*this, offset, offset);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibilityWin::setSelection(LONG selection_index,
+ LONG start_offset,
+ LONG end_offset) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (selection_index != 0)
+ return E_INVALIDARG;
+
+ const string16& text_str = TextForIAccessibleText();
+ HandleSpecialTextOffset(text_str, &start_offset);
+ HandleSpecialTextOffset(text_str, &end_offset);
+
+ manager_->SetTextSelection(*this, start_offset, end_offset);
+ return S_OK;
+}
+
//
// IAccessibleValue methods.
//
@@ -2180,7 +2334,9 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties(
}
STDMETHODIMP BrowserAccessibilityWin::scrollTo(boolean placeTopLeft) {
- return E_NOTIMPL;
+ return scrollTo(placeTopLeft ?
+ IA2_SCROLL_TYPE_TOP_LEFT :
+ IA2_SCROLL_TYPE_ANYWHERE);
}
STDMETHODIMP BrowserAccessibilityWin::get_parentNode(ISimpleDOMNode** node) {
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h
index addb39b..db6d00f 100644
--- a/content/browser/accessibility/browser_accessibility_win.h
+++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -194,6 +194,13 @@ BrowserAccessibilityWin
IAccessibleRelation** relations,
LONG* n_relations);
+ CONTENT_EXPORT STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type);
+
+ CONTENT_EXPORT STDMETHODIMP scrollToPoint(
+ enum IA2CoordinateType coordinate_type,
+ LONG x,
+ LONG y);
+
CONTENT_EXPORT STDMETHODIMP get_groupPosition(LONG* group_level,
LONG* similar_items_in_group,
LONG* position_in_group);
@@ -202,15 +209,6 @@ BrowserAccessibilityWin
CONTENT_EXPORT STDMETHODIMP get_extendedRole(BSTR* extended_role) {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) {
- return E_NOTIMPL;
- }
- CONTENT_EXPORT STDMETHODIMP scrollToPoint(
- enum IA2CoordinateType coordinate_type,
- LONG x,
- LONG y) {
- return E_NOTIMPL;
- }
CONTENT_EXPORT STDMETHODIMP get_localizedExtendedRole(
BSTR* localized_extended_role) {
return E_NOTIMPL;
@@ -445,10 +443,28 @@ BrowserAccessibilityWin
enum IA2CoordinateType coord_type,
LONG* offset);
+ CONTENT_EXPORT STDMETHODIMP scrollSubstringTo(
+ LONG start_index,
+ LONG end_index,
+ enum IA2ScrollType scroll_type);
+
+ CONTENT_EXPORT STDMETHODIMP scrollSubstringToPoint(
+ LONG start_index,
+ LONG end_index,
+ enum IA2CoordinateType coordinate_type,
+ LONG x, LONG y);
+
+ CONTENT_EXPORT STDMETHODIMP addSelection(LONG start_offset, LONG end_offset);
+
+ CONTENT_EXPORT STDMETHODIMP removeSelection(LONG selection_index);
+
+ CONTENT_EXPORT STDMETHODIMP setCaretOffset(LONG offset);
+
+ CONTENT_EXPORT STDMETHODIMP setSelection(LONG selection_index,
+ LONG start_offset,
+ LONG end_offset);
+
// IAccessibleText methods not implemented.
- CONTENT_EXPORT STDMETHODIMP addSelection(LONG start_offset, LONG end_offset) {
- return E_NOTIMPL;
- }
CONTENT_EXPORT STDMETHODIMP get_attributes(LONG offset, LONG* start_offset,
LONG* end_offset,
BSTR* text_attributes) {
@@ -460,28 +476,6 @@ BrowserAccessibilityWin
LONG* width, LONG* height) {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP removeSelection(LONG selection_index) {
- return E_NOTIMPL;
- }
- CONTENT_EXPORT STDMETHODIMP setCaretOffset(LONG offset) {
- return E_NOTIMPL;
- }
- CONTENT_EXPORT STDMETHODIMP setSelection(LONG selection_index,
- LONG start_offset,
- LONG end_offset) {
- return E_NOTIMPL;
- }
- CONTENT_EXPORT STDMETHODIMP scrollSubstringTo(LONG start_index,
- LONG end_index,
- enum IA2ScrollType scroll_type) {
- return E_NOTIMPL;
- }
- CONTENT_EXPORT STDMETHODIMP scrollSubstringToPoint(LONG start_index,
- LONG end_index,
- enum IA2CoordinateType coordinate_type,
- LONG x, LONG y) {
- return E_NOTIMPL;
- }
//
// IAccessibleValue methods.