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

Side by Side Diff: ui/views/accessibility/native_view_accessibility_win.cc

Issue 23506027: Implement web content hit testing in win aura. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fix compile error Created 7 years, 3 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 "ui/views/accessibility/native_view_accessibility_win.h" 5 #include "ui/views/accessibility/native_view_accessibility_win.h"
6 6
7 #include <UIAutomationClient.h> 7 #include <UIAutomationClient.h>
8 #include <oleacc.h> 8 #include <oleacc.h>
9 9
10 #include <set> 10 #include <set>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/memory/singleton.h" 13 #include "base/memory/singleton.h"
14 #include "base/strings/utf_string_conversions.h"
14 #include "base/win/windows_version.h" 15 #include "base/win/windows_version.h"
15 #include "third_party/iaccessible2/ia2_api_all.h" 16 #include "third_party/iaccessible2/ia2_api_all.h"
16 #include "ui/base/accessibility/accessible_text_utils.h" 17 #include "ui/base/accessibility/accessible_text_utils.h"
17 #include "ui/base/accessibility/accessible_view_state.h" 18 #include "ui/base/accessibility/accessible_view_state.h"
18 #include "ui/base/win/accessibility_ids_win.h" 19 #include "ui/base/win/accessibility_ids_win.h"
19 #include "ui/base/win/accessibility_misc_utils.h" 20 #include "ui/base/win/accessibility_misc_utils.h"
20 #include "ui/base/win/atl_module.h" 21 #include "ui/base/win/atl_module.h"
21 #include "ui/views/controls/button/custom_button.h" 22 #include "ui/views/controls/button/custom_button.h"
22 #include "ui/views/focus/focus_manager.h" 23 #include "ui/views/focus/focus_manager.h"
23 #include "ui/views/focus/view_storage.h" 24 #include "ui/views/focus/view_storage.h"
24 #include "ui/views/win/hwnd_util.h" 25 #include "ui/views/win/hwnd_util.h"
25 26
26 using ui::AccessibilityTypes; 27 using ui::AccessibilityTypes;
27 28
28 namespace views { 29 namespace views {
29 namespace { 30 namespace {
30 31
31 class AccessibleWebViewRegistry { 32 class AccessibleWebViewRegistry {
32 public: 33 public:
33 static AccessibleWebViewRegistry* GetInstance(); 34 static AccessibleWebViewRegistry* GetInstance();
34 35
35 void RegisterWebView(AccessibleWebView* web_view); 36 void RegisterWebView(View* web_view);
36 37
37 void UnregisterWebView(AccessibleWebView* web_view); 38 void UnregisterWebView(View* web_view);
38 39
39 // Given the view that received the request for the accessible 40 // Given the view that received the request for the accessible
40 // id in |top_view|, and the child id requested, return the native 41 // id in |top_view|, and the child id requested, return the native
41 // accessible object with that child id from one of the WebViews in 42 // accessible object with that child id from one of the WebViews in
42 // |top_view|'s view hierarchy, if any. 43 // |top_view|'s view hierarchy, if any.
43 IAccessible* GetAccessibleFromWebView(View* top_view, long child_id); 44 IAccessible* GetAccessibleFromWebView(View* top_view, long child_id);
44 45
45 private: 46 private:
46 friend struct DefaultSingletonTraits<AccessibleWebViewRegistry>; 47 friend struct DefaultSingletonTraits<AccessibleWebViewRegistry>;
47 AccessibleWebViewRegistry(); 48 AccessibleWebViewRegistry();
48 ~AccessibleWebViewRegistry() {} 49 ~AccessibleWebViewRegistry() {}
49 50
51 IAccessible* AccessibleObjectFromChildId(View* web_view, long child_id);
52
50 // Set of all web views. We check whether each one is contained in a 53 // Set of all web views. We check whether each one is contained in a
51 // top view dynamically rather than keeping track of a map. 54 // top view dynamically rather than keeping track of a map.
52 std::set<AccessibleWebView*> web_views_; 55 std::set<View*> web_views_;
53 56
54 // The most recent top view used in a call to GetAccessibleFromWebView. 57 // The most recent top view used in a call to GetAccessibleFromWebView.
55 View* last_top_view_; 58 View* last_top_view_;
56 59
57 // The most recent web view where an accessible object was found, 60 // The most recent web view where an accessible object was found,
58 // corresponding to |last_top_view_|. 61 // corresponding to |last_top_view_|.
59 AccessibleWebView* last_web_view_; 62 View* last_web_view_;
60 63
61 DISALLOW_COPY_AND_ASSIGN(AccessibleWebViewRegistry); 64 DISALLOW_COPY_AND_ASSIGN(AccessibleWebViewRegistry);
62 }; 65 };
63 66
64 AccessibleWebViewRegistry::AccessibleWebViewRegistry() 67 AccessibleWebViewRegistry::AccessibleWebViewRegistry()
65 : last_top_view_(NULL), 68 : last_top_view_(NULL),
66 last_web_view_(NULL) { 69 last_web_view_(NULL) {
67 } 70 }
68 71
69 AccessibleWebViewRegistry* AccessibleWebViewRegistry::GetInstance() { 72 AccessibleWebViewRegistry* AccessibleWebViewRegistry::GetInstance() {
70 return Singleton<AccessibleWebViewRegistry>::get(); 73 return Singleton<AccessibleWebViewRegistry>::get();
71 } 74 }
72 75
73 void AccessibleWebViewRegistry::RegisterWebView(AccessibleWebView* web_view) { 76 void AccessibleWebViewRegistry::RegisterWebView(View* web_view) {
74 DCHECK(web_views_.find(web_view) == web_views_.end()); 77 DCHECK(web_views_.find(web_view) == web_views_.end());
75 web_views_.insert(web_view); 78 web_views_.insert(web_view);
76 } 79 }
77 80
78 void AccessibleWebViewRegistry::UnregisterWebView(AccessibleWebView* web_view) { 81 void AccessibleWebViewRegistry::UnregisterWebView(View* web_view) {
79 DCHECK(web_views_.find(web_view) != web_views_.end()); 82 DCHECK(web_views_.find(web_view) != web_views_.end());
80 web_views_.erase(web_view); 83 web_views_.erase(web_view);
81 if (last_web_view_ == web_view) { 84 if (last_web_view_ == web_view) {
82 last_top_view_ = NULL; 85 last_top_view_ = NULL;
83 last_web_view_ = NULL; 86 last_web_view_ = NULL;
84 } 87 }
85 } 88 }
86 89
87 IAccessible* AccessibleWebViewRegistry::GetAccessibleFromWebView( 90 IAccessible* AccessibleWebViewRegistry::GetAccessibleFromWebView(
88 View* top_view, long child_id) { 91 View* top_view, long child_id) {
89 // This function gets called frequently, so try to avoid searching all 92 // This function gets called frequently, so try to avoid searching all
90 // of the web views if the notification is on the same web view that 93 // of the web views if the notification is on the same web view that
91 // sent the last one. 94 // sent the last one.
92 if (last_top_view_ == top_view) { 95 if (last_top_view_ == top_view) {
93 IAccessible* accessible = 96 IAccessible* accessible =
94 last_web_view_->AccessibleObjectFromChildId(child_id); 97 AccessibleObjectFromChildId(last_web_view_, child_id);
95 if (accessible) 98 if (accessible)
96 return accessible; 99 return accessible;
97 } 100 }
98 101
99 // Search all web views. For each one, first ensure it's a descendant 102 // Search all web views. For each one, first ensure it's a descendant
100 // of this view where the event was posted - and if so, see if it owns 103 // of this view where the event was posted - and if so, see if it owns
101 // an accessible object with that child id. If so, save the view to speed 104 // an accessible object with that child id. If so, save the view to speed
102 // up the next notification. 105 // up the next notification.
103 for (std::set<AccessibleWebView*>::iterator iter = web_views_.begin(); 106 for (std::set<View*>::iterator iter = web_views_.begin();
104 iter != web_views_.end(); ++iter) { 107 iter != web_views_.end(); ++iter) {
105 AccessibleWebView* web_view = *iter; 108 View* web_view = *iter;
106 if (!top_view->Contains(web_view->AsView())) 109 if (!top_view->Contains(web_view))
107 continue; 110 continue;
108 IAccessible* accessible = web_view->AccessibleObjectFromChildId(child_id); 111 IAccessible* accessible = AccessibleObjectFromChildId(web_view, child_id);
109 if (accessible) { 112 if (accessible) {
110 last_top_view_ = top_view; 113 last_top_view_ = top_view;
111 last_web_view_ = web_view; 114 last_web_view_ = web_view;
112 return accessible; 115 return accessible;
113 } 116 }
114 } 117 }
118
115 return NULL; 119 return NULL;
116 } 120 }
117 121
122 IAccessible* AccessibleWebViewRegistry::AccessibleObjectFromChildId(
123 View* web_view,
124 long child_id) {
125 IAccessible* web_view_accessible = web_view->GetNativeViewAccessible();
126 if (web_view_accessible == NULL)
127 return NULL;
128
129 VARIANT var_child;
130 var_child.vt = VT_I4;
131 var_child.lVal = child_id;
132 IAccessible* result = NULL;
133 if (S_OK == web_view_accessible->get_accChild(
134 var_child, reinterpret_cast<IDispatch**>(&result))) {
135 return result;
136 }
137
138 return NULL;
139 }
140
118 } // anonymous namespace 141 } // anonymous namespace
119 142
120 // static 143 // static
121 long NativeViewAccessibilityWin::next_unique_id_ = 1; 144 long NativeViewAccessibilityWin::next_unique_id_ = 1;
122 int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0}; 145 int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0};
123 int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0; 146 int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0;
124 147
125 // static 148 // static
126 NativeViewAccessibility* NativeViewAccessibility::Create(View* view) { 149 NativeViewAccessibility* NativeViewAccessibility::Create(View* view) {
127 // Make sure ATL is initialized in this module. 150 // Make sure ATL is initialized in this module.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 195
173 gfx::NativeViewAccessible NativeViewAccessibilityWin::GetNativeObject() { 196 gfx::NativeViewAccessible NativeViewAccessibilityWin::GetNativeObject() {
174 return this; 197 return this;
175 } 198 }
176 199
177 void NativeViewAccessibilityWin::Destroy() { 200 void NativeViewAccessibilityWin::Destroy() {
178 view_ = NULL; 201 view_ = NULL;
179 Release(); 202 Release();
180 } 203 }
181 204
182 // TODO(ctguil): Handle case where child View is not contained by parent.
183 STDMETHODIMP NativeViewAccessibilityWin::accHitTest( 205 STDMETHODIMP NativeViewAccessibilityWin::accHitTest(
184 LONG x_left, LONG y_top, VARIANT* child) { 206 LONG x_left, LONG y_top, VARIANT* child) {
185 if (!child) 207 if (!child)
186 return E_INVALIDARG; 208 return E_INVALIDARG;
187 209
188 if (!view_) 210 if (!view_)
189 return E_FAIL; 211 return E_FAIL;
190 212
191 gfx::Point point(x_left, y_top); 213 gfx::Point point(x_left, y_top);
192 View::ConvertPointToTarget(NULL, view_, &point); 214 View::ConvertPointToTarget(NULL, view_, &point);
193 215
216 // If the point is not inside this view, return false.
194 if (!view_->HitTestPoint(point)) { 217 if (!view_->HitTestPoint(point)) {
195 // If containing parent is not hit, return with failure.
196 child->vt = VT_EMPTY; 218 child->vt = VT_EMPTY;
197 return S_FALSE; 219 return S_FALSE;
198 } 220 }
199 221
200 View* view = view_->GetEventHandlerForPoint(point); 222 // Check if the point is within any of the immediate children of this
201 if (view == view_) { 223 // view.
202 // No child hit, return parent id. 224 View* hit_child_view = NULL;
203 child->vt = VT_I4; 225 for (int i = view_->child_count() - 1; i >= 0; --i) {
204 child->lVal = CHILDID_SELF; 226 View* child_view = view_->child_at(i);
205 } else { 227 if (!child_view->visible())
206 child->vt = VT_DISPATCH; 228 continue;
207 child->pdispVal = view->GetNativeViewAccessible(); 229
208 child->pdispVal->AddRef(); 230 gfx::Point point_in_child_coords(point);
231 view_->ConvertPointToTarget(view_, child_view, &point_in_child_coords);
232 if (child_view->HitTestPoint(point_in_child_coords)) {
233 hit_child_view = child_view;
234 break;
235 }
209 } 236 }
237
238 // If the point was within one of this view's immediate children,
239 // call accHitTest recursively on that child's native view accessible -
240 // which may be a recursive call to this function or it may be overridden,
241 // for example in the case of a WebView.
242 if (hit_child_view) {
243 HRESULT result = hit_child_view->GetNativeViewAccessible()->accHitTest(
244 x_left, y_top, child);
245
246 // If the recursive call returned CHILDID_SELF, we have to convert that
247 // into a VT_DISPATCH for the return value to this call.
248 if (S_OK == result && child->vt == VT_I4 && child->lVal == CHILDID_SELF) {
249 child->vt = VT_DISPATCH;
250 child->pdispVal = hit_child_view->GetNativeViewAccessible();
251 // Always increment ref when returning a reference to a COM object.
252 child->pdispVal->AddRef();
253 }
254 return result;
255 }
256
257 // This object is the best match, so return CHILDID_SELF. It's tempting to
258 // simplify the logic and use VT_DISPATCH everywhere, but the Windows
259 // call AccessibleObjectFromPoint will keep calling accHitTest until some
260 // object returns CHILDID_SELF.
261 child->vt = VT_I4;
262 child->lVal = CHILDID_SELF;
210 return S_OK; 263 return S_OK;
211 } 264 }
212 265
213 HRESULT NativeViewAccessibilityWin::accDoDefaultAction(VARIANT var_id) { 266 HRESULT NativeViewAccessibilityWin::accDoDefaultAction(VARIANT var_id) {
214 if (!IsValidId(var_id)) 267 if (!IsValidId(var_id))
215 return E_INVALIDARG; 268 return E_INVALIDARG;
216 269
217 // The object does not support the method. This value is returned for 270 // The object does not support the method. This value is returned for
218 // controls that do not perform actions, such as edit fields. 271 // controls that do not perform actions, such as edit fields.
219 return DISP_E_MEMBERNOTFOUND; 272 return DISP_E_MEMBERNOTFOUND;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 int view_storage_id_index = 424 int view_storage_id_index =
372 base::win::kFirstViewsAccessibilityId - child_id; 425 base::win::kFirstViewsAccessibilityId - child_id;
373 if (view_storage_id_index >= 0 && 426 if (view_storage_id_index >= 0 &&
374 view_storage_id_index < kMaxViewStorageIds) { 427 view_storage_id_index < kMaxViewStorageIds) {
375 int view_storage_id = view_storage_ids_[view_storage_id_index]; 428 int view_storage_id = view_storage_ids_[view_storage_id_index];
376 ViewStorage* view_storage = ViewStorage::GetInstance(); 429 ViewStorage* view_storage = ViewStorage::GetInstance();
377 child_view = view_storage->RetrieveView(view_storage_id); 430 child_view = view_storage->RetrieveView(view_storage_id);
378 } else { 431 } else {
379 *disp_child = AccessibleWebViewRegistry::GetInstance()-> 432 *disp_child = AccessibleWebViewRegistry::GetInstance()->
380 GetAccessibleFromWebView(view_, child_id); 433 GetAccessibleFromWebView(view_, child_id);
381 if (*disp_child) { 434 if (*disp_child)
382 (*disp_child)->AddRef();
383 return S_OK; 435 return S_OK;
384 }
385 } 436 }
386 } 437 }
387 438
388 if (!child_view) { 439 if (!child_view) {
389 // No child found. 440 // No child found.
390 *disp_child = NULL; 441 *disp_child = NULL;
391 return E_FAIL; 442 return E_FAIL;
392 } 443 }
393 444
394 *disp_child = child_view->GetNativeViewAccessible(); 445 *disp_child = child_view->GetNativeViewAccessible();
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 } else { 1028 } else {
978 V_VT(ret) = VT_EMPTY; 1029 V_VT(ret) = VT_EMPTY;
979 } 1030 }
980 return S_OK; 1031 return S_OK;
981 } 1032 }
982 1033
983 // 1034 //
984 // Static methods. 1035 // Static methods.
985 // 1036 //
986 1037
987 void NativeViewAccessibility::RegisterWebView(AccessibleWebView* web_view) { 1038 void NativeViewAccessibility::RegisterWebView(View* web_view) {
988 AccessibleWebViewRegistry::GetInstance()->RegisterWebView(web_view); 1039 AccessibleWebViewRegistry::GetInstance()->RegisterWebView(web_view);
989 } 1040 }
990 1041
991 void NativeViewAccessibility::UnregisterWebView(AccessibleWebView* web_view) { 1042 void NativeViewAccessibility::UnregisterWebView(View* web_view) {
992 AccessibleWebViewRegistry::GetInstance()->UnregisterWebView(web_view); 1043 AccessibleWebViewRegistry::GetInstance()->UnregisterWebView(web_view);
993 } 1044 }
994 1045
995 int32 NativeViewAccessibilityWin::MSAAEvent(AccessibilityTypes::Event event) { 1046 int32 NativeViewAccessibilityWin::MSAAEvent(AccessibilityTypes::Event event) {
996 switch (event) { 1047 switch (event) {
997 case AccessibilityTypes::EVENT_ALERT: 1048 case AccessibilityTypes::EVENT_ALERT:
998 return EVENT_SYSTEM_ALERT; 1049 return EVENT_SYSTEM_ALERT;
999 case AccessibilityTypes::EVENT_FOCUS: 1050 case AccessibilityTypes::EVENT_FOCUS:
1000 return EVENT_OBJECT_FOCUS; 1051 return EVENT_OBJECT_FOCUS;
1001 case AccessibilityTypes::EVENT_MENUSTART: 1052 case AccessibilityTypes::EVENT_MENUSTART:
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 LONG start_offset, 1277 LONG start_offset,
1227 ui::TextBoundaryDirection direction) { 1278 ui::TextBoundaryDirection direction) {
1228 HandleSpecialTextOffset(text, &start_offset); 1279 HandleSpecialTextOffset(text, &start_offset);
1229 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary); 1280 ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
1230 std::vector<int32> line_breaks; 1281 std::vector<int32> line_breaks;
1231 return ui::FindAccessibleTextBoundary( 1282 return ui::FindAccessibleTextBoundary(
1232 text, line_breaks, boundary, start_offset, direction); 1283 text, line_breaks, boundary, start_offset, direction);
1233 } 1284 }
1234 1285
1235 } // namespace views 1286 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/accessibility/native_view_accessibility.cc ('k') | ui/views/controls/webview/webview.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698