Commit c9c86ac1 authored by dmazzoni's avatar dmazzoni Committed by Commit bot

Draw a focus ring around native views when ChromeVox is running.

Previously a focus ring was only drawn around web elements; this uses a
new API to draw the focus ring around native views, too, by adding a new
field to the existing private accessibility API with the bounding rect of
the focused view.

BUG=314889

Review URL: https://codereview.chromium.org/600063002

Cr-Commit-Position: refs/heads/master@{#296970}
parent 03f26fbf
......@@ -63,6 +63,14 @@ void AccessibilityControlInfo::SerializeToDict(
dict->SetString(keys::kTypeKey, type());
if (!context_.empty())
dict->SetString(keys::kContextKey, context_);
if (!bounds_.IsEmpty()) {
base::DictionaryValue* bounds_value = new base::DictionaryValue();
bounds_value->SetInteger(keys::kLeft, bounds_.x());
bounds_value->SetInteger(keys::kTop, bounds_.y());
bounds_value->SetInteger(keys::kWidth, bounds_.width());
bounds_value->SetInteger(keys::kHeight, bounds_.height());
dict->Set(keys::kBoundsKey, bounds_value);
}
}
AccessibilityWindowInfo::AccessibilityWindowInfo(Profile* profile,
......
......@@ -8,6 +8,7 @@
#include <string>
#include "base/compiler_specific.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/gfx/rect.h"
class AccessibilityControlInfo;
class AccessibilityMenuInfo;
......@@ -70,6 +71,9 @@ class AccessibilityControlInfo : public AccessibilityEventInfo {
const std::string& context() const { return context_; }
void set_bounds(const gfx::Rect& bounds) { bounds_ = bounds; }
const gfx::Rect& bounds() const { return bounds_; }
protected:
AccessibilityControlInfo(Profile* profile,
const std::string& name);
......@@ -82,6 +86,9 @@ class AccessibilityControlInfo : public AccessibilityEventInfo {
// A string describing the context of the control, such as the name of
// the group or toolbar it's contained in.
std::string context_;
// The bounds of the control in global screen coordinates.
gfx::Rect bounds_;
};
// Accessibility information about a window passed to onWindowOpened
......
......@@ -323,10 +323,10 @@ bool AccessibilityPrivateSetFocusRingFunction::RunSync() {
base::DictionaryValue* rect_value = NULL;
EXTENSION_FUNCTION_VALIDATE(rect_values->GetDictionary(i, &rect_value));
int left, top, width, height;
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger("left", &left));
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger("top", &top));
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger("width", &width));
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger("height", &height));
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kLeft, &left));
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kTop, &top));
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kWidth, &width));
EXTENSION_FUNCTION_VALIDATE(rect_value->GetInteger(keys::kHeight, &height));
rects.push_back(gfx::Rect(left, top, width, height));
}
......
......@@ -23,6 +23,7 @@ const char kCheckedKey[] = "details.isChecked";
const char kHasSubmenuKey[] = "details.hasSubmenu";
const char kMessageKey[] = "message";
const char kStringValueKey[] = "details.stringValue";
const char kBoundsKey[] = "bounds";
// Types of controls that can receive accessibility events.
const char kTypeAlert[] = "alert";
......@@ -42,6 +43,12 @@ const char kTypeTree[] = "tree";
const char kTypeTreeItem[] = "treeitem";
const char kTypeWindow[] = "window";
// ScreenRect fields.
const char kLeft[] = "left";
const char kTop[] = "top";
const char kWidth[] = "width";
const char kHeight[] = "height";
// Errors.
const char kErrorNotSupported[] = "This API is not supported on this platform.";
......
......@@ -26,6 +26,7 @@ extern const char kCheckedKey[];
extern const char kHasSubmenuKey[];
extern const char kMessageKey[];
extern const char kStringValueKey[];
extern const char kBoundsKey[];
// Types of controls that can receive accessibility events.
extern const char kTypeAlert[];
......@@ -46,6 +47,12 @@ extern const char kTypeTreeItem[];
extern const char kTypeVolume[];
extern const char kTypeWindow[];
// ScreenRect fields.
extern const char kLeft[];
extern const char kTop[];
extern const char kWidth[];
extern const char kHeight[];
// Errors.
extern const char kErrorNotSupported[];
......
......@@ -162,6 +162,12 @@ cvox.AccessibilityApiHandler.prototype.setWebContext = function() {
this.lastContext = '--internal-web--';
this.editableTextHandler = null;
this.editableTextName = '';
if (chrome.accessibilityPrivate.setFocusRing &&
cvox.ChromeVox.isChromeOS) {
// Clear the focus ring.
chrome.accessibilityPrivate.setFocusRing([]);
}
};
/**
......@@ -401,6 +407,12 @@ cvox.AccessibilityApiHandler.prototype.onControlFocused = function(ctl) {
return;
}
if (ctl.bounds &&
chrome.accessibilityPrivate.setFocusRing &&
cvox.ChromeVox.isChromeOS) {
chrome.accessibilityPrivate.setFocusRing([ctl.bounds]);
}
// Call this first because it may clear this.editableTextHandler.
var description = this.describe(ctl, false);
......
......@@ -52,6 +52,14 @@ chrome.accessibilityPrivate.setNativeAccessibilityEnabled = function(on) {
chrome.accessibilityPrivate.getAlertsForTab =
function(tabId, callback) {};
/**
* @param {Array.<{left: number, top: number, width: number, height: number}>}
* rects The bounding rects to draw focus ring(s) around, in global
* screen coordinates.
*/
chrome.accessibilityPrivate.setFocusRing = function(rects) {
};
/** @type ChromeEvent */
chrome.accessibilityPrivate.onWindowOpened;
......
......@@ -262,6 +262,7 @@ void AccessibilityEventRouterViews::SendTabNotification(
std::string name = base::UTF16ToUTF8(state.name);
std::string context = GetViewContext(view);
AccessibilityTabInfo info(profile, name, context, state.index, state.count);
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -272,6 +273,7 @@ void AccessibilityEventRouterViews::SendButtonNotification(
Profile* profile) {
AccessibilityButtonInfo info(
profile, GetViewName(view), GetViewContext(view));
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -282,6 +284,7 @@ void AccessibilityEventRouterViews::SendStaticTextNotification(
Profile* profile) {
AccessibilityStaticTextInfo info(
profile, GetViewName(view), GetViewContext(view));
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -291,6 +294,7 @@ void AccessibilityEventRouterViews::SendLinkNotification(
ui::AXEvent event,
Profile* profile) {
AccessibilityLinkInfo info(profile, GetViewName(view), GetViewContext(view));
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -300,6 +304,7 @@ void AccessibilityEventRouterViews::SendMenuNotification(
ui::AXEvent event,
Profile* profile) {
AccessibilityMenuInfo info(profile, GetViewName(view));
info.set_bounds(view->GetBoundsInScreen());
SendMenuAccessibilityNotification(event, &info);
}
......@@ -330,6 +335,7 @@ void AccessibilityEventRouterViews::SendMenuItemNotification(
AccessibilityMenuItemInfo info(
profile, name, context, has_submenu, index, count);
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -339,6 +345,7 @@ void AccessibilityEventRouterViews::SendTreeNotification(
ui::AXEvent event,
Profile* profile) {
AccessibilityTreeInfo info(profile, GetViewName(view));
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -384,6 +391,7 @@ void AccessibilityEventRouterViews::SendTreeItemNotification(
AccessibilityTreeItemInfo info(
profile, name, context, depth, index, siblings_count, children_count,
is_expanded);
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -400,6 +408,7 @@ void AccessibilityEventRouterViews::SendTextfieldNotification(
AccessibilityTextBoxInfo info(profile, name, context, password);
std::string value = base::UTF16ToUTF8(state.value);
info.SetValue(value, state.selection_start, state.selection_end);
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -415,6 +424,7 @@ void AccessibilityEventRouterViews::SendComboboxNotification(
std::string context = GetViewContext(view);
AccessibilityComboBoxInfo info(
profile, name, context, value, state.index, state.count);
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -432,6 +442,7 @@ void AccessibilityEventRouterViews::SendCheckboxNotification(
name,
context,
state.HasStateFlag(ui::AX_STATE_CHECKED));
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -454,6 +465,7 @@ void AccessibilityEventRouterViews::SendWindowNotification(
window_text = base::UTF16ToUTF8(state.name);
AccessibilityWindowInfo info(profile, window_text);
info.set_bounds(view->GetBoundsInScreen());
SendWindowAccessibilityNotification(event, &info);
}
......@@ -473,6 +485,7 @@ void AccessibilityEventRouterViews::SendSliderNotification(
name,
context,
value);
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......@@ -488,6 +501,7 @@ void AccessibilityEventRouterViews::SendAlertControlNotification(
AccessibilityAlertInfo info(
profile,
name);
info.set_bounds(view->GetBoundsInScreen());
SendControlAccessibilityNotification(event, &info);
}
......
......@@ -123,6 +123,17 @@
}
}
},
{
"id": "ScreenRect",
"type": "object",
"description": "Bounding rectangle in global screen coordinates.",
"properties": {
"left": {"type": "integer", "description": "Left coordinate in global screen coordinates."},
"top": {"type": "integer", "description": "Top coordinate in global screen coordinates."},
"width": {"type": "integer", "description": "Width in pixels."},
"height": {"type": "integer", "description": "Height in pixels."}
}
},
{
"id": "AccessibilityObject",
"type": "object",
......@@ -157,19 +168,13 @@
{ "$ref": "TreeDetails" },
{ "$ref": "TreeItemDetails" }
]
},
"bounds": {
"$ref": "ScreenRect",
"description": "The bounds of the object, in global screen coordinates.",
"optional": true
}
}
},
{
"id": "ScreenRect",
"type": "object",
"description": "Bounding rectangle in global screen coordinates.",
"properties": {
"left": {"type": "integer", "description": "Left coordinate in global screen coordinates."},
"top": {"type": "integer", "description": "Top coordinate in global screen coordinates."},
"width": {"type": "integer", "description": "Width in pixels."},
"height": {"type": "integer", "description": "Height in pixels."}
}
}
],
"functions": [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment