File: view_accessibility_utils.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (160 lines) | stat: -rw-r--r-- 5,636 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/accessibility/view_accessibility_utils.h"

#include <algorithm>
#include <set>
#include <string>

#include "base/memory/raw_ptr.h"
#include "ui/accessibility/ax_enum_util.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace views {

// static
Widget* ViewAccessibilityUtils::GetFocusedChildWidgetForAccessibility(
    const View* view) {
  const FocusManager* focus_manager = view->GetFocusManager();
  if (!focus_manager) {
    return nullptr;
  }
  const View* focused_view = view->GetFocusManager()->GetFocusedView();
  if (!focused_view) {
    return nullptr;
  }

  Widget::Widgets child_widgets =
      Widget::GetAllOwnedWidgets(view->GetWidget()->GetNativeView());
  const auto i =
      std::ranges::find_if(child_widgets, [focused_view](Widget* child_widget) {
        return IsFocusedChildWidget(child_widget, focused_view);
      });
  return (i == child_widgets.cend()) ? nullptr : *i;
}

// static
bool ViewAccessibilityUtils::IsFocusedChildWidget(Widget* widget,
                                                  const View* focused_view) {
  return widget->IsVisible() &&
         widget->GetContentsView()->Contains(focused_view);
}

// static
void ViewAccessibilityUtils::Merge(const ui::AXNodeData& source,
                                   ui::AXNodeData& destination) {
  if (source.role != ax::mojom::Role::kUnknown) {
    destination.role = source.role;
  }

  for (const auto& attr : source.int_attributes) {
    destination.AddIntAttribute(attr.first, attr.second);
  }

  for (const auto& attr : source.string_attributes) {
    // Child Tree ID attribute must be added using AddChildTreeId, otherwise
    // DCHECK will be hit.
    if (attr.first == ax::mojom::StringAttribute::kChildTreeId) {
      destination.AddChildTreeId(ui::AXTreeID::FromString(attr.second));
    } else {
      destination.AddStringAttribute(attr.first, attr.second);
    }
  }

  for (const auto& attr : source.bool_attributes) {
    destination.AddBoolAttribute(attr.first, attr.second);
  }

  for (const auto& attr : source.intlist_attributes) {
    destination.AddIntListAttribute(attr.first, attr.second);
  }

  for (const auto& attr : source.stringlist_attributes) {
    destination.AddStringListAttribute(attr.first, attr.second);
  }

  for (const auto& attr : source.float_attributes) {
    destination.AddFloatAttribute(attr.first, attr.second);
  }

  if (!source.relative_bounds.bounds.IsEmpty()) {
    destination.relative_bounds.bounds = source.relative_bounds.bounds;
  }

  if (source.id != ui::kInvalidAXNodeID) {
    destination.id = source.id;
  }

  destination.state |= source.state;

  destination.actions |= source.actions;
}

// static
void ViewAccessibilityUtils::ValidateAttributesNotSet(
    const ui::AXNodeData& new_data,
    const ui::AXNodeData& existing_data) {
  auto attributeErrorMessage = [](std::string attr) -> std::string {
    return "The \"" + attr +
           "\" attribute has been migrated to use the new AXNodeData pipeline. "
           "Please use "
           "the setters/getters in ViewAccessibility to set the attribute."
           "See the comment in ViewAccessibility::GetAccessibleNodeData for "
           "more info.";
  };

  for (const auto& attr : new_data.int_attributes) {
    DCHECK(!existing_data.HasIntAttribute(attr.first))
        << attributeErrorMessage(std::string(ui::ToString(attr.first)));
  }

  for (const auto& attr : new_data.string_attributes) {
    DCHECK(!existing_data.HasStringAttribute(attr.first))
        << attributeErrorMessage(std::string(ui::ToString(attr.first)));
  }

  for (const auto& attr : new_data.bool_attributes) {
    DCHECK(!existing_data.HasBoolAttribute(attr.first))
        << attributeErrorMessage(std::string(ui::ToString(attr.first)));
  }

  for (const auto& attr : new_data.float_attributes) {
    DCHECK(!existing_data.HasFloatAttribute(attr.first))
        << attributeErrorMessage(std::string(ui::ToString(attr.first)));
  }

  for (const auto& attr : new_data.intlist_attributes) {
    DCHECK(!existing_data.HasIntListAttribute(attr.first))
        << attributeErrorMessage(std::string(ui::ToString(attr.first)));
  }

  for (const auto& attr : new_data.stringlist_attributes) {
    DCHECK(!existing_data.HasStringListAttribute(attr.first))
        << attributeErrorMessage(std::string(ui::ToString(attr.first)));
  }

  auto bitfieldErrorMessage = [](std::string bitfield_name) -> std::string {
    return "The accessible " + bitfield_name +
           " should be set directly in the accessibility cache through the "
           "ViewAccessibility setters, not through this lazy loading "
           "mechanism. The purpose of the lazy loading mechanism is to avoid "
           "expensive memory allocations and calculations until the "
           "accessibility tree is actually needed. However, the state is "
           "stored efficiently in a bitfield always initialized to zero, so "
           "there's not performance improvement to be gained by lazy loading "
           "it.";
  };

  DCHECK(new_data.state == 0U) << bitfieldErrorMessage("state");
  DCHECK(new_data.actions == 0U) << bitfieldErrorMessage("action");
  DCHECK(new_data.relative_bounds.bounds.IsEmpty())
      << "The `relative_bounds` should not be set in the lazy loading "
         "function. Instead, use `ViewAccessibility::SetBounds.`";
}

}  // namespace views