cefclient: OSR accessibility enhancements (see issue #2604)

- Implement multi-tree support (e.g. page with iframes contains several trees)
- Implement OnAccessibilityLocationChange support
- Add scroll offset calculation
- Fix new Chromium tree layout parsing
- Fix uninitialized OsrAXNode::offset_container_id_
- Fix Windows non ascii AxName, AxValue, AxDescription representation
This commit is contained in:
Andrei Kurushin 2019-03-21 16:56:06 +00:00 committed by Marshall Greenblatt
parent b3468451f5
commit af349ade33
13 changed files with 411 additions and 137 deletions

View File

@ -1362,6 +1362,11 @@ void BrowserWindowOsrGtk::UpdateAccessibilityTree(CefRefPtr<CefValue> value) {
CEF_REQUIRE_UI_THREAD();
}
void BrowserWindowOsrGtk::UpdateAccessibilityLocation(
CefRefPtr<CefValue> value) {
CEF_REQUIRE_UI_THREAD();
}
void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) {
REQUIRE_MAIN_THREAD();
DCHECK(!glarea_);

View File

@ -89,6 +89,7 @@ class BrowserWindowOsrGtk : public BrowserWindow,
const CefRange& selection_range,
const CefRenderHandler::RectList& character_bounds) OVERRIDE;
void UpdateAccessibilityTree(CefRefPtr<CefValue> value) OVERRIDE;
void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) OVERRIDE;
private:
~BrowserWindowOsrGtk();

View File

@ -85,6 +85,7 @@ class BrowserWindowOsrMac : public BrowserWindow,
const CefRenderHandler::RectList& character_bounds) OVERRIDE;
void UpdateAccessibilityTree(CefRefPtr<CefValue> value) OVERRIDE;
void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) OVERRIDE;
private:
// Create the NSView.

View File

@ -109,6 +109,7 @@ CefTextInputClientOSRMac* GetInputClientFromContext(
character_bounds:
(const CefRenderHandler::RectList&)character_bounds;
- (void)UpdateAccessibilityTree:(CefRefPtr<CefValue>)value;
- (void)UpdateAccessibilityLocation:(CefRefPtr<CefValue>)value;
@end
namespace {
@ -1306,6 +1307,18 @@ NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
}
return;
}
- (void)UpdateAccessibilityLocation:(CefRefPtr<CefValue>)value {
if (accessibility_helper_) {
accessibility_helper_->UpdateAccessibilityLocation(value);
}
if (accessibility_helper_) {
NSAccessibilityPostNotification(self,
NSAccessibilityValueChangedNotification);
}
return;
}
@end
namespace client {

View File

@ -167,4 +167,12 @@ void ClientHandlerOsr::OnAccessibilityTreeChange(CefRefPtr<CefValue> value) {
osr_delegate_->UpdateAccessibilityTree(value);
}
void ClientHandlerOsr::OnAccessibilityLocationChange(
CefRefPtr<CefValue> value) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return;
osr_delegate_->UpdateAccessibilityLocation(value);
}
} // namespace client

View File

@ -68,6 +68,8 @@ class ClientHandlerOsr : public ClientHandler,
virtual void UpdateAccessibilityTree(CefRefPtr<CefValue> value) = 0;
virtual void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) = 0;
protected:
virtual ~OsrDelegate() {}
};
@ -130,7 +132,7 @@ class ClientHandlerOsr : public ClientHandler,
// CefAccessibilityHandler methods.
void OnAccessibilityTreeChange(CefRefPtr<CefValue> value) OVERRIDE;
void OnAccessibilityLocationChange(CefRefPtr<CefValue> value) OVERRIDE {}
void OnAccessibilityLocationChange(CefRefPtr<CefValue> value) OVERRIDE;
private:
// Only accessed on the UI thread.

View File

