Flutter Engine
The Flutter Engine
Classes | Public Types | Public Member Functions | Friends | List of all members
ui::AXTree Class Reference

#include <ax_tree.h>

Inheritance diagram for ui::AXTree:
ui::AXNode::OwnerTree

Classes

struct  OrderedSetContent
 
struct  OrderedSetItemsMap
 

Public Types

using IntReverseRelationMap = std::map< ax::mojom::IntAttribute, std::map< int32_t, std::set< int32_t > > >
 
using IntListReverseRelationMap = std::map< ax::mojom::IntListAttribute, std::map< int32_t, std::set< int32_t > > >
 

Public Member Functions

 AXTree ()
 
 AXTree (const AXTreeUpdate &initial_state)
 
virtual ~AXTree ()
 
 AXTree (const AXTree &)=delete
 
AXTreeoperator= (const AXTree &)=delete
 
void AddObserver (AXTreeObserver *observer)
 
bool HasObserver (AXTreeObserver *observer)
 
void RemoveObserver (AXTreeObserver *observer)
 
std::vector< AXTreeObserver * > & observers ()
 
AXNoderoot () const
 
const AXTreeDatadata () const
 
void Destroy ()
 
AXTreeID GetAXTreeID () const override
 
AXNodeGetFromId (int32_t id) const override
 
virtual bool Unserialize (const AXTreeUpdate &update)
 
virtual void UpdateData (const AXTreeData &data)
 
gfx::RectF RelativeToTreeBounds (const AXNode *node, gfx::RectF node_bounds, bool *offscreen=nullptr, bool clip_bounds=true) const
 
gfx::RectF GetTreeBounds (const AXNode *node, bool *offscreen=nullptr, bool clip_bounds=true) const
 
std::set< int32_t > GetReverseRelations (ax::mojom::IntAttribute attr, int32_t dst_id) const
 
std::set< int32_t > GetReverseRelations (ax::mojom::IntListAttribute attr, int32_t dst_id) const
 
std::set< int32_t > GetNodeIdsForChildTreeId (AXTreeID child_tree_id) const
 
const std::set< AXTreeIDGetAllChildTreeIds () const
 
const IntReverseRelationMapint_reverse_relations ()
 
const IntListReverseRelationMapintlist_reverse_relations ()
 
std::string ToString () const
 
const std::string & error () const
 
int size ()
 
void SetEnableExtraMacNodes (bool enabled)
 
bool enable_extra_mac_nodes () const
 
int32_t GetNextNegativeInternalNodeId ()
 
std::optional< intGetPosInSet (const AXNode &node) override
 
std::optional< intGetSetSize (const AXNode &node) override
 
Selection GetUnignoredSelection () const override
 
bool GetTreeUpdateInProgressState () const override
 
void SetTreeUpdateInProgressState (bool set_tree_update_value)
 
bool HasPaginationSupport () const override
 
const std::vector< AXEventIntent > & event_intents () const
 
virtual AXTreeID GetAXTreeID () const =0
 
virtual AXTableInfoGetTableInfo (const AXNode *table_node) const =0
 
virtual AXNodeGetFromId (int32_t id) const =0
 
virtual std::optional< intGetPosInSet (const AXNode &node)=0
 
virtual std::optional< intGetSetSize (const AXNode &node)=0
 
virtual Selection GetUnignoredSelection () const =0
 
virtual bool GetTreeUpdateInProgressState () const =0
 
virtual bool HasPaginationSupport () const =0
 

Friends

class AXTableInfoTest
 

Detailed Description

Definition at line 35 of file ax_tree.h.

Member Typedef Documentation

◆ IntListReverseRelationMap

using ui::AXTree::IntListReverseRelationMap = std::map<ax::mojom::IntListAttribute, std::map<int32_t, std::set<int32_t> >>

Definition at line 39 of file ax_tree.h.

◆ IntReverseRelationMap

using ui::AXTree::IntReverseRelationMap = std::map<ax::mojom::IntAttribute, std::map<int32_t, std::set<int32_t> >>

Definition at line 37 of file ax_tree.h.

Constructor & Destructor Documentation

◆ AXTree() [1/3]

ui::AXTree::AXTree ( )

Definition at line 684 of file ax_tree.cc.

