| OLD | NEW |
| 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/accessibility/accessibility_types.h" |
| 15 #include "views/controls/button/image_button.h" | 15 #include "views/controls/button/image_button.h" |
| 16 #include "views/controls/button/menu_button.h" | 16 #include "views/controls/button/menu_button.h" |
| 17 #include "views/controls/button/native_button.h" | 17 #include "views/controls/button/native_button.h" |
| 18 #include "views/controls/link.h" | 18 #include "views/controls/link.h" |
| 19 #include "views/controls/menu/menu_item_view.h" | 19 #include "views/controls/menu/menu_item_view.h" |
| 20 #include "views/controls/menu/submenu_view.h" | 20 #include "views/controls/menu/submenu_view.h" |
| 21 #include "views/view.h" |
| 21 | 22 |
| 22 using views::FocusManager; | 23 using views::FocusManager; |
| 23 using views::View; | |
| 24 | 24 |
| 25 AccessibilityEventRouterViews::AccessibilityEventRouterViews() | 25 AccessibilityEventRouterViews::AccessibilityEventRouterViews() |
| 26 : most_recent_profile_(NULL), | 26 : most_recent_profile_(NULL), |
| 27 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 27 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
| 28 } | 28 } |
| 29 | 29 |
| 30 AccessibilityEventRouterViews::~AccessibilityEventRouterViews() { | 30 AccessibilityEventRouterViews::~AccessibilityEventRouterViews() { |
| 31 } | 31 } |
| 32 | 32 |
| 33 // static | 33 // static |
| 34 AccessibilityEventRouterViews* AccessibilityEventRouterViews::GetInstance() { | 34 AccessibilityEventRouterViews* AccessibilityEventRouterViews::GetInstance() { |
| 35 return Singleton<AccessibilityEventRouterViews>::get(); | 35 return Singleton<AccessibilityEventRouterViews>::get(); |
| 36 } | 36 } |
| 37 | 37 |
| 38 bool AccessibilityEventRouterViews::AddViewTree(View* view, Profile* profile) { | 38 bool AccessibilityEventRouterViews::AddViewTree( |
| 39 views::View* view, Profile* profile) { |
| 39 if (view_tree_profile_map_[view] != NULL) | 40 if (view_tree_profile_map_[view] != NULL) |
| 40 return false; | 41 return false; |
| 41 | 42 |
| 42 view_tree_profile_map_[view] = profile; | 43 view_tree_profile_map_[view] = profile; |
| 43 return true; | 44 return true; |
| 44 } | 45 } |
| 45 | 46 |
| 46 void AccessibilityEventRouterViews::RemoveViewTree(View* view) { | 47 void AccessibilityEventRouterViews::RemoveViewTree(views::View* view) { |
| 47 DCHECK(view_tree_profile_map_.find(view) != | 48 DCHECK(view_tree_profile_map_.find(view) != |
| 48 view_tree_profile_map_.end()); | 49 view_tree_profile_map_.end()); |
| 49 view_tree_profile_map_.erase(view); | 50 view_tree_profile_map_.erase(view); |
| 50 } | 51 } |
| 51 | 52 |
| 52 void AccessibilityEventRouterViews::IgnoreView(View* view) { | 53 void AccessibilityEventRouterViews::IgnoreView(views::View* view) { |
| 53 view_info_map_[view].ignore = true; | 54 view_info_map_[view].ignore = true; |
| 54 } | 55 } |
| 55 | 56 |
| 56 void AccessibilityEventRouterViews::SetViewName(View* view, std::string name) { | 57 void AccessibilityEventRouterViews::SetViewName( |
| 58 views::View* view, std::string name) { |
| 57 view_info_map_[view].name = name; | 59 view_info_map_[view].name = name; |
| 58 } | 60 } |
| 59 | 61 |
| 60 void AccessibilityEventRouterViews::RemoveView(View* view) { | 62 void AccessibilityEventRouterViews::RemoveView(views::View* view) { |
| 61 DCHECK(view_info_map_.find(view) != view_info_map_.end()); | 63 DCHECK(view_info_map_.find(view) != view_info_map_.end()); |
| 62 view_info_map_.erase(view); | 64 view_info_map_.erase(view); |
| 63 } | 65 } |
| 64 | 66 |
| 65 void AccessibilityEventRouterViews::HandleAccessibilityEvent( | 67 void AccessibilityEventRouterViews::HandleAccessibilityEvent( |
| 66 views::View* view, AccessibilityTypes::Event event_type) { | 68 views::View* view, AccessibilityTypes::Event event_type) { |
| 67 switch (event_type) { | 69 switch (event_type) { |
| 68 case AccessibilityTypes::EVENT_FOCUS: | 70 case AccessibilityTypes::EVENT_FOCUS: |
| 69 DispatchAccessibilityNotification( | 71 DispatchAccessibilityNotification( |
| 70 view, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED); | 72 view, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED); |
| 71 break; | 73 break; |
| 72 case AccessibilityTypes::EVENT_MENUSTART: | 74 case AccessibilityTypes::EVENT_MENUSTART: |
| 73 case AccessibilityTypes::EVENT_MENUPOPUPSTART: | 75 case AccessibilityTypes::EVENT_MENUPOPUPSTART: |
| 74 DispatchAccessibilityNotification( | 76 DispatchAccessibilityNotification( |
| 75 view, NotificationType::ACCESSIBILITY_MENU_OPENED); | 77 view, NotificationType::ACCESSIBILITY_MENU_OPENED); |
| 76 break; | 78 break; |
| 77 case AccessibilityTypes::EVENT_MENUEND: | 79 case AccessibilityTypes::EVENT_MENUEND: |
| 78 case AccessibilityTypes::EVENT_MENUPOPUPEND: | 80 case AccessibilityTypes::EVENT_MENUPOPUPEND: |
| 79 DispatchAccessibilityNotification( | 81 DispatchAccessibilityNotification( |
| 80 view, NotificationType::ACCESSIBILITY_MENU_CLOSED); | 82 view, NotificationType::ACCESSIBILITY_MENU_CLOSED); |
| 81 break; | 83 break; |
| 82 } | 84 } |
| 83 } | 85 } |
| 84 | 86 |
| 85 // | 87 // |
| 86 // Private methods | 88 // Private methods |
| 87 // | 89 // |
| 88 | 90 |
| 89 void AccessibilityEventRouterViews::FindView( | 91 void AccessibilityEventRouterViews::FindView( |
| 90 View* view, Profile** profile, bool* is_accessible) { | 92 views::View* view, Profile** profile, bool* is_accessible) { |
| 91 *is_accessible = false; | 93 *is_accessible = false; |
| 92 | 94 |
| 93 // First see if it's a descendant of an accessible view. | 95 // First see if it's a descendant of an accessible view. |
| 94 for (base::hash_map<View*, Profile*>::const_iterator iter = | 96 for (base::hash_map<views::View*, Profile*>::const_iterator iter = |
| 95 view_tree_profile_map_.begin(); | 97 view_tree_profile_map_.begin(); |
| 96 iter != view_tree_profile_map_.end(); | 98 iter != view_tree_profile_map_.end(); |
| 97 ++iter) { | 99 ++iter) { |
| 98 if (iter->first->IsParentOf(view)) { | 100 if (iter->first->IsParentOf(view)) { |
| 99 *is_accessible = true; | 101 *is_accessible = true; |
| 100 if (profile) | 102 if (profile) |
| 101 *profile = iter->second; | 103 *profile = iter->second; |
| 102 break; | 104 break; |
| 103 } | 105 } |
| 104 } | 106 } |
| 105 if (!*is_accessible) | 107 if (!*is_accessible) |
| 106 return; | 108 return; |
| 107 | 109 |
| 108 // Now make sure it's not marked as a widget to be ignored. | 110 // Now make sure it's not marked as a widget to be ignored. |
| 109 base::hash_map<View*, ViewInfo>::const_iterator iter = | 111 base::hash_map<views::View*, ViewInfo>::const_iterator iter = |
| 110 view_info_map_.find(view); | 112 view_info_map_.find(view); |
| 111 if (iter != view_info_map_.end() && iter->second.ignore) | 113 if (iter != view_info_map_.end() && iter->second.ignore) |
| 112 *is_accessible = false; | 114 *is_accessible = false; |
| 113 } | 115 } |
| 114 | 116 |
| 115 std::string AccessibilityEventRouterViews::GetViewName(View* view) { | 117 std::string AccessibilityEventRouterViews::GetViewName(views::View* view) { |
| 116 std::string name; | 118 std::string name; |
| 117 | 119 |
| 118 // First see if we have a name registered for this view. | 120 // First see if we have a name registered for this view. |
| 119 base::hash_map<View*, ViewInfo>::const_iterator iter = | 121 base::hash_map<views::View*, ViewInfo>::const_iterator iter = |
| 120 view_info_map_.find(view); | 122 view_info_map_.find(view); |
| 121 if (iter != view_info_map_.end()) | 123 if (iter != view_info_map_.end()) |
| 122 name = iter->second.name; | 124 name = iter->second.name; |
| 123 | 125 |
| 124 // Otherwise ask the view for its accessible name. | 126 // Otherwise ask the view for its accessible name. |
| 125 if (name.empty()) { | 127 if (name.empty()) { |
| 126 std::wstring wname; | 128 std::wstring wname; |
| 127 view->GetAccessibleName(&wname); | 129 view->GetAccessibleName(&wname); |
| 128 name = WideToUTF8(wname); | 130 name = WideToUTF8(wname); |
| 129 } | 131 } |
| 130 | 132 |
| 131 return name; | 133 return name; |
| 132 } | 134 } |
| 133 | 135 |
| 134 void AccessibilityEventRouterViews::DispatchAccessibilityNotification( | 136 void AccessibilityEventRouterViews::DispatchAccessibilityNotification( |
| 135 View* view, NotificationType type) { | 137 views::View* view, NotificationType type) { |
| 136 Profile* profile = NULL; | 138 Profile* profile = NULL; |
| 137 bool is_accessible; | 139 bool is_accessible; |
| 138 FindView(view, &profile, &is_accessible); | 140 FindView(view, &profile, &is_accessible); |
| 139 | 141 |
| 140 // Special case: a menu isn't associated with any particular top-level | 142 // Special case: a menu isn't associated with any particular top-level |
| 141 // window, so menu events get routed to the profile of the most recent | 143 // window, so menu events get routed to the profile of the most recent |
| 142 // event that was associated with a window, which should be the window | 144 // event that was associated with a window, which should be the window |
| 143 // that triggered opening the menu. | 145 // that triggered opening the menu. |
| 144 bool is_menu_event = IsMenuEvent(view, type); | 146 bool is_menu_event = IsMenuEvent(view, type); |
| 145 if (is_menu_event && !profile && most_recent_profile_) { | 147 if (is_menu_event && !profile && most_recent_profile_) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 165 } else if (class_name == views::ImageButton::kViewClassName || | 167 } else if (class_name == views::ImageButton::kViewClassName || |
| 166 class_name == views::NativeButton::kViewClassName || | 168 class_name == views::NativeButton::kViewClassName || |
| 167 class_name == views::TextButton::kViewClassName) { | 169 class_name == views::TextButton::kViewClassName) { |
| 168 SendButtonNotification(view, type, profile); | 170 SendButtonNotification(view, type, profile); |
| 169 } else if (class_name == views::Link::kViewClassName) { | 171 } else if (class_name == views::Link::kViewClassName) { |
| 170 SendLinkNotification(view, type, profile); | 172 SendLinkNotification(view, type, profile); |
| 171 } | 173 } |
| 172 } | 174 } |
| 173 | 175 |
| 174 void AccessibilityEventRouterViews::SendButtonNotification( | 176 void AccessibilityEventRouterViews::SendButtonNotification( |
| 175 View* view, NotificationType type, Profile* profile) { | 177 views::View* view, NotificationType type, Profile* profile) { |
| 176 AccessibilityButtonInfo info(profile, GetViewName(view)); | 178 AccessibilityButtonInfo info(profile, GetViewName(view)); |
| 177 SendAccessibilityNotification(type, &info); | 179 SendAccessibilityNotification(type, &info); |
| 178 } | 180 } |
| 179 | 181 |
| 180 void AccessibilityEventRouterViews::SendLinkNotification( | 182 void AccessibilityEventRouterViews::SendLinkNotification( |
| 181 View* view, NotificationType type, Profile* profile) { | 183 views::View* view, NotificationType type, Profile* profile) { |
| 182 AccessibilityLinkInfo info(profile, GetViewName(view)); | 184 AccessibilityLinkInfo info(profile, GetViewName(view)); |
| 183 SendAccessibilityNotification(type, &info); | 185 SendAccessibilityNotification(type, &info); |
| 184 } | 186 } |
| 185 | 187 |
| 186 void AccessibilityEventRouterViews::SendMenuNotification( | 188 void AccessibilityEventRouterViews::SendMenuNotification( |
| 187 View* view, NotificationType type, Profile* profile) { | 189 views::View* view, NotificationType type, Profile* profile) { |
| 188 AccessibilityMenuInfo info(profile, GetViewName(view)); | 190 AccessibilityMenuInfo info(profile, GetViewName(view)); |
| 189 SendAccessibilityNotification(type, &info); | 191 SendAccessibilityNotification(type, &info); |
| 190 } | 192 } |
| 191 | 193 |
| 192 void AccessibilityEventRouterViews::SendMenuItemNotification( | 194 void AccessibilityEventRouterViews::SendMenuItemNotification( |
| 193 View* view, NotificationType type, Profile* profile) { | 195 views::View* view, NotificationType type, Profile* profile) { |
| 194 std::string name = GetViewName(view); | 196 std::string name = GetViewName(view); |
| 195 | 197 |
| 196 bool has_submenu = false; | 198 bool has_submenu = false; |
| 197 int index = -1; | 199 int index = -1; |
| 198 int count = -1; | 200 int count = -1; |
| 199 | 201 |
| 200 if (view->GetClassName() == views::MenuItemView::kViewClassName) | 202 if (view->GetClassName() == views::MenuItemView::kViewClassName) |
| 201 has_submenu = static_cast<views::MenuItemView*>(view)->HasSubmenu(); | 203 has_submenu = static_cast<views::MenuItemView*>(view)->HasSubmenu(); |
| 202 | 204 |
| 203 View* parent_menu = view->GetParent(); | 205 views::View* parent_menu = view->GetParent(); |
| 204 while (parent_menu != NULL && parent_menu->GetClassName() != | 206 while (parent_menu != NULL && parent_menu->GetClassName() != |
| 205 views::SubmenuView::kViewClassName) { | 207 views::SubmenuView::kViewClassName) { |
| 206 parent_menu = parent_menu->GetParent(); | 208 parent_menu = parent_menu->GetParent(); |
| 207 } | 209 } |
| 208 if (parent_menu) { | 210 if (parent_menu) { |
| 209 count = 0; | 211 count = 0; |
| 210 RecursiveGetMenuItemIndexAndCount(parent_menu, view, &index, &count); | 212 RecursiveGetMenuItemIndexAndCount(parent_menu, view, &index, &count); |
| 211 } | 213 } |
| 212 | 214 |
| 213 AccessibilityMenuItemInfo info(profile, name, has_submenu, index, count); | 215 AccessibilityMenuItemInfo info(profile, name, has_submenu, index, count); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 227 (*count)++; | 229 (*count)++; |
| 228 } else if (child->GetClassName() == views::TextButton::kViewClassName) { | 230 } else if (child->GetClassName() == views::TextButton::kViewClassName) { |
| 229 if (item == child) | 231 if (item == child) |
| 230 *index = *count; | 232 *index = *count; |
| 231 (*count)++; | 233 (*count)++; |
| 232 } | 234 } |
| 233 } | 235 } |
| 234 } | 236 } |
| 235 | 237 |
| 236 bool AccessibilityEventRouterViews::IsMenuEvent( | 238 bool AccessibilityEventRouterViews::IsMenuEvent( |
| 237 View* view, NotificationType type) { | 239 views::View* view, NotificationType type) { |
| 238 if (type == NotificationType::ACCESSIBILITY_MENU_OPENED || | 240 if (type == NotificationType::ACCESSIBILITY_MENU_OPENED || |
| 239 type == NotificationType::ACCESSIBILITY_MENU_CLOSED) | 241 type == NotificationType::ACCESSIBILITY_MENU_CLOSED) |
| 240 return true; | 242 return true; |
| 241 | 243 |
| 242 while (view) { | 244 while (view) { |
| 243 AccessibilityTypes::Role role; | 245 AccessibilityTypes::Role role; |
| 244 view->GetAccessibleRole(&role); | 246 view->GetAccessibleRole(&role); |
| 245 if (role == AccessibilityTypes::ROLE_MENUITEM || | 247 if (role == AccessibilityTypes::ROLE_MENUITEM || |
| 246 role == AccessibilityTypes::ROLE_MENUPOPUP) { | 248 role == AccessibilityTypes::ROLE_MENUPOPUP) { |
| 247 return true; | 249 return true; |
| 248 } | 250 } |
| 249 view = view->GetParent(); | 251 view = view->GetParent(); |
| 250 } | 252 } |
| 251 | 253 |
| 252 return false; | 254 return false; |
| 253 } | 255 } |
| OLD | NEW |