Commit 7cf6d186 authored by Mohamed Mansour's avatar Mohamed Mansour Committed by Commit Bot

Views a11y: Announce Table Columns for TableView

Implements the ITableProvider and ITableItemProvider for UIA.
Currently just supports TableView's column headers. Row headers
are not supported in TableView's control.

AX-Relnotes: Column Headers in TableView are announceable.
Bug: 1078623
Change-Id: I7c8ba49cd8de9fffe471e91c4d6d4e759c9ddc29
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2348541
Commit-Queue: Mohamed Mansour <mmansour@microsoft.com>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799200}
parent 1569b82f
......@@ -21,6 +21,7 @@
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/accessibility/view_ax_platform_node_delegate.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
......@@ -386,7 +387,10 @@ gfx::NativeViewAccessible AXVirtualView::GetFocus() {
}
ui::AXPlatformNode* AXVirtualView::GetFromNodeID(int32_t id) {
// TODO(nektar): Implement.
AXVirtualView* virtual_view = GetFromId(id);
if (virtual_view) {
return virtual_view->ax_platform_node();
}
return nullptr;
}
......@@ -423,6 +427,18 @@ gfx::AcceleratedWidget AXVirtualView::GetTargetForNativeAccessibilityEvent() {
return gfx::kNullAcceleratedWidget;
}
base::Optional<bool> AXVirtualView::GetTableHasColumnOrRowHeaderNode() const {
return GetDelegate()->GetTableHasColumnOrRowHeaderNode();
}
std::vector<int32_t> AXVirtualView::GetColHeaderNodeIds() const {
return GetDelegate()->GetColHeaderNodeIds();
}
std::vector<int32_t> AXVirtualView::GetColHeaderNodeIds(int col_index) const {
return GetDelegate()->GetColHeaderNodeIds(col_index);
}
bool AXVirtualView::IsIgnored() const {
return GetData().IsIgnored();
}
......@@ -473,6 +489,12 @@ View* AXVirtualView::GetOwnerView() const {
return nullptr;
}
ViewAXPlatformNodeDelegate* AXVirtualView::GetDelegate() const {
DCHECK(GetOwnerView());
return static_cast<ViewAXPlatformNodeDelegate*>(
&GetOwnerView()->GetViewAccessibility());
}
AXVirtualViewWrapper* AXVirtualView::GetOrCreateWrapper(
views::AXAuraObjCache* cache) {
#if defined(USE_AURA)
......
......@@ -40,6 +40,7 @@ namespace views {
class AXAuraObjCache;
class View;
class ViewAccessibility;
class ViewAXPlatformNodeDelegate;
// Implements a virtual view that is used only for accessibility.
//
......@@ -99,6 +100,8 @@ class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase {
}
AXVirtualView* virtual_parent_view() { return virtual_parent_view_; }
ui::AXPlatformNode* ax_platform_node() { return ax_platform_node_; }
// Returns true if |view| is contained within the hierarchy of this
// AXVirtualView, even as an indirect descendant. Will return true if |view|
// is also this AXVirtualView.
......@@ -153,10 +156,16 @@ class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase {
bool IsOffscreen() const override;
const ui::AXUniqueId& GetUniqueId() const override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
std::vector<int32_t> GetColHeaderNodeIds() const override;
std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
// Gets the real View that owns our shallowest virtual ancestor,, if any.
View* GetOwnerView() const;
// Gets the view platform delegate if exists, otherwise nullptr.
ViewAXPlatformNodeDelegate* GetDelegate() const;
// Gets or creates a wrapper suitable for use with tree sources.
AXVirtualViewWrapper* GetOrCreateWrapper(views::AXAuraObjCache* cache);
......
......@@ -540,6 +540,46 @@ const ui::AXUniqueId& ViewAXPlatformNodeDelegate::GetUniqueId() const {
return ViewAccessibility::GetUniqueId();
}
base::Optional<bool>
ViewAXPlatformNodeDelegate::GetTableHasColumnOrRowHeaderNode() const {
if (!GetAncestorTableView())
return false;
return !GetAncestorTableView()->visible_columns().empty();
}
std::vector<int32_t> ViewAXPlatformNodeDelegate::GetColHeaderNodeIds() const {
std::vector<int32_t> col_header_ids;
if (!virtual_children().empty()) {
for (const std::unique_ptr<AXVirtualView>& header_cell :
virtual_children().front()->children()) {
const ui::AXNodeData& header_data = header_cell->GetData();
if (header_data.role == ax::mojom::Role::kColumnHeader) {
col_header_ids.push_back(header_data.id);
}
}
}
return col_header_ids;
}
std::vector<int32_t> ViewAXPlatformNodeDelegate::GetColHeaderNodeIds(
int col_index) const {
std::vector<int32_t> columns = GetColHeaderNodeIds();
if (columns.size() <= size_t{col_index}) {
return {};
}
return {columns[col_index]};
}
TableView* ViewAXPlatformNodeDelegate::GetAncestorTableView() const {
ui::AXNodeData data;
view()->GetViewAccessibility().GetAccessibleNodeData(&data);
if (!ui::IsTableLike(data.role))
return nullptr;
return static_cast<TableView*>(view());
}
bool ViewAXPlatformNodeDelegate::IsOrderedSetItem() const {
const ui::AXNodeData& data = GetData();
return (view()->GetGroup() >= 0) ||
......
......@@ -17,6 +17,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/table/table_view.h"
#include "ui/views/widget/widget_observer.h"
namespace ui {
......@@ -83,6 +84,9 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
bool IsMinimized() const override;
// Also in |ViewAccessibility|.
const ui::AXUniqueId& GetUniqueId() const override;
base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
std::vector<int32_t> GetColHeaderNodeIds() const override;
std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
// Ordered-set-like and item-like nodes.
bool IsOrderedSetItem() const override;
......@@ -108,6 +112,9 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
ChildWidgetsResult GetChildWidgets() const;
// Gets the real TableView, otherwise nullptr.
TableView* GetAncestorTableView() const;
// We own this, but it is reference-counted on some platforms so we can't use
// a unique_ptr. It is destroyed in the destructor.
ui::AXPlatformNode* ax_platform_node_;
......
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