@ -7,134 +7,260 @@
namespace client {
OsrAXTree::OsrAXTree() : parent_tree_id_(-1), root_node_id_(-1) {}
OsrAXNode* OsrAXTree::GetNode(int nodeId) const {
auto result = node_map_.find(nodeId);
if (result != node_map_.end()) {
return result->second;
}
return NULL;
}
void OsrAXTree::EraseNode(int nodeId) {
node_map_.erase(nodeId);
}
void OsrAXTree::AddNode(OsrAXNode* node) {
node_map_[node->OsrAXNodeId()] = node;
}
void OsrAXTree::UpdateTreeData(CefRefPtr<CefDictionaryValue> value) {
if (value->HasKey("parent_tree_id")) {
parent_tree_id_ =
OsrAccessibilityHelper::CastToInt(value->GetValue("parent_tree_id"));
} else {
parent_tree_id_ = -1;
}
// may also update following:
// doctype, title, url, mimetype
}
OsrAccessibilityHelper::OsrAccessibilityHelper(CefRefPtr<CefValue> value,
CefRefPtr<CefBrowser> browser)
: root_node_id_(-1), focused_node_id_(-1), browser_(browser) {
: root_tree_id_(-1),
focused_tree_id_(-1),
focused_node_id_(-1),
browser_(browser) {
UpdateAccessibilityTree(value);
}
int OsrAccessibilityHelper::CastToInt(CefRefPtr<CefValue> value) {
if (value->GetType() == VTYPE_STRING) {
const std::string& str = value->GetString();
return atoi(str.c_str());
} else {
return value->GetInt();
}
}
void OsrAccessibilityHelper::UpdateAccessibilityLocation(
CefRefPtr<CefValue> value) {
if (!value || value->GetType() != VTYPE_LIST) {
return;
}
CefRefPtr<CefListValue> locationChangeList = value->GetList();
size_t locationChangeCount = locationChangeList->GetSize();
if (locationChangeCount == 0) {
return;
}
for (size_t i = 0; i < locationChangeCount; i++) {
CefRefPtr<CefDictionaryValue> locationChangeDict =
locationChangeList->GetDictionary(i);
if (!locationChangeDict->HasKey("ax_tree_id") ||
!locationChangeDict->HasKey("new_location") ||
!locationChangeDict->HasKey("id")) {
continue;
}
int treeId = CastToInt(locationChangeDict->GetValue("ax_tree_id"));
int nodeId = CastToInt(locationChangeDict->GetValue("id"));
CefRefPtr<CefDictionaryValue> newLocationDict =
locationChangeDict->GetDictionary("new_location");
if (!newLocationDict) {
continue;
}
OsrAXNode* node = GetNode(treeId, nodeId);
if (!node) {
continue;
}
node->UpdateLocation(newLocationDict);
}
}
void OsrAccessibilityHelper::UpdateAccessibilityTree(
CefRefPtr<CefValue> value) {
if (value && value->GetType() == VTYPE_LIST) {
CefRefPtr<CefListValue> list = value->GetList();
size_t numEvents = list->GetSize();
if (numEvents > 0) {
for (size_t i = 0; i < numEvents; i++) {
CefRefPtr<CefDictionaryValue> event = list->GetDictionary(i);
if (event && event->HasKey("event_type") && event->HasKey("update")) {
std::string event_type = event->GetString("event_type");
CefRefPtr<CefDictionaryValue> update = event->GetDictionary("update");
if (event_type == "layoutComplete")
UpdateLayout(update);
if (event_type == "focus" && event->HasKey("id")) {
// Update focused node id
focused_node_id_ = event->GetInt("id");
UpdateFocusedNode(update);
}
}
}
}
if (!value || value->GetType() != VTYPE_DICTIONARY) {
return;
}
CefRefPtr<CefDictionaryValue> mainDict = value->GetDictionary();
if (!mainDict->HasKey("ax_tree_id") || !mainDict->HasKey("updates")) {
return;
}
int treeId = CastToInt(mainDict->GetValue("ax_tree_id"));
CefRefPtr<CefListValue> updatesList = mainDict->GetList("updates");
size_t updatesCount = updatesList->GetSize();
if (updatesCount == 0) {
return;
}
for (size_t i = 0; i < updatesCount; i++) {
CefRefPtr<CefDictionaryValue> updateDict = updatesList->GetDictionary(i);
UpdateLayout(treeId, updateDict);
}
}
OsrAXNode* OsrAccessibilityHelper::GetRootNode() const {
return GetTreeRootNode(root_tree_id_);
}
OsrAXNode* OsrAccessibilityHelper::GetFocusedNode() const {
auto tree = accessibility_node_map_.find(focused_tree_id_);
if (tree != accessibility_node_map_.end()) {
return tree->second.GetNode(focused_node_id_);
}
return NULL;
}
OsrAXNode* OsrAccessibilityHelper::GetTreeRootNode(int treeId) const {
auto tree = accessibility_node_map_.find(treeId);
if (tree != accessibility_node_map_.end()) {
return tree->second.GetNode(tree->second.GetRootNodeId());
}
return NULL;
}
void OsrAccessibilityHelper::UpdateLayout(
int treeId,
CefRefPtr<CefDictionaryValue> update) {
if (update) {
CefRefPtr<CefDictionaryValue> tree_data;
// get tree data
if (update->HasKey("has_tree_data") && update->GetBool("has_tree_data"))
tree_data = update->GetDictionary("tree_data");
if (!update) {
return;
}
// If a node is to be cleared
if (update->HasKey("node_id_to_clear")) {
int node_id_to_clear = update->GetInt("node_id_to_clear");
// If a node is to be cleared
if (update->HasKey("node_id_to_clear")) {
int nodeId = CastToInt(update->GetValue("node_id_to_clear"));
// reset root node if that is to be cleared
if (node_id_to_clear == root_node_id_)
root_node_id_ = -1;
OsrAXNode* node = GetNode(node_id_to_clear);
DestroyNode(node);
}
if (update->HasKey("root_id"))
root_node_id_ = update->GetInt("root_id");
if (tree_data && tree_data->HasKey("focus_id"))
focused_node_id_ = tree_data->GetInt("focus_id");
// Now initialize/update the node data.
if (update->HasKey("nodes")) {
CefRefPtr<CefListValue> nodes = update->GetList("nodes");
for (size_t index = 0; index < nodes->GetSize(); index++) {
CefRefPtr<CefDictionaryValue> node = nodes->GetDictionary(index);
if (node) {
int node_id = node->GetInt("id");
OsrAXNode* axNode = GetNode(node_id);
// Create if it is a new one
if (axNode) {
axNode->UpdateValue(node);
} else {
axNode = OsrAXNode::CreateNode(node, this);
accessibility_node_map_[node_id] = axNode;
}
}
// reset root node if that is to be cleared
auto tree = accessibility_node_map_.find(treeId);
if (tree != accessibility_node_map_.end()) {
if (tree->second.GetRootNodeId() == nodeId) {
root_tree_id_ = -1;
tree->second.SetRootNodeId(-1);
}
}
if ((focused_tree_id_ == treeId) && (focused_node_id_ == nodeId)) {
UpdateFocusedNode(-1, -1);
}
OsrAXNode* node = GetNode(treeId, nodeId);
DestroyNode(node);
}
}
void OsrAccessibilityHelper::UpdateFocusedNode(
CefRefPtr<CefDictionaryValue> update) {
if (update && update->HasKey("nodes")) {
// get tree data
if (update->HasKey("tree_data") && update->HasKey("has_tree_data") &&
update->GetBool("has_tree_data")) {
CefRefPtr<CefDictionaryValue> tree_data =
update->GetDictionary("tree_data");
auto& tree = accessibility_node_map_[treeId];
tree.UpdateTreeData(tree_data);
if (tree.GetParentTreeId() == -1) {
root_tree_id_ = treeId;
}
if (tree_data->HasKey("focus_id") && tree_data->HasKey("focused_tree_id")) {
UpdateFocusedNode(CastToInt(tree_data->GetValue("focused_tree_id")),
CastToInt(tree_data->GetValue("focus_id")));
}
}
// Now initialize/update the node data.
if (update->HasKey("nodes")) {
CefRefPtr<CefListValue> nodes = update->GetList("nodes");
for (size_t index = 0; index < nodes->GetSize(); index++) {
CefRefPtr<CefDictionaryValue> node = nodes->GetDictionary(index);
if (node) {
int node_id = node->GetInt("id");
OsrAXNode* axNode = GetNode(node_id);
auto& tree = accessibility_node_map_[treeId];
int nodeId = CastToInt(node->GetValue("id"));
OsrAXNode* axNode = tree.GetNode(nodeId);
// Create if it is a new one
if (axNode) {
axNode->UpdateValue(node);
} else {
axNode = OsrAXNode::CreateNode(node, this);
accessibility_node_map_[node_id] = axNode;
axNode = OsrAXNode::CreateNode(treeId, nodeId, node, this);
tree.AddNode(axNode);
}
}
}
}
if (update->HasKey("root_id")) {
int nodeId = CastToInt(update->GetValue("root_id"));
OsrAXNode* node = GetNode(treeId, nodeId);
if (node != NULL) {
auto& tree = accessibility_node_map_[treeId];
tree.SetRootNodeId(nodeId);
}
}
}
void OsrAccessibilityHelper::UpdateFocusedNode(int treeId, int nodeId) {
if ((focused_tree_id_ == treeId) && (focused_node_id_ == nodeId)) {
return;
}
focused_tree_id_ = treeId;
focused_node_id_ = nodeId;
// Now Notify Screen Reader
OsrAXNode* axNode = GetFocusedNode();
// Fallback to Root
if (!axNode)
axNode = GetRootNode();
axNode->NotifyAccessibilityEvent("focus");
if (axNode) {
axNode->NotifyAccessibilityEvent("focus");
}
}
void OsrAccessibilityHelper::Reset() {
accessibility_node_map_.clear();
root_node_id_ = focused_node_id_ = -1;
root_tree_id_ = -1;
focused_tree_id_ = focused_node_id_ = -1;
}
void OsrAccessibilityHelper::DestroyNode(OsrAXNode* node) {
if (node) {
int treeId = node->OsrAXTreeId();
int numChilds = node->GetChildCount();
if (numChilds > 0) {
for (int i = 0; i < numChilds; i++) {
DestroyNode(node->ChildAtIndex(i));
OsrAXNode* childNode = node->ChildAtIndex(i);
if (!childNode) {
continue;
}
childNode->SetParent(NULL);
if (childNode->OsrAXTreeId() == treeId) {
DestroyNode(childNode);
}
}
}
accessibility_node_map_.erase(node->OsrAXNodeId());
auto tree = accessibility_node_map_.find(treeId);
if (tree != accessibility_node_map_.end()) {
tree->second.EraseNode(node->OsrAXNodeId());
}
node->Destroy();
}
}
OsrAXNode* OsrAccessibilityHelper::GetNode(int nodeId) const {
if (nodeId != -1 &&
accessibility_node_map_.find(nodeId) != accessibility_node_map_.end()) {
return accessibility_node_map_.at(nodeId);
OsrAXNode* OsrAccessibilityHelper::GetNode(int treeId, int nodeId) const {
auto tree = accessibility_node_map_.find(treeId);
if (tree != accessibility_node_map_.end()) {
return tree->second.GetNode(nodeId);
}
return NULL;

View File

@ -12,6 +12,24 @@
namespace client {
class OsrAXNode;
class OsrAccessibilityHelper;
class OsrAXTree {
public:
OsrAXTree();
OsrAXNode* GetNode(int nodeId) const;
void EraseNode(int nodeId);
void UpdateTreeData(CefRefPtr<CefDictionaryValue> value);
void AddNode(OsrAXNode* node);
int GetParentTreeId() const { return parent_tree_id_; }
int GetRootNodeId() const { return root_node_id_; }
void SetRootNodeId(int nodeId) { root_node_id_ = nodeId; }
private:
int parent_tree_id_;
int root_node_id_;
std::map<int, OsrAXNode*> node_map_;
};
// Helper class that abstracts Renderer Accessibility tree and provides a
// uniform interface to be consumed by IAccessible interface on Windows and
@ -23,9 +41,11 @@ class OsrAccessibilityHelper {
void UpdateAccessibilityTree(CefRefPtr<CefValue> value);
OsrAXNode* GetRootNode() const { return GetNode(root_node_id_); }
void UpdateAccessibilityLocation(CefRefPtr<CefValue> value);
OsrAXNode* GetFocusedNode() const { return GetNode(focused_node_id_); }
OsrAXNode* GetRootNode() const;
OsrAXNode* GetFocusedNode() const;
CefWindowHandle GetWindowHandle() const {
return browser_->GetHost()->GetWindowHandle();
@ -33,23 +53,26 @@ class OsrAccessibilityHelper {
CefRefPtr<CefBrowser> GetBrowser() const { return browser_; }
OsrAXNode* GetNode(int nodeId) const;
OsrAXNode* GetNode(int treeId, int nodeId) const;
OsrAXNode* GetTreeRootNode(int treeId) const;
static int CastToInt(CefRefPtr<CefValue> value);
private:
OsrAXNode* CreateNode(OsrAXNode* parent, CefRefPtr<CefDictionaryValue> value);
void Reset();
void UpdateLayout(CefRefPtr<CefDictionaryValue> update);
void UpdateLayout(int treeId, CefRefPtr<CefDictionaryValue> update);
void UpdateFocusedNode(CefRefPtr<CefDictionaryValue> update);
void UpdateFocusedNode(int treeId, int nodeId);
// Destroy the node and remove from Map
void DestroyNode(OsrAXNode* node);
int root_node_id_;
int root_tree_id_;
int focused_tree_id_;
int focused_node_id_;
CefRefPtr<CefBrowser> browser_;
std::map<int, OsrAXNode*> accessibility_node_map_;
std::map<int, OsrAXTree> accessibility_node_map_;
};
} // namespace client

View File

@ -11,52 +11,88 @@
namespace client {
OsrAXNode::OsrAXNode(CefRefPtr<CefDictionaryValue> value,
OsrAXNode::OsrAXNode(int treeId,
int nodeId,
CefRefPtr<CefDictionaryValue> value,
OsrAccessibilityHelper* helper)
: node_id_(-1),
: tree_id_(treeId),
node_id_(nodeId),
child_tree_id_(-1),
platform_accessibility_(NULL),
parent_(NULL),
offset_container_id_(-1),
accessibility_helper_(helper) {
UpdateValue(value);
}
void OsrAXNode::UpdateLocation(CefRefPtr<CefDictionaryValue> value) {
// Update Bounds
if (value->HasKey("bounds")) {
CefRefPtr<CefDictionaryValue> loc = value->GetDictionary("bounds");
if (loc) {
location_ = CefRect(loc->GetDouble("x"), loc->GetDouble("y"),
loc->GetDouble("width"), loc->GetDouble("height"));
}
}
// Update offsets
if (value->HasKey("offset_container_id")) {
offset_container_id_ = OsrAccessibilityHelper::CastToInt(
value->GetValue("offset_container_id"));
}
}
void OsrAXNode::UpdateValue(CefRefPtr<CefDictionaryValue> value) {
if (value && value->HasKey("id")) {
node_id_ = value->GetInt("id");
if (value->HasKey("role"))
role_ = value->GetString("role");
if (value->HasKey("role"))
role_ = value->GetString("role");
if (value->HasKey("child_ids")) {
CefRefPtr<CefListValue> childs = value->GetList("child_ids");
// Reset child Ids
child_ids_.clear();
for (size_t idx = 0; idx < childs->GetSize(); idx++)
child_ids_.push_back(
OsrAccessibilityHelper::CastToInt(childs->GetValue(idx)));
}
// Update Location
if (value->HasKey("location")) {
CefRefPtr<CefDictionaryValue> loc = value->GetDictionary("location");
if (loc) {
location_ = CefRect(loc->GetDouble("x"), loc->GetDouble("y"),
loc->GetDouble("width"), loc->GetDouble("height"));
}
}
// Update offsets
if (value->HasKey("offset_container_id")) {
offset_container_id_ = OsrAccessibilityHelper::CastToInt(
value->GetValue("offset_container_id"));
}
// Update attributes
if (value->HasKey("attributes")) {
child_tree_id_ = -1;
if (value->HasKey("child_ids")) {
CefRefPtr<CefListValue> childs = value->GetList("child_ids");
// Reset child Ids
child_ids_.clear();
for (size_t idx = 0; idx < childs->GetSize(); idx++)
child_ids_.push_back(childs->GetInt(idx));
}
// Update Location
if (value->HasKey("location")) {
CefRefPtr<CefDictionaryValue> loc = value->GetDictionary("location");
if (loc) {
location_ = CefRect(loc->GetDouble("x"), loc->GetDouble("y"),
loc->GetDouble("width"), loc->GetDouble("height"));
}
}
// Update offsets
if (value->HasKey("offset_container_id")) {
offset_container_id_ = value->GetInt("offset_container_id");
}
// Update attributes
if (value->HasKey("attributes")) {
attributes_ = value->GetDictionary("attributes");
attributes_ = value->GetDictionary("attributes");
if (attributes_ && attributes_->HasKey("name"))
name_ = attributes_->GetString("name");
if (attributes_ && attributes_->HasKey("value"))
value_ = attributes_->GetString("value");
if (attributes_ && attributes_->HasKey("description"))
description_ = attributes_->GetString("description");
if (attributes_) {
scroll_.x = attributes_->HasKey("scrollX")
? OsrAccessibilityHelper::CastToInt(
attributes_->GetValue("scrollX"))
: 0;
scroll_.y = attributes_->HasKey("scrollY")
? OsrAccessibilityHelper::CastToInt(
attributes_->GetValue("scrollY"))
: 0;
}
if (attributes_ && attributes_->HasKey("childTreeId")) {
child_tree_id_ = OsrAccessibilityHelper::CastToInt(
attributes_->GetValue("childTreeId"));
}
if (attributes_ && attributes_->HasKey("name"))
name_ = attributes_->GetString("name");
if (attributes_ && attributes_->HasKey("value"))
value_ = attributes_->GetString("value");
if (attributes_ && attributes_->HasKey("description"))
description_ = attributes_->GetString("description");
}
}
@ -78,8 +114,21 @@ void OsrAXNode::SetParent(OsrAXNode* parent) {
CefRect OsrAXNode::AxLocation() const {
CefRect loc = location_;
OsrAXNode* offsetNode = accessibility_helper_->GetNode(offset_container_id_);
// Add offset from parent Lcoation
loc.x -= scroll_.x;
loc.y -= scroll_.y;
OsrAXNode* offsetNode =
accessibility_helper_->GetNode(OsrAXTreeId(), offset_container_id_);
if (!offsetNode) {
OsrAXNode* p = parent_;
while (p) {
if (p->OsrAXTreeId() != OsrAXTreeId()) {
offsetNode = p;
break;
}
p = p->parent_;
}
}
// Add offset from parent Location
if (offsetNode) {
CefRect offset = offsetNode->AxLocation();
loc.x += offset.x;
@ -88,17 +137,39 @@ CefRect OsrAXNode::AxLocation() const {
return loc;
}
int OsrAXNode::GetChildCount() const {
int count = static_cast<int>(child_ids_.size());
if (child_tree_id_ >= 0) {
OsrAXNode* childTreeRootNode =
accessibility_helper_->GetTreeRootNode(child_tree_id_);
if (childTreeRootNode) {
count++;
}
}
return count;
}
OsrAXNode* OsrAXNode::ChildAtIndex(int index) const {
if (index < GetChildCount())
return accessibility_helper_->GetNode(child_ids_[index]);
else
return NULL;
int count = static_cast<int>(child_ids_.size());
if (index < count)
return accessibility_helper_->GetNode(OsrAXTreeId(), child_ids_[index]);
if ((index == count) && (child_tree_id_ >= 0)) {
OsrAXNode* childTreeRootNode =
accessibility_helper_->GetTreeRootNode(child_tree_id_);
if (childTreeRootNode) {
return childTreeRootNode;
}
}
return NULL;
}
// Create and return the platform specific OsrAXNode Object
OsrAXNode* OsrAXNode::CreateNode(CefRefPtr<CefDictionaryValue> value,
OsrAXNode* OsrAXNode::CreateNode(int treeId,
int nodeId,
CefRefPtr<CefDictionaryValue> value,
OsrAccessibilityHelper* helper) {
return new OsrAXNode(value, helper);
return new OsrAXNode(treeId, nodeId, value, helper);
}
} // namespace client

View File

@ -33,12 +33,17 @@ class OsrAccessibilityHelper;
class OsrAXNode {
public:
// Create and return the platform specific OsrAXNode Object.
static OsrAXNode* CreateNode(CefRefPtr<CefDictionaryValue> value,
static OsrAXNode* CreateNode(int treeId,
int nodeId,
CefRefPtr<CefDictionaryValue> value,
OsrAccessibilityHelper* helper);
// Update Value.
void UpdateValue(CefRefPtr<CefDictionaryValue> value);
// UpdateLocation
void UpdateLocation(CefRefPtr<CefDictionaryValue> value);
// Fire a platform-specific notification that an event has occurred on
// this object.
void NotifyAccessibilityEvent(std::string event_type) const;
@ -58,13 +63,15 @@ class OsrAXNode {
return accessibility_helper_;
}
int GetChildCount() const { return static_cast<int>(child_ids_.size()); }
int GetChildCount() const;
// Return the Child at the specified index
OsrAXNode* ChildAtIndex(int index) const;
const CefString& AxRole() const { return role_; }
int OsrAXTreeId() const { return tree_id_; }
int OsrAXNodeId() const { return node_id_; }
const CefString& AxValue() const { return value_; }
@ -82,15 +89,20 @@ class OsrAXNode {
void SetParent(OsrAXNode* parent);
protected:
OsrAXNode(CefRefPtr<CefDictionaryValue> value,
OsrAXNode(int treeId,
int nodeId,
CefRefPtr<CefDictionaryValue> value,
OsrAccessibilityHelper* helper);
int tree_id_;
int node_id_;
int child_tree_id_;
CefString role_;
CefString value_;
CefString name_;
CefString description_;
CefRect location_;
CefPoint scroll_;
std::vector<int> child_ids_;
CefNativeAccessible* platform_accessibility_;
OsrAXNode* parent_;

View File

@ -347,7 +347,7 @@ STDMETHODIMP CefIAccessible::get_accName(VARIANT varChild, BSTR* pszName) {
HRESULT retCode = DATACHECK(node_);
if (SUCCEEDED(retCode)) {
if (pszName && VALID_CHILDID(varChild)) {
std::string name = node_->AxName();
std::wstring name = node_->AxName();
CComBSTR bstrResult(name.c_str());
*pszName = bstrResult.Detach();
}
@ -362,7 +362,7 @@ STDMETHODIMP CefIAccessible::get_accValue(VARIANT varChild, BSTR* pszValue) {
HRESULT retCode = DATACHECK(node_);
if (SUCCEEDED(retCode)) {
if (pszValue && VALID_CHILDID(varChild)) {
std::string name = node_->AxValue();
std::wstring name = node_->AxValue();
CComBSTR bstrResult(name.c_str());
*pszValue = bstrResult.Detach();
}
@ -378,7 +378,7 @@ STDMETHODIMP CefIAccessible::get_accDescription(VARIANT varChild,
HRESULT retCode = DATACHECK(node_);
if (SUCCEEDED(retCode)) {
if (pszDescription && VALID_CHILDID(varChild)) {
std::string name = node_->AxDescription();
std::wstring name = node_->AxDescription();
CComBSTR bstrResult(name.c_str());
*pszDescription = bstrResult.Detach();
}

View File

@ -1058,6 +1058,16 @@ void OsrWindowWin::UpdateAccessibilityTree(CefRefPtr<CefValue> value) {
#endif // defined(CEF_USE_ATL)
}
void OsrWindowWin::UpdateAccessibilityLocation(CefRefPtr<CefValue> value) {
CEF_REQUIRE_UI_THREAD();
#if defined(CEF_USE_ATL)
if (accessibility_handler_) {
accessibility_handler_->UpdateAccessibilityLocation(value);
}
#endif // defined(CEF_USE_ATL)
}
#if defined(CEF_USE_ATL)
CefBrowserHost::DragOperationsMask OsrWindowWin::OnDragEnter(

View File

@ -146,7 +146,9 @@ class OsrWindowWin
const CefRange& selection_range,
const CefRenderHandler::RectList& character_bounds) OVERRIDE;
void UpdateAccessibilityTree(CefRefPtr<CefValue> value);
void UpdateAccessibilityTree(CefRefPtr<CefValue> value) OVERRIDE;
void UpdateAccessibilityLocation(CefRefPtr<CefValue> value) OVERRIDE;
#if defined(CEF_USE_ATL)
// OsrDragEvents methods.