cef/tests/cefclient/browser/osr_accessibility_node.cc
Andrei Kurushin af349ade33 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
2019-03-21 16:56:06 +00:00

176 lines
5.4 KiB
C++

// Copyright 2017 The Chromium Embedded Framework Authors. Portions copyright
// 2013 The Chromium Authors. All rights reserved. Use of this source code is
// governed by a BSD-style license that can be found in the LICENSE file.
// Base class implementation for CEF Acccessibility node. This is subclassed and
// used by both IAccessible/NSAccessibility protocol implementation.
#include "tests/cefclient/browser/osr_accessibility_node.h"
#include "tests/cefclient/browser/osr_accessibility_helper.h"
namespace client {
OsrAXNode::OsrAXNode(int treeId,
int nodeId,
CefRefPtr<CefDictionaryValue> value,
OsrAccessibilityHelper* helper)
: 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->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;
attributes_ = value->GetDictionary("attributes");
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");
}
}
CefWindowHandle OsrAXNode::GetWindowHandle() const {
if (accessibility_helper_)
return accessibility_helper_->GetWindowHandle();
return NULL;
}
CefRefPtr<CefBrowser> OsrAXNode::GetBrowser() const {
if (accessibility_helper_)
return accessibility_helper_->GetBrowser();
return NULL;
}
void OsrAXNode::SetParent(OsrAXNode* parent) {
parent_ = parent;
}
CefRect OsrAXNode::AxLocation() const {
CefRect loc = location_;
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;
loc.y += offset.y;
}
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 {
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(int treeId,
int nodeId,
CefRefPtr<CefDictionaryValue> value,
OsrAccessibilityHelper* helper) {
return new OsrAXNode(treeId, nodeId, value, helper);
}
} // namespace client