diff options
9 files changed, 178 insertions, 101 deletions
diff --git a/chrome/browser/ui/views/accessibility_event_router_views.cc b/chrome/browser/ui/views/accessibility_event_router_views.cc index 1936a64..be15213 100644 --- a/chrome/browser/ui/views/accessibility_event_router_views.cc +++ b/chrome/browser/ui/views/accessibility_event_router_views.cc @@ -12,20 +12,12 @@ #include "chrome/browser/extensions/extension_accessibility_api.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "content/common/notification_type.h" -#include "ui/base/models/combobox_model.h" #include "ui/base/accessibility/accessible_view_state.h" -#include "views/controls/button/checkbox.h" -#include "views/controls/button/custom_button.h" -#include "views/controls/button/menu_button.h" -#include "views/controls/combobox/combobox.h" -#include "views/controls/link.h" +#include "views/controls/button/text_button.h" #include "views/controls/menu/menu_item_view.h" #include "views/controls/menu/submenu_view.h" -#include "views/controls/textfield/textfield.h" #include "views/view.h" -#include "views/widget/native_widget.h" #include "views/widget/widget.h" using views::FocusManager; @@ -75,10 +67,10 @@ void AccessibilityEventRouterViews::HandleAccessibilityEvent( view, NotificationType::ACCESSIBILITY_CONTROL_ACTION); break; case ui::AccessibilityTypes::EVENT_ALERT: + DispatchAccessibilityNotification( + view, NotificationType::ACCESSIBILITY_WINDOW_OPENED); + break; case ui::AccessibilityTypes::EVENT_NAME_CHANGED: - // TODO(dmazzoni): re-evaluate this list later and see - // if supporting any of these would be useful feature requests or - // they'd just be superfluous. NOTIMPLEMENTED(); break; } @@ -112,12 +104,6 @@ void AccessibilityEventRouterViews::HandleMenuItemFocused( // Private methods // -std::string AccessibilityEventRouterViews::GetViewName(views::View* view) { - ui::AccessibleViewState state; - view->GetAccessibleState(&state); - return UTF16ToUTF8(state.name); -} - void AccessibilityEventRouterViews::DispatchAccessibilityNotification( views::View* view, NotificationType type) { // Get the profile associated with this view. If it's not found, use @@ -139,52 +125,81 @@ void AccessibilityEventRouterViews::DispatchAccessibilityNotification( } most_recent_profile_ = profile; - std::string class_name = view->GetClassName(); - if (class_name == views::Checkbox::kViewClassName) { - SendCheckboxNotification(view, type, profile); - } else if (class_name == views::MenuButton::kViewClassName || - type == NotificationType::ACCESSIBILITY_MENU_OPENED || + if (type == NotificationType::ACCESSIBILITY_MENU_OPENED || type == NotificationType::ACCESSIBILITY_MENU_CLOSED) { SendMenuNotification(view, type, profile); - } else if (IsMenuEvent(view, type)) { - SendMenuItemNotification(view, type, profile); - } else if (class_name == views::CustomButton::kViewClassName || - class_name == views::NativeButton::kViewClassName || - class_name == views::NativeTextButton::kViewClassName || - class_name == views::TextButton::kViewClassName) { + return; + } + + ui::AccessibleViewState state; + view->GetAccessibleState(&state); + switch (state.role) { + case ui::AccessibilityTypes::ROLE_ALERT: + SendWindowNotification(view, type, profile); + break; + case ui::AccessibilityTypes::ROLE_BUTTONMENU: + case ui::AccessibilityTypes::ROLE_MENUBAR: + case ui::AccessibilityTypes::ROLE_MENUPOPUP: + SendMenuNotification(view, type, profile); + break; + case ui::AccessibilityTypes::ROLE_BUTTONDROPDOWN: + case ui::AccessibilityTypes::ROLE_PUSHBUTTON: SendButtonNotification(view, type, profile); - } else if (class_name == views::Link::kViewClassName) { + break; + case ui::AccessibilityTypes::ROLE_CHECKBUTTON: + SendCheckboxNotification(view, type, profile); + break; + case ui::AccessibilityTypes::ROLE_COMBOBOX: + SendComboboxNotification(view, type, profile); + break; + case ui::AccessibilityTypes::ROLE_LINK: SendLinkNotification(view, type, profile); - } else if (class_name == LocationBarView::kViewClassName) { - SendLocationBarNotification(view, type, profile); - } else if (class_name == views::Textfield::kViewClassName) { + break; + case ui::AccessibilityTypes::ROLE_LOCATION_BAR: + case ui::AccessibilityTypes::ROLE_TEXT: SendTextfieldNotification(view, type, profile); - } else if (class_name == views::Combobox::kViewClassName) { - SendComboboxNotification(view, type, profile); + break; + case ui::AccessibilityTypes::ROLE_MENUITEM: + SendMenuItemNotification(view, type, profile); + break; + case ui::AccessibilityTypes::ROLE_RADIOBUTTON: + // Not used anymore? + default: + // If this is encountered, please file a bug with the role that wasn't + // caught so we can add accessibility extension API support. + NOTREACHED(); } } void AccessibilityEventRouterViews::SendButtonNotification( - views::View* view, NotificationType type, Profile* profile) { + views::View* view, + NotificationType type, + Profile* profile) { AccessibilityButtonInfo info(profile, GetViewName(view)); SendAccessibilityNotification(type, &info); } void AccessibilityEventRouterViews::SendLinkNotification( - views::View* view, NotificationType type, Profile* profile) { + views::View* view, + NotificationType type, + Profile* profile) { AccessibilityLinkInfo info(profile, GetViewName(view)); SendAccessibilityNotification(type, &info); } void AccessibilityEventRouterViews::SendMenuNotification( - views::View* view, NotificationType type, Profile* profile) { + views::View* view, + NotificationType type, + Profile* profile) { AccessibilityMenuInfo info(profile, GetViewName(view)); SendAccessibilityNotification(type, &info); } void AccessibilityEventRouterViews::SendMenuItemNotification( - views::View* view, NotificationType type, Profile* profile) { + views::View* view, + NotificationType type, + Profile* profile) { std::string name = GetViewName(view); bool has_submenu = false; @@ -208,63 +223,15 @@ void AccessibilityEventRouterViews::SendMenuItemNotification( SendAccessibilityNotification(type, &info); } -void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount( - views::View* menu, views::View* item, int* index, int* count) { - for (int i = 0; i < menu->child_count(); ++i) { - views::View* child = menu->GetChildViewAt(i); - int previous_count = *count; - RecursiveGetMenuItemIndexAndCount(child, item, index, count); - if (child->GetClassName() == views::MenuItemView::kViewClassName && - *count == previous_count) { - if (item == child) - *index = *count; - (*count)++; - } else if (child->GetClassName() == views::TextButton::kViewClassName) { - if (item == child) - *index = *count; - (*count)++; - } - } -} - -bool AccessibilityEventRouterViews::IsMenuEvent( - views::View* view, NotificationType type) { - if (type == NotificationType::ACCESSIBILITY_MENU_OPENED || - type == NotificationType::ACCESSIBILITY_MENU_CLOSED) - return true; - - while (view) { - ui::AccessibleViewState state; - view->GetAccessibleState(&state); - ui::AccessibilityTypes::Role role = state.role; - if (role == ui::AccessibilityTypes::ROLE_MENUITEM || - role == ui::AccessibilityTypes::ROLE_MENUPOPUP) { - return true; - } - view = view->parent(); - } - - return false; -} - -void AccessibilityEventRouterViews::SendLocationBarNotification( - views::View* view, NotificationType type, Profile* profile) { - ui::AccessibleViewState state; - view->GetAccessibleState(&state); - std::string name = UTF16ToUTF8(state.name); - AccessibilityTextBoxInfo info(profile, name, false); - std::string value = UTF16ToUTF8(state.value); - info.SetValue(value, state.selection_start, state.selection_end); - SendAccessibilityNotification(type, &info); -} - void AccessibilityEventRouterViews::SendTextfieldNotification( - views::View* view, NotificationType type, Profile* profile) { + views::View* view, + NotificationType type, + Profile* profile) { ui::AccessibleViewState state; view->GetAccessibleState(&state); std::string name = UTF16ToUTF8(state.name); - views::Textfield* textfield = static_cast<views::Textfield*>(view); - bool password = textfield->IsPassword(); + bool password = + (state.state & ui::AccessibilityTypes::STATE_PROTECTED) != 0; AccessibilityTextBoxInfo info(profile, name, password); std::string value = UTF16ToUTF8(state.value); info.SetValue(value, state.selection_start, state.selection_end); @@ -272,7 +239,9 @@ void AccessibilityEventRouterViews::SendTextfieldNotification( } void AccessibilityEventRouterViews::SendComboboxNotification( - views::View* view, NotificationType type, Profile* profile) { + views::View* view, + NotificationType type, + Profile* profile) { ui::AccessibleViewState state; view->GetAccessibleState(&state); std::string name = UTF16ToUTF8(state.name); @@ -283,7 +252,9 @@ void AccessibilityEventRouterViews::SendComboboxNotification( } void AccessibilityEventRouterViews::SendCheckboxNotification( - views::View* view, NotificationType type, Profile* profile) { + views::View* view, + NotificationType type, + Profile* profile) { ui::AccessibleViewState state; view->GetAccessibleState(&state); std::string name = UTF16ToUTF8(state.name); @@ -293,3 +264,88 @@ void AccessibilityEventRouterViews::SendCheckboxNotification( SendAccessibilityNotification(type, &info); } +void AccessibilityEventRouterViews::SendWindowNotification( + views::View* view, + NotificationType type, + Profile* profile) { + ui::AccessibleViewState state; + view->GetAccessibleState(&state); + std::string window_text; + + // If it's an alert, try to get the text from the contents of the + // static text, not the window title. + if (state.role == ui::AccessibilityTypes::ROLE_ALERT) + window_text = RecursiveGetStaticText(view); + + // Otherwise get it from the window's accessible name. + if (window_text.empty()) + window_text = UTF16ToUTF8(state.name); + + AccessibilityWindowInfo info(profile, window_text); + SendAccessibilityNotification(type, &info); +} + +std::string AccessibilityEventRouterViews::GetViewName(views::View* view) { + ui::AccessibleViewState state; + view->GetAccessibleState(&state); + return UTF16ToUTF8(state.name); +} + +bool AccessibilityEventRouterViews::IsMenuEvent( + views::View* view, + NotificationType type) { + if (type == NotificationType::ACCESSIBILITY_MENU_OPENED || + type == NotificationType::ACCESSIBILITY_MENU_CLOSED) + return true; + + while (view) { + ui::AccessibleViewState state; + view->GetAccessibleState(&state); + ui::AccessibilityTypes::Role role = state.role; + if (role == ui::AccessibilityTypes::ROLE_MENUITEM || + role == ui::AccessibilityTypes::ROLE_MENUPOPUP) { + return true; + } + view = view->parent(); + } + + return false; +} + +void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount( + views::View* menu, + views::View* item, + int* index, + int* count) { + for (int i = 0; i < menu->child_count(); ++i) { + views::View* child = menu->GetChildViewAt(i); + int previous_count = *count; + RecursiveGetMenuItemIndexAndCount(child, item, index, count); + if (child->GetClassName() == views::MenuItemView::kViewClassName && + *count == previous_count) { + if (item == child) + *index = *count; + (*count)++; + } else if (child->GetClassName() == views::TextButton::kViewClassName) { + if (item == child) + *index = *count; + (*count)++; + } + } +} + +std::string AccessibilityEventRouterViews::RecursiveGetStaticText( + views::View* view) { + ui::AccessibleViewState state; + view->GetAccessibleState(&state); + if (state.role == ui::AccessibilityTypes::ROLE_STATICTEXT) + return UTF16ToUTF8(state.name); + + for (int i = 0; i < view->child_count(); ++i) { + views::View* child = view->GetChildViewAt(i); + std::string result = RecursiveGetStaticText(child); + if (!result.empty()) + return result; + } + return std::string(); +} diff --git a/chrome/browser/ui/views/accessibility_event_router_views.h b/chrome/browser/ui/views/accessibility_event_router_views.h index 44908bd..8890026 100644 --- a/chrome/browser/ui/views/accessibility_event_router_views.h +++ b/chrome/browser/ui/views/accessibility_event_router_views.h @@ -78,9 +78,6 @@ class AccessibilityEventRouterViews { void DispatchAccessibilityNotification( views::View* view, NotificationType type); - // Return the name of a view. - std::string GetViewName(views::View* view); - // Each of these methods constructs an AccessibilityControlInfo object // and sends a notification of a specific accessibility event. void SendButtonNotification( @@ -91,14 +88,17 @@ class AccessibilityEventRouterViews { views::View* view, NotificationType type, Profile* profile); void SendMenuItemNotification( views::View* view, NotificationType type, Profile* profile); - void SendLocationBarNotification( - views::View* view, NotificationType type, Profile* profile); void SendTextfieldNotification( views::View* view, NotificationType type, Profile* profile); void SendComboboxNotification( views::View* view, NotificationType type, Profile* profile); void SendCheckboxNotification( views::View* view, NotificationType type, Profile* profile); + void SendWindowNotification( + views::View* view, NotificationType type, Profile* profile); + + // Return the name of a view. + std::string GetViewName(views::View* view); // Return true if it's an event on a menu. bool IsMenuEvent(views::View* view, NotificationType type); @@ -111,6 +111,10 @@ class AccessibilityEventRouterViews { void RecursiveGetMenuItemIndexAndCount( views::View* menu, views::View* item, int* index, int* count); + // Recursively explore the subviews and return the text from the first + // subview with a role of STATIC_TEXT. + std::string RecursiveGetStaticText(views::View* view); + // The profile associated with the most recent window event - used to // figure out where to route a few events that can't be directly traced // to a window with a profile (like menu events). diff --git a/chrome/browser/ui/views/browser_actions_container.cc b/chrome/browser/ui/views/browser_actions_container.cc index 63f4e9d..5bfb2bd 100644 --- a/chrome/browser/ui/views/browser_actions_container.cc +++ b/chrome/browser/ui/views/browser_actions_container.cc @@ -172,6 +172,7 @@ void BrowserActionButton::UpdateState() { if (name.empty()) name = UTF8ToUTF16(extension()->name()); SetTooltipText(UTF16ToWideHack(name)); + SetAccessibleName(name); parent()->SchedulePaint(); } diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 5b320bb..9b3b79f 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc @@ -1066,7 +1066,7 @@ bool LocationBarView::SkipDefaultKeyEventProcessing( } void LocationBarView::GetAccessibleState(ui::AccessibleViewState* state) { - state->role = ui::AccessibilityTypes::ROLE_GROUPING; + state->role = ui::AccessibilityTypes::ROLE_LOCATION_BAR; state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION); state->value = location_entry_->GetText(); diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.cc b/chrome/browser/ui/views/location_bar/page_action_image_view.cc index 5a43196..3cbad31 100644 --- a/chrome/browser/ui/views/location_bar/page_action_image_view.cc +++ b/chrome/browser/ui/views/location_bar/page_action_image_view.cc @@ -105,6 +105,7 @@ void PageActionImageView::ExecuteAction(int button, void PageActionImageView::GetAccessibleState(ui::AccessibleViewState* state) { state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON; + state->name = UTF8ToUTF16(tooltip_); } bool PageActionImageView::OnMousePressed(const views::MouseEvent& event) { diff --git a/ui/base/accessibility/accessibility_types.h b/ui/base/accessibility/accessibility_types.h index 62f3255..2d11908 100644 --- a/ui/base/accessibility/accessibility_types.h +++ b/ui/base/accessibility/accessibility_types.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -60,6 +60,7 @@ class AccessibilityTypes { ROLE_GRAPHIC, ROLE_GROUPING, ROLE_LINK, + ROLE_LOCATION_BAR, ROLE_MENUBAR, ROLE_MENUITEM, ROLE_MENUPOPUP, diff --git a/views/accessibility/native_view_accessibility_win.cc b/views/accessibility/native_view_accessibility_win.cc index e36c406..c75cb07 100644 --- a/views/accessibility/native_view_accessibility_win.cc +++ b/views/accessibility/native_view_accessibility_win.cc @@ -620,6 +620,8 @@ return ROLE_SYSTEM_ALERT; return ROLE_SYSTEM_GROUPING; case AccessibilityTypes::ROLE_LINK: return ROLE_SYSTEM_LINK; + case AccessibilityTypes::ROLE_LOCATION_BAR: + return ROLE_SYSTEM_GROUPING; case AccessibilityTypes::ROLE_MENUBAR: return ROLE_SYSTEM_MENUBAR; case AccessibilityTypes::ROLE_MENUITEM: diff --git a/views/controls/message_box_view.cc b/views/controls/message_box_view.cc index df35312..2710894 100644 --- a/views/controls/message_box_view.cc +++ b/views/controls/message_box_view.cc @@ -7,6 +7,7 @@ #include "base/i18n/rtl.h" #include "base/message_loop.h" #include "base/utf_string_conversions.h" +#include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/message_box_flags.h" @@ -17,6 +18,7 @@ #include "views/layout/grid_layout.h" #include "views/layout/layout_constants.h" #include "views/views_delegate.h" +#include "views/widget/widget.h" #include "views/window/client_view.h" static const int kDefaultMessageWidth = 320; @@ -85,6 +87,10 @@ void MessageBoxView::SetCheckBoxSelected(bool selected) { checkbox_->SetChecked(selected); } +void MessageBoxView::GetAccessibleState(ui::AccessibleViewState* state) { + state->role = ui::AccessibilityTypes::ROLE_ALERT; +} + /////////////////////////////////////////////////////////////////////////////// // MessageBoxView, View overrides: @@ -94,6 +100,9 @@ void MessageBoxView::ViewHierarchyChanged(bool is_add, if (child == this && is_add) { if (prompt_field_) prompt_field_->SelectAll(); + + GetWidget()->NotifyAccessibilityEvent( + this, ui::AccessibilityTypes::EVENT_ALERT, true); } } diff --git a/views/controls/message_box_view.h b/views/controls/message_box_view.h index 9734d17..a3f1355 100644 --- a/views/controls/message_box_view.h +++ b/views/controls/message_box_view.h @@ -56,6 +56,9 @@ class MessageBoxView : public View { // Sets the state of the check-box. void SetCheckBoxSelected(bool selected); + // View: + virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; + protected: // View: virtual void ViewHierarchyChanged(bool is_add, |