684 {
685 AXNodeData root;
687
688 AXTreeUpdate initial_state;
689 initial_state.root_id = AXNode::kInvalidAXID;
690 initial_state.nodes.push_back(root);
691 if (!Unserialize(initial_state)) {
692 BASE_LOG() << error();
694 }
695}
AXID id() const
Definition: ax_node.h:110
static constexpr AXID kInvalidAXID
Definition: ax_node.h:41
const std::string & error() const
Definition: ax_tree.h:134
virtual bool Unserialize(const AXTreeUpdate &update)
Definition: ax_tree.cc:969
AXNode * root() const
Definition: ax_tree.h:57
AXTreeUpdateBase< AXNodeData, AXTreeData > AXTreeUpdate
#define BASE_UNREACHABLE()
Definition: logging.h:69
#define BASE_LOG()
Definition: logging.h:54

◆ AXTree() [2/3]

ui::AXTree::AXTree ( const AXTreeUpdate initial_state)
explicit

Definition at line 697 of file ax_tree.cc.

697 {
698 if (!Unserialize(initial_state)) {
699 BASE_LOG() << error();
701 }
702}

◆ ~AXTree()

ui::AXTree::~AXTree ( )
virtual

Definition at line 704 of file ax_tree.cc.

704 {
705 Destroy();
706}
void Destroy()
Definition: ax_tree.cc:733

◆ AXTree() [3/3]

ui::AXTree::AXTree ( const AXTree )
delete

Member Function Documentation

◆ AddObserver()

void ui::AXTree::AddObserver ( AXTreeObserver observer)

Definition at line 708 of file ax_tree.cc.

708 {
709 observers_.push_back(observer);
710}

◆ data()

const AXTreeData & ui::AXTree::data ( ) const
inline

Definition at line 59 of file ax_tree.h.

59{ return data_; }

◆ Destroy()

void ui::AXTree::Destroy ( )

Definition at line 733 of file ax_tree.cc.

733 {
734 table_info_map_.clear();
735 if (root_) {
736 RecursivelyNotifyNodeDeletedForTreeTeardown(root_);
737 base::AutoReset<bool> update_state_resetter(&tree_update_in_progress_,
738 true);
739 DestroyNodeAndSubtree(root_, nullptr);
740 root_ = nullptr;
741 }
742}

◆ enable_extra_mac_nodes()

bool ui::AXTree::enable_extra_mac_nodes ( ) const
inline

Definition at line 141 of file ax_tree.h.

141{ return enable_extra_mac_nodes_; }

◆ error()

const std::string & ui::AXTree::error ( ) const
inline

Definition at line 134 of file ax_tree.h.

134{ return error_; }

◆ event_intents()

const std::vector< AXEventIntent > & ui::AXTree::event_intents ( ) const
inline

Definition at line 167 of file ax_tree.h.

167 {
168 return event_intents_;
169 }

◆ GetAllChildTreeIds()

const std::set< AXTreeID > ui::AXTree::GetAllChildTreeIds ( ) const

Definition at line 962 of file ax_tree.cc.

962 {
963 std::set<AXTreeID> result;
964 for (auto entry : child_tree_id_reverse_map_)
965 result.insert(entry.first);
966 return result;
967}
GAsyncResult * result

◆ GetAXTreeID()

AXTreeID ui::AXTree::GetAXTreeID ( ) const
overridevirtual

Implements ui::AXNode::OwnerTree.

Definition at line 724 of file ax_tree.cc.

724 {
725 return data().tree_id;
726}
const AXTreeData & data() const
Definition: ax_tree.h:59
AXTreeID tree_id
Definition: ax_tree_data.h:34

◆ GetFromId()

AXNode * ui::AXTree::GetFromId ( int32_t  id) const
overridevirtual

Implements ui::AXNode::OwnerTree.

Definition at line 728 of file ax_tree.cc.

728 {
729 auto iter = id_map_.find(id);
730 return iter != id_map_.end() ? iter->second : nullptr;
731}

◆ GetNextNegativeInternalNodeId()

int32_t ui::AXTree::GetNextNegativeInternalNodeId ( )

Definition at line 1947 of file ax_tree.cc.

1947 {
1948 int32_t return_value = next_negative_internal_node_id_;
1949 next_negative_internal_node_id_--;
1950 if (next_negative_internal_node_id_ > 0)
1951 next_negative_internal_node_id_ = -1;
1952 return return_value;
1953}

◆ GetNodeIdsForChildTreeId()

std::set< int32_t > ui::AXTree::GetNodeIdsForChildTreeId ( AXTreeID  child_tree_id) const

Definition at line 952 of file ax_tree.cc.

953 {
954 // Conceptually, this is the "const" version of:
955 // return child_tree_id_reverse_map_[child_tree_id];
956 const auto& result = child_tree_id_reverse_map_.find(child_tree_id);
957 if (result != child_tree_id_reverse_map_.end())
958 return result->second;
959 return std::set<int32_t>();
960}

◆ GetPosInSet()

std::optional< int > ui::AXTree::GetPosInSet ( const AXNode node)
overridevirtual

