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

@@ -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