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

Side by Side Diff: chrome/browser/views/accessibility_event_router_views.cc

Issue 3056045: Improvements to accessibility extension api support for "views":... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/views/accessibility_event_router_views.h" 5 #include "chrome/browser/views/accessibility_event_router_views.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/extensions/extension_accessibility_api.h" 11 #include "chrome/browser/extensions/extension_accessibility_api.h"
12 #include "chrome/browser/profile.h" 12 #include "chrome/browser/profile.h"
13 #include "chrome/common/notification_type.h" 13 #include "chrome/common/notification_type.h"
14 #include "views/accessibility/accessibility_types.h"
14 #include "views/controls/button/image_button.h" 15 #include "views/controls/button/image_button.h"
15 #include "views/controls/button/menu_button.h" 16 #include "views/controls/button/menu_button.h"
16 #include "views/controls/button/native_button.h" 17 #include "views/controls/button/native_button.h"
17 #include "views/controls/link.h" 18 #include "views/controls/link.h"
19 #include "views/controls/menu/menu_item_view.h"
20 #include "views/controls/menu/submenu_view.h"
18 21
19 using views::FocusManager; 22 using views::FocusManager;
20 using views::View; 23 using views::View;
21 24
22 AccessibilityEventRouterViews::AccessibilityEventRouterViews() 25 AccessibilityEventRouterViews::AccessibilityEventRouterViews()
23 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 26 : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
24 } 27 }
25 28
26 AccessibilityEventRouterViews::~AccessibilityEventRouterViews() { 29 AccessibilityEventRouterViews::~AccessibilityEventRouterViews() {
27 } 30 }
28 31
29 // static 32 // static
30 AccessibilityEventRouterViews* AccessibilityEventRouterViews::GetInstance() { 33 AccessibilityEventRouterViews* AccessibilityEventRouterViews::GetInstance() {
31 return Singleton<AccessibilityEventRouterViews>::get(); 34 return Singleton<AccessibilityEventRouterViews>::get();
32 } 35 }
33 36
34 bool AccessibilityEventRouterViews::AddViewTree(View* view, Profile* profile) { 37 bool AccessibilityEventRouterViews::AddViewTree(View* view, Profile* profile) {
35 if (view_tree_profile_map_[view] != NULL) 38 if (view_tree_profile_map_[view] != NULL)
36 return false; 39 return false;
37 40
38 view_tree_profile_map_[view] = profile; 41 view_tree_profile_map_[view] = profile;
39 FocusManager* focus_manager = view->GetFocusManager();
40
41 // Add this object as a listener for this focus manager, but use a ref
42 // count to ensure we only call AddFocusChangeListener on any given
43 // focus manager once. Note that hash_map<FocusManager*, int>::operator[]
44 // will initialize the ref count to zero if it's not already in the map.
45 if (focus_manager_ref_count_[focus_manager] == 0) {
46 focus_manager->AddFocusChangeListener(this);
47 }
48 focus_manager_ref_count_[focus_manager]++;
49
50 view_info_map_[view].focus_manager = focus_manager;
51 return true; 42 return true;
52 } 43 }
53 44
54 void AccessibilityEventRouterViews::RemoveViewTree(View* view) { 45 void AccessibilityEventRouterViews::RemoveViewTree(View* view) {
55 DCHECK(view_tree_profile_map_.find(view) != 46 DCHECK(view_tree_profile_map_.find(view) !=
56 view_tree_profile_map_.end()); 47 view_tree_profile_map_.end());
57 view_tree_profile_map_.erase(view); 48 view_tree_profile_map_.erase(view);
58
59 // Decrement the ref count of the focus manager, and remove this object
60 // as a listener if the count reaches zero.
61 FocusManager* focus_manager = view_info_map_[view].focus_manager;
62 DCHECK(focus_manager);
63 focus_manager_ref_count_[focus_manager]--;
64 if (focus_manager_ref_count_[focus_manager] == 0) {
65 focus_manager->RemoveFocusChangeListener(this);
66 }
67 } 49 }
68 50
69 void AccessibilityEventRouterViews::IgnoreView(View* view) { 51 void AccessibilityEventRouterViews::IgnoreView(View* view) {
70 view_info_map_[view].ignore = true; 52 view_info_map_[view].ignore = true;
71 } 53 }
72 54
73 void AccessibilityEventRouterViews::SetViewName(View* view, std::string name) { 55 void AccessibilityEventRouterViews::SetViewName(View* view, std::string name) {
74 view_info_map_[view].name = name; 56 view_info_map_[view].name = name;
75 } 57 }
76 58
77 void AccessibilityEventRouterViews::RemoveView(View* view) { 59 void AccessibilityEventRouterViews::RemoveView(View* view) {
78 DCHECK(view_info_map_.find(view) != view_info_map_.end()); 60 DCHECK(view_info_map_.find(view) != view_info_map_.end());
79 view_info_map_.erase(view); 61 view_info_map_.erase(view);
80 } 62 }
81 63
82 // 64 void AccessibilityEventRouterViews::HandleAccessibilityEvent(
83 // views::FocusChangeListener 65 views::View* view, AccessibilityTypes::Event event_type) {
84 // 66 switch (event_type) {
85 67 case AccessibilityTypes::EVENT_FOCUS:
86 void AccessibilityEventRouterViews::FocusWillChange( 68 DispatchAccessibilityNotification(
87 View* focused_before, View* focused_now) { 69 view, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
88 if (focused_now) { 70 break;
89 DispatchAccessibilityNotification( 71 case AccessibilityTypes::EVENT_MENUSTART:
90 focused_now, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED); 72 case AccessibilityTypes::EVENT_MENUPOPUPSTART:
73 DispatchAccessibilityNotification(
74 view, NotificationType::ACCESSIBILITY_MENU_OPENED);
75 break;
76 case AccessibilityTypes::EVENT_MENUEND:
77 case AccessibilityTypes::EVENT_MENUPOPUPEND:
78 DispatchAccessibilityNotification(
79 view, NotificationType::ACCESSIBILITY_MENU_CLOSED);
80 break;
91 } 81 }
92 } 82 }
93 83
94 // 84 //
95 // Private methods 85 // Private methods
96 // 86 //
97 87
98 void AccessibilityEventRouterViews::FindView( 88 void AccessibilityEventRouterViews::FindView(
99 View* view, Profile** profile, bool* is_accessible) { 89 View* view, Profile** profile, bool* is_accessible) {
100 *is_accessible = false; 90 *is_accessible = false;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 } 128 }
139 129
140 return name; 130 return name;
141 } 131 }
142 132
143 void AccessibilityEventRouterViews::DispatchAccessibilityNotification( 133 void AccessibilityEventRouterViews::DispatchAccessibilityNotification(
144 View* view, NotificationType type) { 134 View* view, NotificationType type) {
145 Profile* profile = NULL; 135 Profile* profile = NULL;
146 bool is_accessible; 136 bool is_accessible;
147 FindView(view, &profile, &is_accessible); 137 FindView(view, &profile, &is_accessible);
138
139 // Special case: a menu isn't associated with any particular top-level
140 // window, so menu events get routed to the profile of the most recent
141 // event that was associated with a window, which should be the window
142 // that triggered opening the menu.
143 bool is_menu_event = IsMenuEvent(view, type);
144 if (is_menu_event && !profile && most_recent_profile_) {
145 profile = most_recent_profile_;
146 is_accessible = true;
147 }
148
148 if (!is_accessible) 149 if (!is_accessible)
149 return; 150 return;
150 151
151 if (view->GetClassName() == views::ImageButton::kViewClassName) { 152 most_recent_profile_ = profile;
153
154 AccessibilityTypes::Role role;
155 view->GetAccessibleRole(&role);
156 std::string class_name = view->GetClassName();
157
158 if (class_name == views::MenuButton::kViewClassName ||
159 type == NotificationType::ACCESSIBILITY_MENU_OPENED ||
160 type == NotificationType::ACCESSIBILITY_MENU_CLOSED) {
161 SendMenuNotification(view, type, profile);
162 } else if (is_menu_event) {
163 SendMenuItemNotification(view, type, profile);
164 } else if (class_name == views::ImageButton::kViewClassName ||
165 class_name == views::NativeButton::kViewClassName ||
166 class_name == views::TextButton::kViewClassName) {
152 SendButtonNotification(view, type, profile); 167 SendButtonNotification(view, type, profile);
153 } else if (view->GetClassName() == views::NativeButton::kViewClassName) { 168 } else if (class_name == views::Link::kViewClassName) {
154 SendButtonNotification(view, type, profile);
155 } else if (view->GetClassName() == views::Link::kViewClassName) {
156 SendLinkNotification(view, type, profile); 169 SendLinkNotification(view, type, profile);
157 } else if (view->GetClassName() == views::MenuButton::kViewClassName) {
158 SendMenuNotification(view, type, profile);
159 } 170 }
160 } 171 }
161 172
162 void AccessibilityEventRouterViews::SendButtonNotification( 173 void AccessibilityEventRouterViews::SendButtonNotification(
163 View* view, NotificationType type, Profile* profile) { 174 View* view, NotificationType type, Profile* profile) {
164 AccessibilityButtonInfo info(profile, GetViewName(view)); 175 AccessibilityButtonInfo info(profile, GetViewName(view));
165 SendAccessibilityNotification(type, &info); 176 SendAccessibilityNotification(type, &info);
166 } 177 }
167 178
168 void AccessibilityEventRouterViews::SendLinkNotification( 179 void AccessibilityEventRouterViews::SendLinkNotification(
169 View* view, NotificationType type, Profile* profile) { 180 View* view, NotificationType type, Profile* profile) {
170 AccessibilityLinkInfo info(profile, GetViewName(view)); 181 AccessibilityLinkInfo info(profile, GetViewName(view));
171 SendAccessibilityNotification(type, &info); 182 SendAccessibilityNotification(type, &info);
172 } 183 }
173 184
174 void AccessibilityEventRouterViews::SendMenuNotification( 185 void AccessibilityEventRouterViews::SendMenuNotification(
175 View* view, NotificationType type, Profile* profile) { 186 View* view, NotificationType type, Profile* profile) {
176 AccessibilityMenuInfo info(profile, GetViewName(view)); 187 AccessibilityMenuInfo info(profile, GetViewName(view));
177 SendAccessibilityNotification(type, &info); 188 SendAccessibilityNotification(type, &info);
178 } 189 }
190
191 void AccessibilityEventRouterViews::SendMenuItemNotification(
192 View* view, NotificationType type, Profile* profile) {
193 std::string name = GetViewName(view);
194
195 bool has_submenu = false;
196 int index = -1;
197 int count = -1;
198
199 if (view->GetClassName() == views::MenuItemView::kViewClassName)
200 has_submenu = static_cast<views::MenuItemView*>(view)->HasSubmenu();
201
202 View* parent_menu = view->GetParent();
203 while (parent_menu != NULL && parent_menu->GetClassName() !=
204 views::SubmenuView::kViewClassName) {
205 parent_menu = parent_menu->GetParent();
206 }
207 if (parent_menu) {
208 count = 0;
209 RecursiveGetMenuItemIndexAndCount(parent_menu, view, &index, &count);
210 }
211
212 AccessibilityMenuItemInfo info(profile, name, has_submenu, index, count);
213 SendAccessibilityNotification(type, &info);
214 }
215
216 void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount(
217 views::View* menu, views::View* item, int* index, int* count) {
218 for (int i = 0; i < menu->GetChildViewCount(); ++i) {
219 views::View* child = menu->GetChildViewAt(i);
220 int previous_count = *count;
221 RecursiveGetMenuItemIndexAndCount(child, item, index, count);
222 if (child->GetClassName() == views::MenuItemView::kViewClassName &&
223 *count == previous_count) {
224 if (item == child)
225 *index = *count;
226 (*count)++;
227 } else if (child->GetClassName() == views::TextButton::kViewClassName) {
228 if (item == child)
229 *index = *count;
230 (*count)++;
231 }
232 }
233 }
234
235 bool AccessibilityEventRouterViews::IsMenuEvent(
236 View* view, NotificationType type) {
237 if (type == NotificationType::ACCESSIBILITY_MENU_OPENED ||
238 type == NotificationType::ACCESSIBILITY_MENU_CLOSED)
239 return true;
240
241 while (view) {
242 AccessibilityTypes::Role role;
243 view->GetAccessibleRole(&role);
244 if (role == AccessibilityTypes::ROLE_MENUITEM ||
245 role == AccessibilityTypes::ROLE_MENUPOPUP) {
246 return true;
247 }
248 view = view->GetParent();
249 }
250
251 return false;
252 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698