Implements ui::AXNode::OwnerTree.

Definition at line 2252 of file ax_tree.cc.

2252 {
2253 if (node.data().role == ax::mojom::Role::kPopUpButton &&
2254 node.GetUnignoredChildCount() == 0 &&
2255 node.HasIntAttribute(ax::mojom::IntAttribute::kPosInSet)) {
2256 return node.GetIntAttribute(ax::mojom::IntAttribute::kPosInSet);
2257 }
2258
2259 if (node_set_size_pos_in_set_info_map_.find(node.id()) !=
2260 node_set_size_pos_in_set_info_map_.end()) {
2261 // If item's id is in the cache, return stored PosInSet value.
2262 return node_set_size_pos_in_set_info_map_[node.id()].pos_in_set;
2263 }
2264
2266 return std::nullopt;
2267
2268 // Only allow this to be called on nodes that can hold PosInSet values,
2269 // which are defined in the ARIA spec.
2270 if (!node.IsOrderedSetItem() || node.IsIgnored())
2271 return std::nullopt;
2272
2273 const AXNode* ordered_set = node.GetOrderedSet();
2274 if (!ordered_set)
2275 return std::nullopt;
2276
2277 // Compute, cache, then return.
2278 ComputeSetSizePosInSetAndCache(node, ordered_set);
2279 std::optional<int> pos_in_set =
2280 node_set_size_pos_in_set_info_map_[node.id()].pos_in_set;
2281 if (pos_in_set.has_value() && pos_in_set.value() < 1)
2282 return std::nullopt;
2283
2284 return pos_in_set;
2285}
bool GetTreeUpdateInProgressState() const override
Definition: ax_tree.cc:2463

◆ GetReverseRelations() [1/2]

std::set< int32_t > ui::AXTree::GetReverseRelations ( ax::mojom::IntAttribute  attr,
int32_t  dst_id 
) const

Definition at line 922 of file ax_tree.cc.

923 {
925
926 // Conceptually, this is the "const" version of:
927 // return int_reverse_relations_[attr][dst_id];
928 const auto& attr_relations = int_reverse_relations_.find(attr);
929 if (attr_relations != int_reverse_relations_.end()) {
930 const auto& result = attr_relations->second.find(dst_id);
931 if (result != attr_relations->second.end())
932 return result->second;
933 }
934 return std::set<int32_t>();
935}
bool IsNodeIdIntAttribute(ax::mojom::IntAttribute attr)
Definition: ax_node_data.cc:99
#define BASE_DCHECK(condition)
Definition: logging.h:63

◆ GetReverseRelations() [2/2]

std::set< int32_t > ui::AXTree::GetReverseRelations ( ax::mojom::IntListAttribute  attr,
int32_t  dst_id 
) const

Definition at line 937 of file ax_tree.cc.

938 {
940
941 // Conceptually, this is the "const" version of:
942 // return intlist_reverse_relations_[attr][dst_id];
943 const auto& attr_relations = intlist_reverse_relations_.find(attr);
944 if (attr_relations != intlist_reverse_relations_.end()) {
945 const auto& result = attr_relations->second.find(dst_id);
946 if (result != attr_relations->second.end())
947 return result->second;
948 }
949 return std::set<int32_t>();
950}
bool IsNodeIdIntListAttribute(ax::mojom::IntListAttribute attr)

◆ GetSetSize()

std::optional< int > ui::AXTree::GetSetSize ( const AXNode node)
overridevirtual

Implements ui::AXNode::OwnerTree.

Definition at line 2287 of file ax_tree.cc.

