Skip to content
Snippets Groups Projects
Commit 02747d4e authored by ctguil@chromium.org's avatar ctguil@chromium.org
Browse files

Add basic support for accessibility hit testing within web contents.

BUG=59890
TEST=Manual. Inspect32.

Review URL: http://codereview.chromium.org/4292001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64943 0039d316-1c4b-4281-b951-d872f2087c98
parent 604890c1
No related merge requests found
......@@ -5,6 +5,7 @@
#include "chrome/browser/accessibility/browser_accessibility.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "chrome/browser/accessibility/browser_accessibility_manager.h"
BrowserAccessibility::BrowserAccessibility()
......@@ -110,3 +111,65 @@ BrowserAccessibility* BrowserAccessibility::GetNextSibling() {
return NULL;
}
gfx::Rect BrowserAccessibility::GetBoundsRect() {
gfx::Rect bounds = location_;
// Adjust the bounds by the top left corner of the containing view's bounds
// in screen coordinates.
gfx::Point top_left = manager_->GetViewBounds().origin();
bounds.Offset(top_left);
// Adjust top left position by the root document's scroll offset.
BrowserAccessibility* root = manager_->GetRoot();
int scroll_x = 0;
int scroll_y = 0;
root->GetAttributeAsInt(
WebAccessibility::ATTR_DOC_SCROLLX, &scroll_x);
root->GetAttributeAsInt(
WebAccessibility::ATTR_DOC_SCROLLY, &scroll_y);
bounds.Offset(-scroll_x, -scroll_y);
return bounds;
}
BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
const gfx::Point& point) {
// Walk the children recursively looking for the BrowserAccessibility that
// most tightly encloses the specified point.
for (int i = children_.size() - 1; i >= 0; --i) {
BrowserAccessibility* child = children_[i];
if (child->GetBoundsRect().Contains(point))
return child->BrowserAccessibilityForPoint(point);
}
return this;
}
bool BrowserAccessibility::HasAttribute(
WebAccessibility::Attribute attribute) {
return (attributes_.find(attribute) != attributes_.end());
}
bool BrowserAccessibility::GetAttribute(
WebAccessibility::Attribute attribute, string16* value) {
std::map<int32, string16>::iterator iter = attributes_.find(attribute);
if (iter != attributes_.end()) {
*value = iter->second;
return true;
}
return false;
}
bool BrowserAccessibility::GetAttributeAsInt(
WebAccessibility::Attribute attribute, int* value_int) {
string16 value_str;
if (!GetAttribute(attribute, &value_str))
return false;
if (!base::StringToInt(value_str, value_int))
return false;
return true;
}
......@@ -90,6 +90,12 @@ class BrowserAccessibility {
// of its parent.
BrowserAccessibility* GetNextSibling();
// Returns the bounds of this object in screen coordinates.
gfx::Rect GetBoundsRect();
// Returns the deepest descendant that contains the specified point.
BrowserAccessibility* BrowserAccessibilityForPoint(const gfx::Point& point);
// Accessors
const std::map<int32, string16>& attributes() const { return attributes_; }
int32 child_id() const { return child_id_; }
......@@ -118,6 +124,20 @@ class BrowserAccessibility {
protected:
BrowserAccessibility();
// Return true if this attribute is in the attributes map.
bool HasAttribute(WebAccessibility::Attribute attribute);
// Retrieve the string value of an attribute from the attribute map and
// returns true if found.
bool GetAttribute(WebAccessibility::Attribute attribute, string16* value);
// Retrieve the value of an attribute from the attribute map and
// if found and nonempty, try to convert it to an integer.
// Returns true only if both the attribute was found and it was successfully
// converted to an integer.
bool GetAttributeAsInt(
WebAccessibility::Attribute attribute, int* value_int);
// The manager of this tree of accessibility objects; needed for
// global operations like focus tracking.
BrowserAccessibilityManager* manager_;
......
......@@ -226,6 +226,12 @@ void BrowserAccessibilityManager::DoDefaultAction(
delegate_->AccessibilityDoDefaultAction(node.renderer_id());
}
gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
if (delegate_)
return delegate_->GetViewBounds();
return gfx::Rect();
}
bool BrowserAccessibilityManager::CanModifyTreeInPlace(
BrowserAccessibility* current_root,
const WebAccessibility& new_root) {
......
......@@ -15,7 +15,6 @@
#include "gfx/native_widget_types.h"
#include "webkit/glue/webaccessibility.h"
class BrowserAccessibility;
#if defined(OS_WIN)
class BrowserAccessibilityManagerWin;
......@@ -30,6 +29,7 @@ class BrowserAccessibilityDelegate {
virtual void SetAccessibilityFocus(int acc_obj_id) = 0;
virtual void AccessibilityDoDefaultAction(int acc_obj_id) = 0;
virtual bool HasFocus() = 0;
virtual gfx::Rect GetViewBounds() const = 0;
};
class BrowserAccessibilityFactory {
......@@ -81,6 +81,9 @@ class BrowserAccessibilityManager {
// Tell the renderer to do the default action for this node.
void DoDefaultAction(const BrowserAccessibility& node);
// Retrieve the bounds of the parent View in screen coordinates.
gfx::Rect GetViewBounds();
// Called when the renderer process has notified us of about tree changes.
// Send a notification to MSAA clients of the change.
void OnAccessibilityNotifications(
......
......@@ -53,15 +53,31 @@ HRESULT BrowserAccessibilityWin::accDoDefaultAction(VARIANT var_id) {
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::accHitTest(LONG x_left, LONG y_top,
VARIANT* child) {
STDMETHODIMP BrowserAccessibilityWin::accHitTest(
LONG x_left, LONG y_top, VARIANT* child) {
if (!instance_active_)
return E_FAIL;
if (!child)
return E_INVALIDARG;
return E_NOTIMPL;
gfx::Point point(x_left, y_top);
if (!GetBoundsRect().Contains(point)) {
// Return S_FALSE and VT_EMPTY when the outside the object's boundaries.
child->vt = VT_EMPTY;
return S_FALSE;
}
BrowserAccessibility* result = BrowserAccessibilityForPoint(point);
if (result == this) {
// Point is within this object.
child->vt = VT_I4;
child->lVal = CHILDID_SELF;
} else {
child->vt = VT_DISPATCH;
child->pdispVal = result->toBrowserAccessibilityWin()->NewReference();
}
return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::accLocation(LONG* x_left, LONG* y_top,
......@@ -77,16 +93,11 @@ STDMETHODIMP BrowserAccessibilityWin::accLocation(LONG* x_left, LONG* y_top,
if (!target)
return E_INVALIDARG;
// Find the top left corner of the containing window in screen coords, and
// adjust the output position by this amount.
HWND parent_hwnd = manager_->GetParentView();
POINT top_left = {0, 0};
::ClientToScreen(parent_hwnd, &top_left);
*x_left = target->location_.x + top_left.x;
*y_top = target->location_.y + top_left.y;
*width = target->location_.width;
*height = target->location_.height;
gfx::Rect bounds = target->GetBoundsRect();
*x_left = bounds.x();
*y_top = bounds.y();
*width = bounds.width();
*height = bounds.height();
return S_OK;
}
......@@ -1156,22 +1167,6 @@ BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID(
return manager_->GetFromChildID(child_id)->toBrowserAccessibilityWin();
}
bool BrowserAccessibilityWin::HasAttribute(
WebAccessibility::Attribute attribute) {
return (attributes_.find(attribute) != attributes_.end());
}
bool BrowserAccessibilityWin::GetAttribute(
WebAccessibility::Attribute attribute, string16* value) {
std::map<int32, string16>::iterator iter = attributes_.find(attribute);
if (iter != attributes_.end()) {
*value = iter->second;
return true;
}
return false;
}
HRESULT BrowserAccessibilityWin::GetAttributeAsBstr(
WebAccessibility::Attribute attribute, BSTR* value_bstr) {
string16 str;
......@@ -1188,19 +1183,6 @@ HRESULT BrowserAccessibilityWin::GetAttributeAsBstr(
return S_OK;
}
bool BrowserAccessibilityWin::GetAttributeAsInt(
WebAccessibility::Attribute attribute, int* value_int) {
string16 value_str;
if (!GetAttribute(attribute, &value_str))
return false;
if (!base::StringToInt(value_str, value_int))
return false;
return true;
}
string16 BrowserAccessibilityWin::Escape(string16 str) {
return EscapeQueryParamValueUTF8(str, false);
}
......
......@@ -457,26 +457,12 @@ class BrowserAccessibilityWin
// bitmasks defined in webkit/glue/webaccessibility.h.
void InitRoleAndState();
// Return true if this attribute is in the attributes map.
bool HasAttribute(WebAccessibility::Attribute attribute);
// Retrieve the string value of an attribute from the attribute map and
// returns true if found.
bool GetAttribute(WebAccessibility::Attribute attribute, string16* value);
// Retrieve the string value of an attribute from the attribute map and
// if found and nonempty, allocate a new BSTR (with SysAllocString)
// and return S_OK. If not found or empty, return S_FALSE.
HRESULT GetAttributeAsBstr(
WebAccessibility::Attribute attribute, BSTR* value_bstr);
// Retrieve the value of an attribute from the attribute map and
// if found and nonempty, try to convert it to an integer.
// Returns true only if both the attribute was found and it was successfully
// converted to an integer.
bool GetAttributeAsInt(
WebAccessibility::Attribute attribute, int* value_int);
// Escape a string like it would be escaped for a URL or HTML form.
string16 Escape(string16 str);
......
......@@ -19,6 +19,7 @@
#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNamedNodeMap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
using WebKit::WebAccessibilityCache;
......@@ -366,6 +367,10 @@ void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src,
const WebKit::WebDocumentType& doctype = document.doctype();
if (!doctype.isNull())
attributes[ATTR_DOC_DOCTYPE] = doctype.name();
const gfx::Size& scroll_offset = document.frame()->scrollOffset();
attributes[ATTR_DOC_SCROLLX] = base::IntToString16(scroll_offset.width());
attributes[ATTR_DOC_SCROLLY] = base::IntToString16(scroll_offset.height());
}
// Add the source object to the cache and store its id.
......
......@@ -162,6 +162,8 @@ struct WebAccessibility {
ATTR_DOC_TITLE,
ATTR_DOC_MIMETYPE,
ATTR_DOC_DOCTYPE,
ATTR_DOC_SCROLLX,
ATTR_DOC_SCROLLY,
// Editable text attributes
ATTR_TEXT_SEL_START,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment