Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1024)

Side by Side Diff: content/browser/accessibility/browser_accessibility_manager_win.cc

Issue 1761633002: One accessibility tree per frame. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix is-richly-editable test Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/accessibility/browser_accessibility_manager_win.h" 5 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <vector> 10 #include <vector>
(...skipping 20 matching lines...) Expand all
31 BrowserAccessibilityManagerWin* 31 BrowserAccessibilityManagerWin*
32 BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() { 32 BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() {
33 return static_cast<BrowserAccessibilityManagerWin*>(this); 33 return static_cast<BrowserAccessibilityManagerWin*>(this);
34 } 34 }
35 35
36 BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin( 36 BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin(
37 const ui::AXTreeUpdate& initial_tree, 37 const ui::AXTreeUpdate& initial_tree,
38 BrowserAccessibilityDelegate* delegate, 38 BrowserAccessibilityDelegate* delegate,
39 BrowserAccessibilityFactory* factory) 39 BrowserAccessibilityFactory* factory)
40 : BrowserAccessibilityManager(delegate, factory), 40 : BrowserAccessibilityManager(delegate, factory),
41 tracked_scroll_object_(NULL), 41 tracked_scroll_object_(NULL) {
42 focus_event_on_root_needed_(false),
43 inside_on_window_focused_(false) {
44 ui::win::CreateATLModuleIfNeeded(); 42 ui::win::CreateATLModuleIfNeeded();
45 Initialize(initial_tree); 43 Initialize(initial_tree);
46 ui::GetIAccessible2UsageObserverList().AddObserver(this); 44 ui::GetIAccessible2UsageObserverList().AddObserver(this);
47 } 45 }
48 46
49 BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() { 47 BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
50 // Destroy the tree in the subclass, rather than in the inherited 48 // Destroy the tree in the subclass, rather than in the inherited
51 // destructor, otherwise our overrides of functions like 49 // destructor, otherwise our overrides of functions like
52 // OnNodeWillBeDeleted won't be called. 50 // OnNodeWillBeDeleted won't be called.
53 tree_.reset(NULL); 51 tree_.reset(NULL);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 // Inline text boxes are an internal implementation detail, we don't 110 // Inline text boxes are an internal implementation detail, we don't
113 // expose them to Windows. 111 // expose them to Windows.
114 if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) 112 if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX)
115 return; 113 return;
116 114
117 // It doesn't make sense to fire a REORDER event on a leaf node; that 115 // It doesn't make sense to fire a REORDER event on a leaf node; that
118 // happens when the node has internal children line inline text boxes. 116 // happens when the node has internal children line inline text boxes.
119 if (event == EVENT_OBJECT_REORDER && node->PlatformIsLeaf()) 117 if (event == EVENT_OBJECT_REORDER && node->PlatformIsLeaf())
120 return; 118 return;
121 119
122 // Don't fire focus, or load complete notifications if the
123 // window isn't focused, because that can confuse screen readers into
124 // entering their "browse" mode.
125 if ((event == EVENT_OBJECT_FOCUS ||
126 event == IA2_EVENT_DOCUMENT_LOAD_COMPLETE) &&
127 !NativeViewHasFocus()) {
128 return;
129 }
130
131 // NVDA gets confused if we focus the main document element when it hasn't
132 // finished loading and it has no children at all, so suppress that event.
133 if (event == EVENT_OBJECT_FOCUS &&
134 node == GetRoot() &&
135 node->PlatformChildCount() == 0 &&
136 !node->HasState(ui::AX_STATE_BUSY) &&
137 !node->manager()->GetTreeData().loaded) {
138 return;
139 }
140
141 // If a focus event is needed on the root, fire that first before
142 // this event.
143 if (event == EVENT_OBJECT_FOCUS && node == GetRoot())
144 focus_event_on_root_needed_ = false;
145 else if (focus_event_on_root_needed_)
146 OnWindowFocused();
147
148 // Pass the negation of this node's unique id in the |child_id| 120 // Pass the negation of this node's unique id in the |child_id|
149 // argument to NotifyWinEvent; the AT client will then call get_accChild 121 // argument to NotifyWinEvent; the AT client will then call get_accChild
150 // on the HWND's accessibility object and pass it that same id, which 122 // on the HWND's accessibility object and pass it that same id, which
151 // we can use to retrieve the IAccessible for this node. 123 // we can use to retrieve the IAccessible for this node.
152 LONG child_id = -node->unique_id(); 124 LONG child_id = -node->unique_id();
153 ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id); 125 ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id);
154 } 126 }
155 127
156 void BrowserAccessibilityManagerWin::OnIAccessible2Used() { 128 void BrowserAccessibilityManagerWin::OnIAccessible2Used() {
157 BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected(); 129 BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected();
158 } 130 }
159 131
160 void BrowserAccessibilityManagerWin::OnWindowFocused() {
161 // Make sure we don't call this recursively.
162 if (inside_on_window_focused_)
163 return;
164 inside_on_window_focused_ = true;
165
166 // This is called either when this web frame gets focused, or when
167 // the root of the accessibility tree changes. In both cases, we need
168 // to fire a focus event on the root and then on the focused element
169 // within the page, if different.
170
171 // Set this flag so that we'll keep trying to fire these focus events
172 // if they're not successful this time.
173 focus_event_on_root_needed_ = true;
174
175 if (!NativeViewHasFocus()) {
176 inside_on_window_focused_ = false;
177 return;
178 }
179
180 // Try to fire a focus event on the root first and then the focused node.
181 // This will clear focus_event_on_root_needed_ if successful.
182 if (GetFocus() != GetRoot() && GetRoot())
183 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetRoot());
184 BrowserAccessibilityManager::OnWindowFocused();
185 inside_on_window_focused_ = false;
186 }
187
188 void BrowserAccessibilityManagerWin::UserIsReloading() { 132 void BrowserAccessibilityManagerWin::UserIsReloading() {
189 if (GetRoot()) 133 if (GetRoot())
190 MaybeCallNotifyWinEvent(IA2_EVENT_DOCUMENT_RELOAD, GetRoot()); 134 MaybeCallNotifyWinEvent(IA2_EVENT_DOCUMENT_RELOAD, GetRoot());
191 } 135 }
192 136
193 void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent( 137 void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
194 ui::AXEvent event_type, 138 ui::AXEvent event_type,
195 BrowserAccessibility* node) { 139 BrowserAccessibility* node) {
196 BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager(); 140 BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
197 if (!root_delegate || !root_delegate->AccessibilityGetAcceleratedWidget()) { 141 if (!root_delegate || !root_delegate->AccessibilityGetAcceleratedWidget()) {
(...skipping 14 matching lines...) Expand all
212 // Don't fire focus, blur, or load complete notifications if the 156 // Don't fire focus, blur, or load complete notifications if the
213 // window isn't focused, because that can confuse screen readers into 157 // window isn't focused, because that can confuse screen readers into
214 // entering their "browse" mode. 158 // entering their "browse" mode.
215 if ((event_type == ui::AX_EVENT_FOCUS || 159 if ((event_type == ui::AX_EVENT_FOCUS ||
216 event_type == ui::AX_EVENT_BLUR || 160 event_type == ui::AX_EVENT_BLUR ||
217 event_type == ui::AX_EVENT_LOAD_COMPLETE) && 161 event_type == ui::AX_EVENT_LOAD_COMPLETE) &&
218 !NativeViewHasFocus()) { 162 !NativeViewHasFocus()) {
219 return; 163 return;
220 } 164 }
221 165
222 // NVDA gets confused if we focus the main document element when it hasn't
223 // finished loading and it has no children at all, so suppress that event.
224 if (event_type == ui::AX_EVENT_FOCUS &&
225 node == GetRoot() &&
226 node->PlatformChildCount() == 0 &&
227 !node->HasState(ui::AX_STATE_BUSY) &&
228 !node->manager()->GetTreeData().loaded) {
229 return;
230 }
231
232 // If a focus event is needed on the root, fire that first before
233 // this event.
234 if (event_type == ui::AX_EVENT_FOCUS && node == GetRoot())
235 focus_event_on_root_needed_ = false;
236 else if (focus_event_on_root_needed_)
237 OnWindowFocused();
238
239 LONG event_id = EVENT_MIN; 166 LONG event_id = EVENT_MIN;
240 switch (event_type) { 167 switch (event_type) {
241 case ui::AX_EVENT_ACTIVEDESCENDANTCHANGED: 168 case ui::AX_EVENT_ACTIVEDESCENDANTCHANGED:
242 event_id = IA2_EVENT_ACTIVE_DESCENDANT_CHANGED; 169 event_id = IA2_EVENT_ACTIVE_DESCENDANT_CHANGED;
243 break; 170 break;
244 case ui::AX_EVENT_ALERT: 171 case ui::AX_EVENT_ALERT:
245 event_id = EVENT_SYSTEM_ALERT; 172 event_id = EVENT_SYSTEM_ALERT;
246 break; 173 break;
247 case ui::AX_EVENT_AUTOCORRECTION_OCCURED: 174 case ui::AX_EVENT_AUTOCORRECTION_OCCURED:
248 event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED; 175 event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE && 230 if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE &&
304 tracked_scroll_object_ && 231 tracked_scroll_object_ &&
305 tracked_scroll_object_->IsDescendantOf(node)) { 232 tracked_scroll_object_->IsDescendantOf(node)) {
306 MaybeCallNotifyWinEvent( 233 MaybeCallNotifyWinEvent(
307 IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_); 234 IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_);
308 tracked_scroll_object_->Release(); 235 tracked_scroll_object_->Release();
309 tracked_scroll_object_ = NULL; 236 tracked_scroll_object_ = NULL;
310 } 237 }
311 } 238 }
312 239
240 bool BrowserAccessibilityManagerWin::CanFireEvents() {
241 BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
242 if (!root_delegate)
243 return false;
244 HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget();
245 return hwnd != nullptr;
246 }
247
248 void BrowserAccessibilityManagerWin::FireFocusEvent(
249 BrowserAccessibility* node) {
250 // On Windows, we always fire a FOCUS event on the root of a frame before
251 // firing a focus event within that frame.
252 if (node->manager() != last_focused_manager_ &&
253 node != node->manager()->GetRoot()) {
254 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node->manager()->GetRoot());
255 }
256
257 BrowserAccessibilityManager::FireFocusEvent(node);
258 }
259
313 void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree, 260 void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
314 ui::AXNode* node) { 261 ui::AXNode* node) {
315 DCHECK(node); 262 DCHECK(node);
316 BrowserAccessibilityManager::OnNodeCreated(tree, node); 263 BrowserAccessibilityManager::OnNodeCreated(tree, node);
317 BrowserAccessibility* obj = GetFromAXNode(node); 264 BrowserAccessibility* obj = GetFromAXNode(node);
318 if (!obj) 265 if (!obj)
319 return; 266 return;
320 if (!obj->IsNative()) 267 if (!obj->IsNative())
321 return; 268 return;
322 } 269 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 341
395 void BrowserAccessibilityManagerWin::TrackScrollingObject( 342 void BrowserAccessibilityManagerWin::TrackScrollingObject(
396 BrowserAccessibilityWin* node) { 343 BrowserAccessibilityWin* node) {
397 if (tracked_scroll_object_) 344 if (tracked_scroll_object_)
398 tracked_scroll_object_->Release(); 345 tracked_scroll_object_->Release();
399 tracked_scroll_object_ = node; 346 tracked_scroll_object_ = node;
400 tracked_scroll_object_->AddRef(); 347 tracked_scroll_object_->AddRef();
401 } 348 }
402 349
403 } // namespace content 350 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/accessibility/browser_accessibility_manager_win.h ('k') | content/browser/frame_host/frame_tree.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698