2287 {
2288 if (node.data().role == ax::mojom::Role::kPopUpButton &&
2289 node.GetUnignoredChildCount() == 0 &&
2290 node.HasIntAttribute(ax::mojom::IntAttribute::kSetSize)) {
2291 return node.GetIntAttribute(ax::mojom::IntAttribute::kSetSize);
2292 }
2293
2294 if (node_set_size_pos_in_set_info_map_.find(node.id()) !=
2295 node_set_size_pos_in_set_info_map_.end()) {
2296 // If item's id is in the cache, return stored SetSize value.
2297 return node_set_size_pos_in_set_info_map_[node.id()].set_size;
2298 }
2299
2301 return std::nullopt;
2302
2303 // Only allow this to be called on nodes that can hold SetSize values, which
2304 // are defined in the ARIA spec. However, we allow set-like items to receive
2305 // SetSize values for internal purposes.
2306 if ((!node.IsOrderedSetItem() && !node.IsOrderedSet()) || node.IsIgnored() ||
2307 node.IsEmbeddedGroup()) {
2308 return std::nullopt;
2309 }
2310
2311 // If |node| is item-like, find its outerlying ordered set. Otherwise,
2312 // |node| is the ordered set.
2313 const AXNode* ordered_set = &node;
2314 if (IsItemLike(node.data().role))
2315 ordered_set = node.GetOrderedSet();
2316 if (!ordered_set)
2317 return std::nullopt;
2318
2319 // For popup buttons that control a single element, inherit the controlled
2320 // item's SetSize. Skip this block if the popup button controls itself.
2321 if (node.data().role == ax::mojom::Role::kPopUpButton) {
2322 const auto& controls_ids = node.data().GetIntListAttribute(
2324 if (controls_ids.size() == 1 && GetFromId(controls_ids[0]) &&
2325 controls_ids[0] != node.id()) {
2326 const AXNode& controlled_item = *GetFromId(controls_ids[0]);
2327
2328 std::optional<int> controlled_item_set_size = GetSetSize(controlled_item);
2329 node_set_size_pos_in_set_info_map_[node.id()].set_size =
2330 controlled_item_set_size;
2331 return controlled_item_set_size;
2332 }
2333 }
2334
2335 // Compute, cache, then return.
2336 ComputeSetSizePosInSetAndCache(node, ordered_set);
2337 std::optional<int> set_size =
2338 node_set_size_pos_in_set_info_map_[node.id()].set_size;
2339 if (set_size.has_value() && set_size.value() < 0)
2340 return std::nullopt;
2341
2342 return set_size;
2343}
AXNode * GetFromId(int32_t id) const override
Definition: ax_tree.cc:728
std::optional< int > GetSetSize(const AXNode &node) override
Definition: ax_tree.cc:2287
bool IsItemLike(const ax::mojom::Role role)

◆ GetTreeBounds()

gfx::RectF ui::AXTree::GetTreeBounds ( const AXNode node,
bool *  offscreen = nullptr,
bool  clip_bounds = true 
) const

Definition at line 916 of file ax_tree.cc.

918 {
919 return RelativeToTreeBounds(node, gfx::RectF(), offscreen, clip_bounds);
920}
gfx::RectF RelativeToTreeBounds(const AXNode *node, gfx::RectF node_bounds, bool *offscreen=nullptr, bool clip_bounds=true) const
Definition: ax_tree.cc:907

◆ GetTreeUpdateInProgressState()

bool ui::AXTree::GetTreeUpdateInProgressState ( ) const
overridevirtual

Implements ui::AXNode::OwnerTree.

Definition at line 2463 of file ax_tree.cc.

2463 {
2464 return tree_update_in_progress_;
2465}

◆ GetUnignoredSelection()

AXTree::Selection ui::AXTree::GetUnignoredSelection ( ) const
overridevirtual

Implements ui::AXNode::OwnerTree.

Definition at line 2345 of file ax_tree.cc.

2345 {
2346 Selection unignored_selection = {
2351 AXNode* anchor_node = GetFromId(data().sel_anchor_object_id);
2352 AXNode* focus_node = GetFromId(data().sel_focus_object_id);
2353
2354 AXNodePosition::AXPositionInstance anchor_position =
2355 anchor_node ? AXNodePosition::CreatePosition(*anchor_node,
2356 data().sel_anchor_offset,
2357 data().sel_anchor_affinity)
2358 : AXNodePosition::CreateNullPosition();
2359
2360 // Null positions are never ignored.
2361 if (anchor_position->IsIgnored()) {
2362 anchor_position = anchor_position->AsUnignoredPosition(
2365
2366 // Any selection endpoint that is inside a leaf node is expressed as a text
2367 // position in AXTreeData.
2368 if (anchor_position->IsLeafTreePosition())
2369 anchor_position = anchor_position->AsTextPosition();
2370
2371 // We do not expect the selection to have an endpoint on an inline text
2372 // box as this will create issues with parts of the code that don't use
2373 // inline text boxes.
2374 if (anchor_position->IsTextPosition() &&
2375 anchor_position->GetAnchor()->data().role ==
2377 anchor_position = anchor_position->CreateParentPosition();
2378 }
2379
2380 switch (anchor_position->kind()) {
2382 // If one of the selection endpoints is invalid, then both endpoints
2383 // should be unset.
2384 unignored_selection.anchor_object_id = AXNode::kInvalidAXID;
2385 unignored_selection.anchor_offset = -1;
2386 unignored_selection.anchor_affinity =
2388 unignored_selection.focus_object_id = AXNode::kInvalidAXID;
2389 unignored_selection.focus_offset = -1;
2390 unignored_selection.focus_affinity =
2392 return unignored_selection;
2394 unignored_selection.anchor_object_id = anchor_position->anchor_id();
2395 unignored_selection.anchor_offset = anchor_position->child_index();
2396 unignored_selection.anchor_affinity =
2398 break;
2400 unignored_selection.anchor_object_id = anchor_position->anchor_id();
2401 unignored_selection.anchor_offset = anchor_position->text_offset();
2402 unignored_selection.anchor_affinity = anchor_position->affinity();
2403 break;
2404 }
2405 }
2406
2407 AXNodePosition::AXPositionInstance focus_position =
2408 focus_node
2409 ? AXNodePosition::CreatePosition(*focus_node, data().sel_focus_offset,
2410 data().sel_focus_affinity)
2411 : AXNodePosition::CreateNullPosition();
2412
2413 // Null positions are never ignored.
2414 if (focus_position->IsIgnored()) {
2415 focus_position = focus_position->AsUnignoredPosition(
2418
2419 // Any selection endpoint that is inside a leaf node is expressed as a text
2420 // position in AXTreeData.
2421 if (focus_position->IsLeafTreePosition())
2422 focus_position = focus_position->AsTextPosition();
2423
2424 // We do not expect the selection to have an endpoint on an inline text
2425 // box as this will create issues with parts of the code that don't use
2426 // inline text boxes.
2427 if (focus_position->IsTextPosition() &&
2428 focus_position->GetAnchor()->data().role ==
2430 focus_position = focus_position->CreateParentPosition();
2431 }
2432
2433 switch (focus_position->kind()) {
2435 // If one of the selection endpoints is invalid, then both endpoints
2436 // should be unset.
2437 unignored_selection.anchor_object_id = AXNode::kInvalidAXID;
2438 unignored_selection.anchor_offset = -1;
2439 unignored_selection.anchor_affinity =
2441 unignored_selection.focus_object_id = AXNode::kInvalidAXID;
2442 unignored_selection.focus_offset = -1;
2443 unignored_selection.focus_affinity =
2445 return unignored_selection;
2447 unignored_selection.focus_object_id = focus_position->anchor_id();
2448 unignored_selection.focus_offset = focus_position->child_index();
2449 unignored_selection.focus_affinity =
2451 break;
2453 unignored_selection.focus_object_id = focus_position->anchor_id();
2454 unignored_selection.focus_offset = focus_position->text_offset();
2455 unignored_selection.focus_affinity = focus_position->affinity();
2456 break;
2457 }
2458 }
2459
2460 return unignored_selection;
2461}
static AXPositionInstance CreatePosition(const AXNode &node, int child_index_or_text_offset, ax::mojom::TextAffinity affinity=ax::mojom::TextAffinity::kDownstream)
std::unique_ptr< AXPosition< AXNodePosition, AXNode > > AXPositionInstance
Definition: ax_position.h:163
bool sel_is_backward
Definition: ax_tree_data.h:61
AXNode::AXID sel_anchor_object_id
Definition: ax_tree_data.h:62
ax::mojom::TextAffinity sel_focus_affinity
Definition: ax_tree_data.h:67
AXNode::AXID sel_focus_object_id
Definition: ax_tree_data.h:65
int32_t sel_focus_offset
Definition: ax_tree_data.h:66
ax::mojom::TextAffinity sel_anchor_affinity
Definition: ax_tree_data.h:64
int32_t sel_anchor_offset
Definition: ax_tree_data.h:63

◆ HasObserver()

bool ui::AXTree::HasObserver ( AXTreeObserver observer)

Definition at line 712 of file ax_tree.cc.

712 {
713 return std::find(observers_.begin(), observers_.end(), observer) !=
714 observers_.end();
715}
int find(T *array, int N, T item)

◆ HasPaginationSupport()

bool ui::AXTree::HasPaginationSupport ( ) const
overridevirtual

Implements ui::AXNode::OwnerTree.

Definition at line 2471 of file ax_tree.cc.

2471 {
2472 return has_pagination_support_;
2473}

◆ int_reverse_relations()

const IntReverseRelationMap & ui::AXTree::int_reverse_relations ( )
inline

Definition at line 122 of file ax_tree.h.

122 {
123 return int_reverse_relations_;
124 }

◆ intlist_reverse_relations()

const IntListReverseRelationMap & ui::AXTree::intlist_reverse_relations ( )
inline

Definition at line 125 of file ax_tree.h.

125 {
126 return intlist_reverse_relations_;
127 }

◆ observers()

std::vector< AXTreeObserver * > & ui::AXTree::observers ( )
inline

Definition at line 55 of file ax_tree.h.

55{ return observers_; }

◆ operator=()

AXTree & ui::AXTree::operator= ( const AXTree )
delete

◆ RelativeToTreeBounds()

gfx::RectF ui::AXTree::RelativeToTreeBounds ( const AXNode node,
gfx::RectF  node_bounds,
bool *  offscreen = nullptr,
bool  clip_bounds = true 
) const

Definition at line 907 of file ax_tree.cc.

910 {
911 bool allow_recursion = true;
912 return RelativeToTreeBoundsInternal(node, bounds, offscreen, clip_bounds,
913 allow_recursion);
914}
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ RemoveObserver()

void ui::AXTree::RemoveObserver ( AXTreeObserver observer)

Definition at line 717 of file ax_tree.cc.

717 {
718 const auto it = std::find(observers_.begin(), observers_.end(), observer);
719 if (it == observers_.end())
720 return;
721 observers_.erase(it);
722}

◆ root()

AXNode * ui::AXTree::root ( ) const
inline

Definition at line 57 of file ax_tree.h.

57{ return root_; }

◆ SetEnableExtraMacNodes()

void ui::AXTree::SetEnableExtraMacNodes ( bool  enabled)

Definition at line 1933 of file ax_tree.cc.

1933 {
1934 if (enable_extra_mac_nodes_ == enabled)
1935 return; // No change.
1936 if (enable_extra_mac_nodes_ && !enabled) {
1937 BASE_LOG()
1938 << "We don't support disabling the extra Mac nodes once enabled.";
1940 return;
1941 }
1942
1943 BASE_DCHECK(0U == table_info_map_.size());
1944 enable_extra_mac_nodes_ = enabled;
1945}

◆ SetTreeUpdateInProgressState()

void ui::AXTree::SetTreeUpdateInProgressState ( bool  set_tree_update_value)

Definition at line 2467 of file ax_tree.cc.

2467 {
2468 tree_update_in_progress_ = set_tree_update_value;
2469}

◆ size()

int ui::AXTree::size ( )
inline

Definition at line 136 of file ax_tree.h.

136{ return static_cast<int>(id_map_.size()); }

◆ ToString()

std::string ui::AXTree::ToString ( ) const

Definition at line 1240 of file ax_tree.cc.

1240 {
1241 return "AXTree" + data_.ToString() + "\n" + TreeToStringHelper(root_, 0);
1242}
virtual std::string ToString() const
Definition: ax_tree_data.cc:24

◆ Unserialize()

bool ui::AXTree::Unserialize ( const AXTreeUpdate update)
virtual

Definition at line 969 of file ax_tree.cc.

969 {
970 AXTreeUpdateState update_state(*this);
971 const AXNode::AXID old_root_id = root_ ? root_->id() : AXNode::kInvalidAXID;
972
973 // Accumulates the work that will be required to update the AXTree.
974 // This allows us to notify observers of structure changes when the
975 // tree is still in a stable and unchanged state.
976 if (!ComputePendingChanges(update, &update_state))
977 return false;
978
979 // Notify observers of subtrees and nodes that are about to be destroyed or
980 // reparented, this must be done before applying any updates to the tree.
981 for (auto&& pair : update_state.node_id_to_pending_data) {
982 const AXNode::AXID node_id = pair.first;
983 const std::unique_ptr<PendingStructureChanges>& data = pair.second;
984 if (data->DoesNodeExpectSubtreeOrNodeWillBeDestroyed()) {
985 if (AXNode* node = GetFromId(node_id)) {
986 if (data->DoesNodeExpectSubtreeWillBeDestroyed())
987 NotifySubtreeWillBeReparentedOrDeleted(node, &update_state);
988 if (data->DoesNodeExpectNodeWillBeDestroyed())
989 NotifyNodeWillBeReparentedOrDeleted(node, &update_state);
990 }
991 }
992 }
993
994 // Notify observers of nodes that are about to change their data.
995 // This must be done before applying any updates to the tree.
996 // This is iterating in reverse order so that we only notify once per node id,
997 // and that we only notify the initial node data against the final node data,
998 // unless the node is a new root.
999 std::set<int32_t> notified_node_data_will_change;
1000 for (size_t i = update.nodes.size(); i-- > 0;) {
1001 const AXNodeData& new_data = update.nodes[i];
1002 const bool is_new_root =
1003 update_state.root_will_be_created && new_data.id == update.root_id;
1004 if (!is_new_root) {
1005 AXNode* node = GetFromId(new_data.id);
1006 if (node && notified_node_data_will_change.insert(new_data.id).second)
1007 NotifyNodeDataWillChange(node->data(), new_data);
1008 }
1009 }
1010
1011 // Now that we have finished sending events for changes that will happen,
1012 // set update state to true. |tree_update_in_progress_| gets set back to
1013 // false whenever this function exits.
1014 base::AutoReset<bool> update_state_resetter(&tree_update_in_progress_, true);
1015
1016 // Handle |node_id_to_clear| before applying ordinary node updates.
1017 // We distinguish between updating the root, e.g. changing its children or
1018 // some of its attributes, or replacing the root completely. If the root is
1019 // being updated, update.node_id_to_clear should hold the current root's ID.
1020 // Otherwise if the root is being replaced, update.root_id should hold the ID
1021 // of the new root.
1022 bool root_updated = false;
1023 if (update.node_id_to_clear != AXNode::kInvalidAXID) {
1024 if (AXNode* cleared_node = GetFromId(update.node_id_to_clear)) {
1025 BASE_DCHECK(root_);
1026 if (cleared_node == root_) {
1027 // Only destroy the root if the root was replaced and not if it's simply
1028 // updated. To figure out if the root was simply updated, we compare
1029 // the ID of the new root with the existing root ID.
1030 if (update.root_id != old_root_id) {
1031 // Clear root_ before calling DestroySubtree so that root_ doesn't
1032 // ever point to an invalid node.
1033 AXNode* old_root = root_;
1034 root_ = nullptr;
1035 DestroySubtree(old_root, &update_state);
1036 } else {
1037 // If the root has simply been updated, we treat it like an update to
1038 // any other node.
1039 root_updated = true;
1040 }
1041 }
1042
1043 // If the tree doesn't exists any more because the root has just been
1044 // replaced, there is nothing more to clear.
1045 if (root_) {
1046 for (auto* child : cleared_node->children())
1047 DestroySubtree(child, &update_state);
1048 std::vector<AXNode*> children;
1049 cleared_node->SwapChildren(&children);
1050 update_state.pending_nodes.insert(cleared_node->id());
1051 }
1052 }
1053 }
1054
1055 BASE_DCHECK(!GetFromId(update.root_id) == update_state.root_will_be_created);
1056
1057 // Update the tree data, do not call |UpdateData| since we want to defer
1058 // the |OnTreeDataChanged| event until after the tree has finished updating.
1059 if (update.has_tree_data && data_ != update.tree_data) {
1060 update_state.old_tree_data = data_;
1061 data_ = update.tree_data;
1062 }
1063
1064 // Update all of the nodes in the update.
1065 for (size_t i = 0; i < update.nodes.size(); ++i) {
1066 const bool is_new_root = update_state.root_will_be_created &&
1067 update.nodes[i].id == update.root_id;
1068 if (!UpdateNode(update.nodes[i], is_new_root, &update_state))
1069 return false;
1070 }
1071
1072 if (!root_) {
1073 error_ = "Tree has no root.";
1074 return false;
1075 }
1076
1077 if (!ValidatePendingChangesComplete(update_state))
1078 return false;
1079
1080 // Look for changes to nodes that are a descendant of a table,
1081 // and invalidate their table info if so. We have to walk up the
1082 // ancestry of every node that was updated potentially, so keep track of
1083 // ids that were checked to eliminate duplicate work.
1084 std::set<int32_t> table_ids_checked;
1085 for (size_t i = 0; i < update.nodes.size(); ++i) {
1086 AXNode* node = GetFromId(update.nodes[i].id);
1087 while (node) {
1088 if (table_ids_checked.find(node->id()) != table_ids_checked.end())
1089 break;
1090 // Remove any table infos.
1091 const auto& table_info_entry = table_info_map_.find(node->id());
1092 if (table_info_entry != table_info_map_.end())
1093 table_info_entry->second->Invalidate();
1094 table_ids_checked.insert(node->id());
1095 node = node->parent();
1096 }
1097 }
1098
1099 // Clears |node_set_size_pos_in_set_info_map_|
1100 node_set_size_pos_in_set_info_map_.clear();
1101
1102 std::vector<AXTreeObserver::Change> changes;
1103 changes.reserve(update.nodes.size());
1104 std::set<AXNode::AXID> visited_observer_changes;
1105 for (size_t i = 0; i < update.nodes.size(); ++i) {
1106 AXNode* node = GetFromId(update.nodes[i].id);
1107 if (!node || !visited_observer_changes.emplace(update.nodes[i].id).second)
1108 continue;
1109
1110 bool is_new_node = update_state.IsCreatedNode(node);
1111 bool is_reparented_node = update_state.IsReparentedNode(node);
1112
1114 if (is_new_node) {
1115 if (is_reparented_node) {
1116 // A reparented subtree is any new node whose parent either doesn't
1117 // exist, or whose parent is not new.
1118 // Note that we also need to check for the special case when we update
1119 // the root without replacing it.
1120 bool is_subtree = !node->parent() ||
1121 !update_state.IsCreatedNode(node->parent()) ||
1122 (node->parent() == root_ && root_updated);
1123 change = is_subtree ? AXTreeObserver::SUBTREE_REPARENTED
1125 } else {
1126 // A new subtree is any new node whose parent is either not new, or
1127 // whose parent happens to be new only because it has been reparented.
1128 // Note that we also need to check for the special case when we update
1129 // the root without replacing it.
1130 bool is_subtree = !node->parent() ||
1131 !update_state.IsCreatedNode(node->parent()) ||
1132 update_state.IsRemovedNode(node->parent()) ||
1133 (node->parent() == root_ && root_updated);
1134 change = is_subtree ? AXTreeObserver::SUBTREE_CREATED
1136 }
1137 }
1138 changes.push_back(AXTreeObserver::Change(node, change));
1139 }
1140
1141 // Update the unignored cached values as necessary, ensuring that we only
1142 // update once for each unignored node.
1143 // If the node is ignored, we must update from an unignored ancestor.
1144 std::set<AXNode::AXID> updated_unignored_cached_values_ids;
1145 for (AXNode::AXID node_id :
1146 update_state.invalidate_unignored_cached_values_ids) {
1147 AXNode* node = GetFromId(node_id);
1148 while (node && node->data().IsIgnored())
1149 node = node->parent();
1150 if (node && updated_unignored_cached_values_ids.insert(node->id()).second)
1151 node->UpdateUnignoredCachedValues();
1152 }
1153
1154 // Tree is no longer updating.
1156
1157 // Now that the tree is stable and its nodes have been updated, notify if
1158 // the tree data changed. We must do this after updating nodes in case the
1159 // root has been replaced, so observers have the most up-to-date information.
1160 if (update_state.old_tree_data) {
1161 for (AXTreeObserver* observer : observers_)
1162 observer->OnTreeDataChanged(this, *update_state.old_tree_data, data_);
1163 }
1164
1165 // Now that the unignored cached values are up to date, update observers to
1166 // the nodes that were deleted from the tree but not reparented.
1167 for (AXNode::AXID node_id : update_state.removed_node_ids) {
1168 if (!update_state.IsCreatedNode(node_id))
1169 NotifyNodeHasBeenDeleted(node_id);
1170 }
1171
1172 // Now that the unignored cached values are up to date, update observers to
1173 // new nodes in the tree.
1174 for (AXNode::AXID node_id : update_state.new_node_ids)
1175 NotifyNodeHasBeenReparentedOrCreated(GetFromId(node_id), &update_state);
1176
1177 // Now that the unignored cached values are up to date, update observers to
1178 // node changes.
1179 for (AXNode::AXID node_data_changed_id : update_state.node_data_changed_ids) {
1180 AXNode* node = GetFromId(node_data_changed_id);
1181 BASE_DCHECK(node);
1182
1183 // If the node exists and is in the old data map, then the node data
1184 // may have changed unless this is a new root.
1185 const bool is_new_root = update_state.root_will_be_created &&
1186 node_data_changed_id == update.root_id;
1187 if (!is_new_root) {
1188 auto it = update_state.old_node_id_to_data.find(node_data_changed_id);
1189 if (it != update_state.old_node_id_to_data.end()) {
1190 const AXNodeData& old_node_data = it->second;
1191 NotifyNodeDataHasBeenChanged(node, old_node_data, node->data());
1192 }
1193 }
1194
1195 // |OnNodeChanged| should be fired for all nodes that have been updated.
1196 for (AXTreeObserver* observer : observers_)
1197 observer->OnNodeChanged(this, node);
1198 }
1199
1200 for (AXTreeObserver* observer : observers_)
1201 observer->OnAtomicUpdateFinished(this, root_->id() != old_root_id, changes);
1202
1203 return true;
1204}
int32_t AXID
Definition: ax_node.h:36
void SetTreeUpdateInProgressState(bool set_tree_update_value)
Definition: ax_tree.cc:2467
Definition: update.py:1

◆ UpdateData()

void ui::AXTree::UpdateData ( const AXTreeData data)
virtual

Definition at line 744 of file ax_tree.cc.

744 {
745 if (data_ == new_data)
746 return;
747
748 AXTreeData old_data = data_;
749 data_ = new_data;
750 for (AXTreeObserver* observer : observers_)
751 observer->OnTreeDataChanged(this, old_data, new_data);
752}

Friends And Related Function Documentation

◆ AXTableInfoTest

friend class AXTableInfoTest
friend

Definition at line 172 of file ax_tree.h.


The documentation for this class was generated from the following files: