diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-21 14:41:14 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-21 14:41:14 +0000 |
commit | 7d5ac9e5a0f5f18cac2f2a8b45de1eeab2751a79 (patch) | |
tree | 25ce776c3c8ebe4bc0a6e971315da42e6cab27b8 | |
parent | cfcf2da53e0439a8e7529392fd19762d0a39e43a (diff) | |
download | chromium_src-7d5ac9e5a0f5f18cac2f2a8b45de1eeab2751a79.zip chromium_src-7d5ac9e5a0f5f18cac2f2a8b45de1eeab2751a79.tar.gz chromium_src-7d5ac9e5a0f5f18cac2f2a8b45de1eeab2751a79.tar.bz2 |
Make the Downloads Shelf keyboard-accessible (via F6) and accessible to
screenreaders. Rename AccessibleToolbarView to AccessiblePaneView to reflect
that it covers more than just toolbars. Also add infobars to the F6 pane
traversal.
BUG=372
TEST=none
Review URL: http://codereview.chromium.org/3722004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63358 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 347 insertions, 178 deletions
diff --git a/chrome/browser/chromeos/frame/browser_view.cc b/chrome/browser/chromeos/frame/browser_view.cc index 89100b1..0791237 100644 --- a/chrome/browser/chromeos/frame/browser_view.cc +++ b/chrome/browser/chromeos/frame/browser_view.cc @@ -260,7 +260,7 @@ void BrowserView::Show() { void BrowserView::FocusChromeOSStatus() { SaveFocusedView(); - status_area_->SetToolbarFocus(last_focused_view_storage_id(), NULL); + status_area_->SetPaneFocus(last_focused_view_storage_id(), NULL); } views::LayoutManager* BrowserView::CreateLayoutManager() const { @@ -339,10 +339,10 @@ bool BrowserView::IsScreenLockerMode() const { //////////////////////////////////////////////////////////////////////////////// // BrowserView protected: -void BrowserView::GetAccessibleToolbars( - std::vector<AccessibleToolbarView*>* toolbars) { - ::BrowserView::GetAccessibleToolbars(toolbars); - toolbars->push_back(status_area_); +void BrowserView::GetAccessiblePanes( + std::vector<AccessiblePaneView*>* panes) { + ::BrowserView::GetAccessiblePanes(panes); + panes->push_back(status_area_); } //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/chromeos/frame/browser_view.h b/chrome/browser/chromeos/frame/browser_view.h index 3c81c12..dc88ec2 100644 --- a/chrome/browser/chromeos/frame/browser_view.h +++ b/chrome/browser/chromeos/frame/browser_view.h @@ -69,8 +69,8 @@ class BrowserView : public ::BrowserView, virtual bool IsScreenLockerMode() const; protected: - virtual void GetAccessibleToolbars( - std::vector<AccessibleToolbarView*>* toolbars); + virtual void GetAccessiblePanes( + std::vector<AccessiblePaneView*>* panes); private: void InitSystemMenu(); diff --git a/chrome/browser/chromeos/status/status_area_view.h b/chrome/browser/chromeos/status/status_area_view.h index b119667..5fbae5f 100644 --- a/chrome/browser/chromeos/status/status_area_view.h +++ b/chrome/browser/chromeos/status/status_area_view.h @@ -7,7 +7,7 @@ #pragma once #include "base/basictypes.h" -#include "chrome/browser/views/accessible_toolbar_view.h" +#include "chrome/browser/views/accessible_pane_view.h" #include "views/view.h" namespace chromeos { @@ -21,7 +21,7 @@ class StatusAreaHost; // This class is used to wrap the small informative widgets in the upper-right // of the window title bar. It is used on ChromeOS only. -class StatusAreaView : public AccessibleToolbarView { +class StatusAreaView : public AccessiblePaneView { public: explicit StatusAreaView(StatusAreaHost* host); virtual ~StatusAreaView() {} diff --git a/chrome/browser/views/accessibility_event_router_views.cc b/chrome/browser/views/accessibility_event_router_views.cc index b8bfc25..efd9b71 100644 --- a/chrome/browser/views/accessibility_event_router_views.cc +++ b/chrome/browser/views/accessibility_event_router_views.cc @@ -67,9 +67,6 @@ void AccessibilityEventRouterViews::RemoveView(views::View* view) { void AccessibilityEventRouterViews::HandleAccessibilityEvent( views::View* view, AccessibilityTypes::Event event_type) { switch (event_type) { - case AccessibilityTypes::EVENT_ALERT: - // TODO(dtseng): does this have any meaning in this context. - break; case AccessibilityTypes::EVENT_FOCUS: DispatchAccessibilityNotification( view, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED); @@ -84,6 +81,13 @@ void AccessibilityEventRouterViews::HandleAccessibilityEvent( DispatchAccessibilityNotification( view, NotificationType::ACCESSIBILITY_MENU_CLOSED); break; + case AccessibilityTypes::EVENT_ALERT: + case AccessibilityTypes::EVENT_NAMECHANGE: + // 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; } } diff --git a/chrome/browser/views/accessible_toolbar_view.cc b/chrome/browser/views/accessible_pane_view.cc index 4aae6ac..b876940 100644 --- a/chrome/browser/views/accessible_toolbar_view.cc +++ b/chrome/browser/views/accessible_pane_view.cc @@ -6,7 +6,7 @@ #include "chrome/browser/view_ids.h" #include "chrome/browser/views/frame/browser_view.h" #include "chrome/browser/views/location_bar/location_bar_view.h" -#include "chrome/browser/views/accessible_toolbar_view.h" +#include "chrome/browser/views/accessible_pane_view.h" #include "views/controls/button/menu_button.h" #include "views/controls/native/native_view_host.h" #include "views/focus/focus_search.h" @@ -14,8 +14,8 @@ #include "views/widget/tooltip_manager.h" #include "views/widget/widget.h" -AccessibleToolbarView::AccessibleToolbarView() - : toolbar_has_focus_(false), +AccessiblePaneView::AccessiblePaneView() + : pane_has_focus_(false), ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), focus_manager_(NULL), home_key_(app::VKEY_HOME, false, false, false), @@ -27,14 +27,14 @@ AccessibleToolbarView::AccessibleToolbarView() focus_search_.reset(new views::FocusSearch(this, true, true)); } -AccessibleToolbarView::~AccessibleToolbarView() { - if (toolbar_has_focus_) { +AccessiblePaneView::~AccessiblePaneView() { + if (pane_has_focus_) { focus_manager_->RemoveFocusChangeListener(this); } } -bool AccessibleToolbarView::SetToolbarFocus(int view_storage_id, - views::View* initial_focus) { +bool AccessiblePaneView::SetPaneFocus(int view_storage_id, + views::View* initial_focus) { if (!IsVisible()) return false; @@ -66,12 +66,12 @@ bool AccessibleToolbarView::SetToolbarFocus(int view_storage_id, focus_manager_->SetFocusedView(initial_focus); } - // If we already have toolbar focus, we're done. - if (toolbar_has_focus_) + // If we already have pane focus, we're done. + if (pane_has_focus_) return true; // Otherwise, set accelerators and start listening for focus change events. - toolbar_has_focus_ = true; + pane_has_focus_ = true; focus_manager_->RegisterAccelerator(home_key_, this); focus_manager_->RegisterAccelerator(end_key_, this); focus_manager_->RegisterAccelerator(escape_key_, this); @@ -82,14 +82,14 @@ bool AccessibleToolbarView::SetToolbarFocus(int view_storage_id, return true; } -bool AccessibleToolbarView::SetToolbarFocusAndFocusDefault( +bool AccessiblePaneView::SetPaneFocusAndFocusDefault( int view_storage_id) { - return SetToolbarFocus(view_storage_id, GetDefaultFocusableChild()); + return SetPaneFocus(view_storage_id, GetDefaultFocusableChild()); } -void AccessibleToolbarView::RemoveToolbarFocus() { +void AccessiblePaneView::RemovePaneFocus() { focus_manager_->RemoveFocusChangeListener(this); - toolbar_has_focus_ = false; + pane_has_focus_ = false; focus_manager_->UnregisterAccelerator(home_key_, this); focus_manager_->UnregisterAccelerator(end_key_, this); @@ -98,7 +98,7 @@ void AccessibleToolbarView::RemoveToolbarFocus() { focus_manager_->UnregisterAccelerator(right_key_, this); } -void AccessibleToolbarView::LocationBarSelectAll() { +void AccessiblePaneView::LocationBarSelectAll() { views::View* focused_view = GetFocusManager()->GetFocusedView(); if (focused_view && focused_view->GetClassName() == LocationBarView::kViewClassName) { @@ -106,7 +106,7 @@ void AccessibleToolbarView::LocationBarSelectAll() { } } -void AccessibleToolbarView::RestoreLastFocusedView() { +void AccessiblePaneView::RestoreLastFocusedView() { views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); views::View* last_focused_view = view_storage->RetrieveView(last_focused_view_storage_id_); @@ -123,7 +123,7 @@ void AccessibleToolbarView::RestoreLastFocusedView() { } } -views::View* AccessibleToolbarView::GetFirstFocusableChild() { +views::View* AccessiblePaneView::GetFirstFocusableChild() { FocusTraversable* dummy_focus_traversable; views::View* dummy_focus_traversable_view; return focus_search_->FindNextFocusableView( @@ -131,7 +131,7 @@ views::View* AccessibleToolbarView::GetFirstFocusableChild() { &dummy_focus_traversable, &dummy_focus_traversable_view); } -views::View* AccessibleToolbarView::GetLastFocusableChild() { +views::View* AccessiblePaneView::GetLastFocusableChild() { FocusTraversable* dummy_focus_traversable; views::View* dummy_focus_traversable_view; return focus_search_->FindNextFocusableView( @@ -142,14 +142,14 @@ views::View* AccessibleToolbarView::GetLastFocusableChild() { //////////////////////////////////////////////////////////////////////////////// // View overrides: -views::FocusTraversable* AccessibleToolbarView::GetPaneFocusTraversable() { - if (toolbar_has_focus_) +views::FocusTraversable* AccessiblePaneView::GetPaneFocusTraversable() { + if (pane_has_focus_) return this; else return NULL; } -bool AccessibleToolbarView::AcceleratorPressed( +bool AccessiblePaneView::AcceleratorPressed( const views::Accelerator& accelerator) { // Special case: don't handle any accelerators for the location bar, // so that it behaves exactly the same whether you focus it with Ctrl+L @@ -162,7 +162,7 @@ bool AccessibleToolbarView::AcceleratorPressed( switch (accelerator.GetKeyCode()) { case app::VKEY_ESCAPE: - RemoveToolbarFocus(); + RemovePaneFocus(); RestoreLastFocusedView(); return true; case app::VKEY_LEFT: @@ -184,23 +184,23 @@ bool AccessibleToolbarView::AcceleratorPressed( } } -void AccessibleToolbarView::SetVisible(bool flag) { - if (IsVisible() && !flag && toolbar_has_focus_) { - RemoveToolbarFocus(); +void AccessiblePaneView::SetVisible(bool flag) { + if (IsVisible() && !flag && pane_has_focus_) { + RemovePaneFocus(); RestoreLastFocusedView(); } View::SetVisible(flag); } -AccessibilityTypes::Role AccessibleToolbarView::GetAccessibleRole() { - return AccessibilityTypes::ROLE_TOOLBAR; +AccessibilityTypes::Role AccessiblePaneView::GetAccessibleRole() { + return AccessibilityTypes::ROLE_PANE; } //////////////////////////////////////////////////////////////////////////////// // FocusChangeListener overrides: -void AccessibleToolbarView::FocusWillChange(views::View* focused_before, - views::View* focused_now) { +void AccessiblePaneView::FocusWillChange(views::View* focused_before, + views::View* focused_now) { if (!focused_now) return; @@ -213,39 +213,39 @@ void AccessibleToolbarView::FocusWillChange(views::View* focused_before, // after the focus. MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &AccessibleToolbarView::LocationBarSelectAll)); + &AccessiblePaneView::LocationBarSelectAll)); } if (!IsParentOf(focused_now) || reason == views::FocusManager::kReasonDirectFocusChange) { - // We should remove toolbar focus (i.e. make most of the controls - // not focusable again) either because the focus is leaving the toolbar, - // or because the focus changed within the toolbar due to the user + // We should remove pane focus (i.e. make most of the controls + // not focusable again) either because the focus is leaving the pane, + // or because the focus changed within the pane due to the user // directly focusing to a specific view (e.g., clicking on it). // - // Defer rather than calling RemoveToolbarFocus right away, because we can't + // Defer rather than calling RemovePaneFocus right away, because we can't // remove |this| as a focus change listener while FocusManager is in the // middle of iterating over the list of listeners. MessageLoop::current()->PostTask( FROM_HERE, method_factory_.NewRunnableMethod( - &AccessibleToolbarView::RemoveToolbarFocus)); + &AccessiblePaneView::RemovePaneFocus)); } } //////////////////////////////////////////////////////////////////////////////// // FocusTraversable overrides: -views::FocusSearch* AccessibleToolbarView::GetFocusSearch() { - DCHECK(toolbar_has_focus_); +views::FocusSearch* AccessiblePaneView::GetFocusSearch() { + DCHECK(pane_has_focus_); return focus_search_.get(); } -views::FocusTraversable* AccessibleToolbarView::GetFocusTraversableParent() { - DCHECK(toolbar_has_focus_); +views::FocusTraversable* AccessiblePaneView::GetFocusTraversableParent() { + DCHECK(pane_has_focus_); return NULL; } -views::View* AccessibleToolbarView::GetFocusTraversableParentView() { - DCHECK(toolbar_has_focus_); +views::View* AccessiblePaneView::GetFocusTraversableParentView() { + DCHECK(pane_has_focus_); return NULL; } diff --git a/chrome/browser/views/accessible_toolbar_view.h b/chrome/browser/views/accessible_pane_view.h index 3d4e976..f31f59b 100644 --- a/chrome/browser/views/accessible_toolbar_view.h +++ b/chrome/browser/views/accessible_pane_view.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_VIEWS_ACCESSIBLE_TOOLBAR_VIEW_H_ -#define CHROME_BROWSER_VIEWS_ACCESSIBLE_TOOLBAR_VIEW_H_ +#ifndef CHROME_BROWSER_VIEWS_ACCESSIBLE_PANE_VIEW_H_ +#define CHROME_BROWSER_VIEWS_ACCESSIBLE_PANE_VIEW_H_ #pragma once #include "base/hash_tables.h" @@ -19,26 +19,26 @@ class FocusSearch; // This class provides keyboard access to any view that extends it, typically // a toolbar. The user sets focus to a control in this view by pressing // F6 to traverse all panes, or by pressing a shortcut that jumps directly -// to this toolbar. -class AccessibleToolbarView : public views::View, - public views::FocusChangeListener, - public views::FocusTraversable { +// to this pane. +class AccessiblePaneView : public views::View, + public views::FocusChangeListener, + public views::FocusTraversable { public: - AccessibleToolbarView(); - virtual ~AccessibleToolbarView(); + AccessiblePaneView(); + virtual ~AccessiblePaneView(); - // Set focus to the toolbar with complete keyboard access. + // Set focus to the pane with complete keyboard access. // Focus will be restored to the ViewStorage with id |view_storage_id| // if the user escapes. If |initial_focus| is not NULL, that control will get // the initial focus, if it's enabled and focusable. Returns true if - // the toolbar was able to receive focus. - virtual bool SetToolbarFocus(int view_storage_id, View* initial_focus); + // the pane was able to receive focus. + virtual bool SetPaneFocus(int view_storage_id, View* initial_focus); - // Set focus to the toolbar with complete keyboard access, with the + // Set focus to the pane with complete keyboard access, with the // focus initially set to the default child. Focus will be restored // to the ViewStorage with id |view_storage_id| if the user escapes. - // Returns true if the toolbar was able to receive focus. - virtual bool SetToolbarFocusAndFocusDefault(int view_storage_id); + // Returns true if the pane was able to receive focus. + virtual bool SetPaneFocusAndFocusDefault(int view_storage_id); // Overridden from views::View: virtual FocusTraversable* GetPaneFocusTraversable(); @@ -60,8 +60,8 @@ class AccessibleToolbarView : public views::View, // other than the first focusable child. virtual views::View* GetDefaultFocusableChild() { return NULL; } - // Remove toolbar focus. - virtual void RemoveToolbarFocus(); + // Remove pane focus. + virtual void RemovePaneFocus(); // Select all text in the location bar virtual void LocationBarSelectAll(); @@ -71,16 +71,16 @@ class AccessibleToolbarView : public views::View, View* GetFirstFocusableChild(); View* GetLastFocusableChild(); - bool toolbar_has_focus_; + bool pane_has_focus_; - ScopedRunnableMethodFactory<AccessibleToolbarView> method_factory_; + ScopedRunnableMethodFactory<AccessiblePaneView> method_factory_; // Save the focus manager rather than calling GetFocusManager(), // so that we can remove focus listeners in the destructor. views::FocusManager* focus_manager_; // Our custom focus search implementation that traps focus in this - // toolbar and traverses all views that are focusable for accessibility, + // pane and traverses all views that are focusable for accessibility, // not just those that are normally focusable. scoped_ptr<views::FocusSearch> focus_search_; @@ -94,7 +94,7 @@ class AccessibleToolbarView : public views::View, // Last focused view that issued this traversal. int last_focused_view_storage_id_; - DISALLOW_COPY_AND_ASSIGN(AccessibleToolbarView); + DISALLOW_COPY_AND_ASSIGN(AccessiblePaneView); }; -#endif // CHROME_BROWSER_VIEWS_ACCESSIBLE_TOOLBAR_VIEW_H_ +#endif // CHROME_BROWSER_VIEWS_ACCESSIBLE_PANE_VIEW_H_ diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index 8c38088..cd03a56 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -713,6 +713,10 @@ bool BookmarkBarView::IsAccessibleViewTraversable(views::View* view) { return view != bookmarks_separator_view_ && view != instructions_; } +AccessibilityTypes::Role BookmarkBarView::GetAccessibleRole() { + return AccessibilityTypes::ROLE_TOOLBAR; +} + void BookmarkBarView::OnStateChanged() { // When the sync state changes, it is sufficient to invoke View::Layout since // during layout we query the profile sync service and determine whether the diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h index d667ad4..37b606f 100644 --- a/chrome/browser/views/bookmark_bar_view.h +++ b/chrome/browser/views/bookmark_bar_view.h @@ -134,8 +134,9 @@ class BookmarkBarView : public DetachableToolbarView, virtual int OnPerformDrop(const views::DropTargetEvent& event); virtual void ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture); - // AccessibleToolbarView methods: + // AccessiblePaneView methods: virtual bool IsAccessibleViewTraversable(views::View* view); + virtual AccessibilityTypes::Role GetAccessibleRole(); // ProfileSyncServiceObserver method. virtual void OnStateChanged(); diff --git a/chrome/browser/views/detachable_toolbar_view.h b/chrome/browser/views/detachable_toolbar_view.h index 0211e88..fe6137b 100644 --- a/chrome/browser/views/detachable_toolbar_view.h +++ b/chrome/browser/views/detachable_toolbar_view.h @@ -6,14 +6,14 @@ #define CHROME_BROWSER_VIEWS_DETACHABLE_TOOLBAR_VIEW_H_ #pragma once -#include "chrome/browser/views/accessible_toolbar_view.h" +#include "chrome/browser/views/accessible_pane_view.h" class SkBitmap; struct SkRect; // DetachableToolbarView contains functionality common to views that can detach // from the Chrome frame, such as the BookmarkBarView and the Extension shelf. -class DetachableToolbarView : public AccessibleToolbarView { +class DetachableToolbarView : public AccessiblePaneView { public: // The color gradient start value close to the edge of the divider. static const SkColor kEdgeDividerColor; diff --git a/chrome/browser/views/download_item_view.cc b/chrome/browser/views/download_item_view.cc index ebaa8916..b47d0dd 100644 --- a/chrome/browser/views/download_item_view.cc +++ b/chrome/browser/views/download_item_view.cc @@ -298,6 +298,9 @@ DownloadItemView::DownloadItemView(DownloadItem* download, SizeLabelToMinWidth(); } + UpdateAccessibleName(); + set_accessibility_focusable(true); + // Set up our animation. StartDownloadProgress(); } @@ -379,6 +382,7 @@ void DownloadItemView::OnDownloadUpdated(DownloadItem* download) { } status_text_ = status_text; + UpdateAccessibleName(); // We use the parent's (DownloadShelfView's) SchedulePaint, since there // are spaces between each DownloadItemView that the parent is responsible @@ -721,6 +725,10 @@ void DownloadItemView::ClearDangerousMode() { delete dangerous_download_label_; dangerous_download_label_ = NULL; + // Set the accessible name back to the status and filename instead of the + // download warning. + UpdateAccessibleName(); + // We need to load the icon now that the download_ has the real path. LoadIcon(); tooltip_text_ = download_->GetFileName().ToWStringHack(); @@ -770,7 +778,8 @@ void DownloadItemView::OnMouseExited(const views::MouseEvent& event) { drop_hover_animation_->Hide(); } -// Display the context menu for this item. +// Handle a mouse click and open the context menu if the mouse is +// over the drop-down region. bool DownloadItemView::OnMousePressed(const views::MouseEvent& event) { // Mouse should not activate us in dangerous mode. if (IsDangerousMode()) @@ -781,54 +790,12 @@ bool DownloadItemView::OnMousePressed(const views::MouseEvent& event) { complete_animation_->End(); if (event.IsOnlyLeftMouseButton()) { - gfx::Point point(event.location()); if (!InDropDownButtonXCoordinateRange(event.x())) { SetState(PUSHED, NORMAL); return true; } - drop_down_pressed_ = true; - SetState(NORMAL, PUSHED); - - // Similar hack as in MenuButton. - // We're about to show the menu from a mouse press. By showing from the - // mouse press event we block RootView in mouse dispatching. This also - // appears to cause RootView to get a mouse pressed BEFORE the mouse - // release is seen, which means RootView sends us another mouse press no - // matter where the user pressed. To force RootView to recalculate the - // mouse target during the mouse press we explicitly set the mouse handler - // to NULL. - GetRootView()->SetMouseHandler(NULL); - - // The menu's position is different depending on the UI layout. - // DownloadShelfContextMenu will take care of setting the right anchor for - // the menu depending on the locale. - point.set_y(height()); - if (base::i18n::IsRTL()) - point.set_x(drop_down_x_right_); - else - point.set_x(drop_down_x_left_); - - views::View::ConvertPointToScreen(this, &point); - - if (!context_menu_.get()) - context_menu_.reset(new DownloadShelfContextMenuWin(model_.get())); - // When we call the Run method on the menu, it runs an inner message loop - // that might causes us to be deleted. - bool deleted = false; - deleted_ = &deleted; - context_menu_->Run(point); - if (deleted) - return true; // We have been deleted! Don't access 'this'. - deleted_ = NULL; - - // If the menu action was to remove the download, this view will also be - // invalid so we must not access 'this' in this case. - if (context_menu_->download()) { - drop_down_pressed_ = false; - // Showing the menu blocks. Here we revert the state. - SetState(NORMAL, NORMAL); - } + ShowContextMenu(event.location(), false); } return true; } @@ -862,8 +829,9 @@ void DownloadItemView::OnMouseReleased(const views::MouseEvent& event, return; } if (event.IsOnlyLeftMouseButton() && - !InDropDownButtonXCoordinateRange(event.x())) + !InDropDownButtonXCoordinateRange(event.x())) { OpenDownload(); + } SetState(NORMAL, NORMAL); } @@ -897,6 +865,78 @@ bool DownloadItemView::OnMouseDragged(const views::MouseEvent& event) { return true; } +bool DownloadItemView::OnKeyPressed(const views::KeyEvent& e) { + // Key press should not activate us in dangerous mode. + if (IsDangerousMode()) + return true; + + if (e.GetKeyCode() == app::VKEY_SPACE || + e.GetKeyCode() == app::VKEY_RETURN) { + OpenDownload(); + return true; + } + return false; +} + +void DownloadItemView::ShowContextMenu(const gfx::Point& p, + bool is_mouse_gesture) { + gfx::Point point = p; + drop_down_pressed_ = true; + SetState(NORMAL, PUSHED); + + // Similar hack as in MenuButton. + // We're about to show the menu from a mouse press. By showing from the + // mouse press event we block RootView in mouse dispatching. This also + // appears to cause RootView to get a mouse pressed BEFORE the mouse + // release is seen, which means RootView sends us another mouse press no + // matter where the user pressed. To force RootView to recalculate the + // mouse target during the mouse press we explicitly set the mouse handler + // to NULL. + GetRootView()->SetMouseHandler(NULL); + + // The menu's position is different depending on the UI layout. + // DownloadShelfContextMenu will take care of setting the right anchor for + // the menu depending on the locale. + point.set_y(height()); + if (base::i18n::IsRTL()) + point.set_x(drop_down_x_right_); + else + point.set_x(drop_down_x_left_); + + views::View::ConvertPointToScreen(this, &point); + + if (!context_menu_.get()) + context_menu_.reset(new DownloadShelfContextMenuWin(model_.get())); + // When we call the Run method on the menu, it runs an inner message loop + // that might causes us to be deleted. + bool deleted = false; + deleted_ = &deleted; + context_menu_->Run(point); + if (deleted) + return; // We have been deleted! Don't access 'this'. + deleted_ = NULL; + + // If the menu action was to remove the download, this view will also be + // invalid so we must not access 'this' in this case. + if (context_menu_->download()) { + drop_down_pressed_ = false; + // Showing the menu blocks. Here we revert the state. + SetState(NORMAL, NORMAL); + } +} + +AccessibilityTypes::Role DownloadItemView::GetAccessibleRole() { + return AccessibilityTypes::ROLE_PUSHBUTTON; +} + +AccessibilityTypes::State DownloadItemView::GetAccessibleState() { + if (download_->safety_state() == DownloadItem::DANGEROUS) { + return AccessibilityTypes::STATE_UNAVAILABLE; + } else { + return AccessibilityTypes::STATE_HASPOPUP; + } +} + void DownloadItemView::AnimationProgressed(const Animation* animation) { // We don't care if what animation (body button/drop button/complete), // is calling back, as they all have to go through the same paint call. @@ -909,6 +949,7 @@ void DownloadItemView::OpenDownload() { UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download", base::Time::Now() - creation_time_); download_->OpenDownload(); + UpdateAccessibleName(); } void DownloadItemView::OnExtractIconComplete(IconManager::Handle handle, @@ -1011,3 +1052,25 @@ bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) { return true; return false; } + +void DownloadItemView::UpdateAccessibleName() { + std::wstring current_name; + GetAccessibleName(¤t_name); + + std::wstring new_name; + if (download_->safety_state() == DownloadItem::DANGEROUS) { + new_name = dangerous_download_label_->GetText(); + } else { + new_name = status_text_ + L" " + + download_->GetFileName().ToWStringHack(); + } + + // If the name has changed, call SetAccessibleName and notify + // assistive technology that the name has changed so they can + // announce it immediately. + if (new_name != current_name) { + SetAccessibleName(new_name); + if (GetWidget()) + NotifyAccessibilityEvent(AccessibilityTypes::EVENT_NAMECHANGE); + } +} diff --git a/chrome/browser/views/download_item_view.h b/chrome/browser/views/download_item_view.h index 91fc7f6..bd76c0d 100644 --- a/chrome/browser/views/download_item_view.h +++ b/chrome/browser/views/download_item_view.h @@ -66,6 +66,10 @@ class DownloadItemView : public views::ButtonListener, virtual bool OnMousePressed(const views::MouseEvent& event); virtual void OnMouseReleased(const views::MouseEvent& event, bool canceled); virtual bool OnMouseDragged(const views::MouseEvent& event); + virtual bool OnKeyPressed(const views::KeyEvent& e); + virtual void ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture); + virtual AccessibilityTypes::Role GetAccessibleRole(); + virtual AccessibilityTypes::State GetAccessibleState(); // ButtonListener implementation. virtual void ButtonPressed(views::Button* sender, const views::Event& event); @@ -155,6 +159,11 @@ class DownloadItemView : public views::ButtonListener, // the drop-down button or not. bool InDropDownButtonXCoordinateRange(int x); + // Update the accessible name to reflect the current state of the control, + // so that screenreaders can access the filename, status text, and + // dangerous download warning message (if any). + void UpdateAccessibleName(); + // The different images used for the background. BodyImageSet normal_body_image_set_; BodyImageSet hot_body_image_set_; diff --git a/chrome/browser/views/download_shelf_view.cc b/chrome/browser/views/download_shelf_view.cc index 3f9a825..43df5c7 100644 --- a/chrome/browser/views/download_shelf_view.cc +++ b/chrome/browser/views/download_shelf_view.cc @@ -113,6 +113,7 @@ void DownloadShelfView::Init() { rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); close_button_->SetImage(views::CustomButton::BS_PUSHED, rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); + close_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE)); UpdateButtonColors(); AddChildView(close_button_); @@ -149,6 +150,13 @@ void DownloadShelfView::MouseMovedOutOfView() { Close(); } +void DownloadShelfView::FocusWillChange(views::View* focused_before, + views::View* focused_now) { + SchedulePaintForDownloadItem(focused_before); + SchedulePaintForDownloadItem(focused_now); + AccessiblePaneView::FocusWillChange(focused_before, focused_now); +} + void DownloadShelfView::RemoveDownloadView(View* view) { DCHECK(view); std::vector<DownloadItemView*>::iterator i = @@ -165,9 +173,25 @@ void DownloadShelfView::RemoveDownloadView(View* view) { SchedulePaint(); } +views::View* DownloadShelfView::GetDefaultFocusableChild() { + if (!download_views_.empty()) + return download_views_[0]; + else + return show_all_view_; +} + void DownloadShelfView::Paint(gfx::Canvas* canvas) { PaintBackground(canvas); PaintBorder(canvas); + + // Draw the focus rect here, since it's outside the bounds of the item. + for (size_t i = 0; i < download_views_.size(); ++i) { + if (download_views_[i]->HasFocus()) { + gfx::Rect r = GetFocusRectBounds(download_views_[i]); + canvas->DrawFocusRect(r.x(), r.y(), r.width(), r.height() - 1); + break; + } + } } void DownloadShelfView::PaintBorder(gfx::Canvas* canvas) { @@ -381,3 +405,35 @@ bool DownloadShelfView::CanAutoClose() { } return true; } + +void DownloadShelfView::SchedulePaintForDownloadItem(views::View* view) { + // Make sure it's not NULL. (Focus sometimes changes to or from NULL.) + if (!view) + return; + + // Make sure it's one of our DownloadItemViews. + bool found = false; + for (size_t i = 0; i < download_views_.size(); ++i) { + if (download_views_[i] == view) + found = true; + } + if (!found) + return; + + // Invalidate it + gfx::Rect invalid_rect = + GetFocusRectBounds(static_cast<DownloadItemView*>(view)); + SchedulePaint(invalid_rect, false); +} + +gfx::Rect DownloadShelfView::GetFocusRectBounds( + const DownloadItemView* download_item_view) { + gfx::Rect bounds = download_item_view->bounds(); + +#if defined(TOOLKIT_VIEWS) + bounds.set_height(bounds.height() - 1); + bounds.Offset(0, 3); +#endif + + return bounds; +} diff --git a/chrome/browser/views/download_shelf_view.h b/chrome/browser/views/download_shelf_view.h index db7e53e..d307d6d 100644 --- a/chrome/browser/views/download_shelf_view.h +++ b/chrome/browser/views/download_shelf_view.h @@ -8,6 +8,7 @@ #include "app/slide_animation.h" #include "chrome/browser/download/download_shelf.h" +#include "chrome/browser/views/accessible_pane_view.h" #include "views/controls/button/button.h" #include "views/controls/link.h" #include "views/mouse_watcher.h" @@ -29,12 +30,12 @@ class DownloadItemView; // // DownloadShelfView does not hold an infinite number of download views, rather // it'll automatically remove views once a certain point is reached. -class DownloadShelfView : public AnimationDelegate, +class DownloadShelfView : public AccessiblePaneView, + public AnimationDelegate, public DownloadShelf, public views::ButtonListener, public views::LinkController, - public views::MouseWatcherListener, - public views::View { + public views::MouseWatcherListener { public: DownloadShelfView(Browser* browser, BrowserView* parent); virtual ~DownloadShelfView(); @@ -71,10 +72,18 @@ class DownloadShelfView : public AnimationDelegate, // Implementation of MouseWatcherDelegate. virtual void MouseMovedOutOfView(); + // Override views::FocusChangeListener method from AccessiblePaneView. + virtual void FocusWillChange(View* focused_before, + View* focused_now); + // Removes a specified download view. The supplied view is deleted after // it's removed. void RemoveDownloadView(views::View* view); + protected: + // From AccessiblePaneView + virtual views::View* GetDefaultFocusableChild(); + private: void Init(); @@ -102,6 +111,15 @@ class DownloadShelfView : public AnimationDelegate, // the shelf have been opened. bool CanAutoClose(); + // Called when any view |view| gains or loses focus. If it's one of our + // DownloadItemView children, call SchedulePaint on its bounds + // so that its focus rect is repainted. + void SchedulePaintForDownloadItem(views::View* view); + + // Get the rect that perfectly surrounds a DownloadItemView so we can + // draw a focus rect around it. + gfx::Rect GetFocusRectBounds(const DownloadItemView* download_item_view); + // The browser for this shelf. Browser* browser_; diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index bd3acc3..b09242b 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -891,13 +891,13 @@ void BrowserView::FocusToolbar() { // Start the traversal within the main toolbar, passing it the storage id // of the view where focus should be returned if the user exits the toolbar. SaveFocusedView(); - toolbar_->SetToolbarFocus(last_focused_view_storage_id_, NULL); + toolbar_->SetPaneFocus(last_focused_view_storage_id_, NULL); } void BrowserView::FocusBookmarksToolbar() { if (active_bookmark_bar_ && bookmark_bar_view_->IsVisible()) { SaveFocusedView(); - bookmark_bar_view_->SetToolbarFocus(last_focused_view_storage_id_, NULL); + bookmark_bar_view_->SetPaneFocus(last_focused_view_storage_id_, NULL); } } @@ -913,27 +913,27 @@ void BrowserView::FocusAppMenu() { RestoreFocus(); } else { SaveFocusedView(); - toolbar_->SetToolbarFocusAndFocusAppMenu(last_focused_view_storage_id_); + toolbar_->SetPaneFocusAndFocusAppMenu(last_focused_view_storage_id_); } } void BrowserView::RotatePaneFocus(bool forwards) { // This gets called when the user presses F6 (forwards) or Shift+F6 // (backwards) to rotate to the next pane. Here, our "panes" are the - // tab contents and each of our accessible toolbars. When a toolbar has - // pane focus, all of its controls are accessible in the tab traversal, - // and the tab traversal is "trapped" within that pane. - - // Get a vector of all panes in the order we want them to be focused - - // each of the accessible toolbars, then NULL to represent the tab contents - // getting focus. If one of these is currently invisible or has no - // focusable children it will be automatically skipped. - std::vector<AccessibleToolbarView*> accessible_toolbars; - GetAccessibleToolbars(&accessible_toolbars); - int toolbars_count = static_cast<int>(accessible_toolbars.size()); + // tab contents and each of our accessible toolbars, infobars, downloads + // shelf, etc. When a pane has focus, all of its controls are accessible + // in the tab traversal, and the tab traversal is "trapped" within that pane. + // + // Get a vector of all panes in the order we want them to be focused, + // with NULL to represent the tab contents getting focus. If one of these + // is currently invisible or has no focusable children it will be + // automatically skipped. + std::vector<AccessiblePaneView*> accessible_panes; + GetAccessiblePanes(&accessible_panes); + int pane_count = static_cast<int>(accessible_panes.size()); std::vector<views::View*> accessible_views( - accessible_toolbars.begin(), accessible_toolbars.end()); + accessible_panes.begin(), accessible_panes.end()); accessible_views.push_back(GetTabContentsContainerView()); if (sidebar_container_ && sidebar_container_->IsVisible()) accessible_views.push_back(GetSidebarContainerView()); @@ -954,13 +954,13 @@ void BrowserView::RotatePaneFocus(bool forwards) { } } - // If the focus isn't currently in a toolbar, save the focus so we + // If the focus isn't currently in a pane, save the focus so we // can restore it if the user presses Escape. - if (focused_view && index >= toolbars_count) + if (focused_view && index >= pane_count) SaveFocusedView(); - // Try to focus the next pane; if SetToolbarFocusAndFocusDefault returns - // false it means the toolbar didn't have any focusable controls, so skip + // Try to focus the next pane; if SetPaneFocusAndFocusDefault returns + // false it means the pane didn't have any focusable controls, so skip // it and try the next one. for (;;) { if (forwards) @@ -968,8 +968,8 @@ void BrowserView::RotatePaneFocus(bool forwards) { else index = ((index - 1) + count) % count; - if (index < toolbars_count) { - if (accessible_toolbars[index]->SetToolbarFocusAndFocusDefault( + if (index < pane_count) { + if (accessible_panes[index]->SetPaneFocusAndFocusDefault( last_focused_view_storage_id_)) { break; } @@ -1750,13 +1750,18 @@ gfx::Size BrowserView::GetMinimumSize() { /////////////////////////////////////////////////////////////////////////////// // BrowserView, protected -void BrowserView::GetAccessibleToolbars( - std::vector<AccessibleToolbarView*>* toolbars) { - // This should be in the order of pane traversal of the toolbars using F6. +void BrowserView::GetAccessiblePanes( + std::vector<AccessiblePaneView*>* panes) { + // This should be in the order of pane traversal of the panes using F6. // If one of these is invisible or has no focusable children, it will be // automatically skipped. - toolbars->push_back(toolbar_); - toolbars->push_back(bookmark_bar_view_.get()); + panes->push_back(toolbar_); + if (bookmark_bar_view_.get()) + panes->push_back(bookmark_bar_view_.get()); + if (infobar_container_) + panes->push_back(infobar_container_); + if (download_shelf_.get()) + panes->push_back(download_shelf_.get()); } /////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index 5f8d5ec..32272ab 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -37,7 +37,7 @@ // NOTE: For more information about the objects and files in this directory, // view: http://dev.chromium.org/developers/design-documents/browser-window -class AccessibleToolbarView; +class AccessiblePaneView; class AccessibleViewHelper; class BookmarkBarView; class Browser; @@ -391,11 +391,11 @@ class BrowserView : public BrowserBubbleHost, virtual void InfoBarSizeChanged(bool is_animating); protected: - // Appends to |toolbars| a pointer to each AccessibleToolbarView that + // Appends to |toolbars| a pointer to each AccessiblePaneView that // can be traversed using F6, in the order they should be traversed. // Abstracted here so that it can be extended for Chrome OS. - virtual void GetAccessibleToolbars( - std::vector<AccessibleToolbarView*>* toolbars); + virtual void GetAccessiblePanes( + std::vector<AccessiblePaneView*>* panes); // Save the current focused view to view storage void SaveFocusedView(); diff --git a/chrome/browser/views/infobars/infobar_container.h b/chrome/browser/views/infobars/infobar_container.h index 8efa6b5..89d5a91 100644 --- a/chrome/browser/views/infobars/infobar_container.h +++ b/chrome/browser/views/infobars/infobar_container.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_VIEWS_INFOBARS_INFOBAR_CONTAINER_H_ #pragma once +#include "chrome/browser/views/accessible_pane_view.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "views/view.h" @@ -16,7 +17,7 @@ class TabContents; // A views::View subclass that contains a collection of InfoBars associated with // a TabContents. -class InfoBarContainer : public views::View, +class InfoBarContainer : public AccessiblePaneView, public NotificationObserver { public: // Implement this interface when you want to receive notifications from the diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index 25d9546..f349e08 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -217,12 +217,12 @@ void ToolbarView::Update(TabContents* tab, bool should_restore_state) { browser_actions_->RefreshBrowserActionViews(); } -void ToolbarView::SetToolbarFocusAndFocusLocationBar(int view_storage_id) { - SetToolbarFocus(view_storage_id, location_bar_); +void ToolbarView::SetPaneFocusAndFocusLocationBar(int view_storage_id) { + SetPaneFocus(view_storage_id, location_bar_); } -void ToolbarView::SetToolbarFocusAndFocusAppMenu(int view_storage_id) { - SetToolbarFocus(view_storage_id, app_menu_); +void ToolbarView::SetPaneFocusAndFocusAppMenu(int view_storage_id) { + SetPaneFocus(view_storage_id, app_menu_); } bool ToolbarView::IsAppMenuFocused() { @@ -254,17 +254,21 @@ void ToolbarView::RemoveMenuListener(views::MenuListener* listener) { } //////////////////////////////////////////////////////////////////////////////// -// ToolbarView, AccessibleToolbarView overrides: +// ToolbarView, AccessiblePaneView overrides: -bool ToolbarView::SetToolbarFocus( +bool ToolbarView::SetPaneFocus( int view_storage_id, views::View* initial_focus) { - if (!AccessibleToolbarView::SetToolbarFocus(view_storage_id, initial_focus)) + if (!AccessiblePaneView::SetPaneFocus(view_storage_id, initial_focus)) return false; location_bar_->SetShowFocusRect(true); return true; } +AccessibilityTypes::Role ToolbarView::GetAccessibleRole() { + return AccessibilityTypes::ROLE_TOOLBAR; +} + //////////////////////////////////////////////////////////////////////////////// // ToolbarView, Menu::BaseControllerDelegate overrides: @@ -549,8 +553,8 @@ views::View* ToolbarView::GetDefaultFocusableChild() { return location_bar_; } -void ToolbarView::RemoveToolbarFocus() { - AccessibleToolbarView::RemoveToolbarFocus(); +void ToolbarView::RemovePaneFocus() { + AccessiblePaneView::RemovePaneFocus(); location_bar_->SetShowFocusRect(false); } diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h index 396a392..7f50af9 100644 --- a/chrome/browser/views/toolbar_view.h +++ b/chrome/browser/views/toolbar_view.h @@ -15,7 +15,7 @@ #include "chrome/browser/back_forward_menu_model.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/prefs/pref_member.h" -#include "chrome/browser/views/accessible_toolbar_view.h" +#include "chrome/browser/views/accessible_pane_view.h" #include "chrome/browser/views/location_bar/location_bar_view.h" #include "chrome/browser/views/reload_button.h" #include "views/controls/button/menu_button.h" @@ -36,7 +36,7 @@ class WrenchMenu; #endif // The Browser Window's toolbar. -class ToolbarView : public AccessibleToolbarView, +class ToolbarView : public AccessiblePaneView, public views::ViewMenuDelegate, public menus::AcceleratorProvider, public LocationBarView::Delegate, @@ -64,12 +64,12 @@ class ToolbarView : public AccessibleToolbarView, // Set focus to the toolbar with complete keyboard access, with the // focus initially set to the location bar. Focus will be restored // to the ViewStorage with id |view_storage_id| if the user escapes. - void SetToolbarFocusAndFocusLocationBar(int view_storage_id); + void SetPaneFocusAndFocusLocationBar(int view_storage_id); // Set focus to the toolbar with complete keyboard access, with the // focus initially set to the app menu. Focus will be restored // to the ViewStorage with id |view_storage_id| if the user escapes. - void SetToolbarFocusAndFocusAppMenu(int view_storage_id); + void SetPaneFocusAndFocusAppMenu(int view_storage_id); // Returns true if the app menu is focused. bool IsAppMenuFocused(); @@ -87,8 +87,9 @@ class ToolbarView : public AccessibleToolbarView, LocationBarView* location_bar() const { return location_bar_; } views::MenuButton* app_menu() const { return app_menu_; } - // Overridden from AccessibleToolbarView - virtual bool SetToolbarFocus(int view_storage_id, View* initial_focus); + // Overridden from AccessiblePaneView + virtual bool SetPaneFocus(int view_storage_id, View* initial_focus); + virtual AccessibilityTypes::Role GetAccessibleRole(); // Overridden from Menu::BaseControllerDelegate: virtual bool GetAcceleratorInfo(int id, menus::Accelerator* accel); @@ -134,9 +135,9 @@ class ToolbarView : public AccessibleToolbarView, protected: - // Overridden from AccessibleToolbarView + // Overridden from AccessiblePaneView virtual views::View* GetDefaultFocusableChild(); - virtual void RemoveToolbarFocus(); + virtual void RemovePaneFocus(); private: // Returns true if we should show the upgrade recommended dot. diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index ce6165e..082834d 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2923,8 +2923,8 @@ 'browser/views/accelerator_table_gtk.h', 'browser/views/accessibility_event_router_views.cc', 'browser/views/accessibility_event_router_views.h', - 'browser/views/accessible_toolbar_view.cc', - 'browser/views/accessible_toolbar_view.h', + 'browser/views/accessible_pane_view.cc', + 'browser/views/accessible_pane_view.h', 'browser/views/accessible_view_helper.cc', 'browser/views/accessible_view_helper.h', 'browser/views/app_launched_animation_win.cc', @@ -3685,8 +3685,8 @@ ['include', '^browser/views/accelerator_table_gtk.h'], ['include', '^browser/views/accessibility_event_router_views.cc'], ['include', '^browser/views/accessibility_event_router_views.h'], - ['include', '^browser/views/accessible_toolbar_view.cc'], - ['include', '^browser/views/accessible_toolbar_view.h'], + ['include', '^browser/views/accessible_pane_view.cc'], + ['include', '^browser/views/accessible_pane_view.h'], ['include', '^browser/views/accessible_view_helper.cc'], ['include', '^browser/views/accessible_view_helper.h'], ['include', '^browser/views/autocomplete/autocomplete_popup_contents_view.cc'], diff --git a/views/accessibility/accessibility_types.h b/views/accessibility/accessibility_types.h index b30208f..43f6de0 100644 --- a/views/accessibility/accessibility_types.h +++ b/views/accessibility/accessibility_types.h @@ -88,7 +88,8 @@ class AccessibilityTypes { EVENT_MENUSTART, EVENT_MENUEND, EVENT_MENUPOPUPSTART, - EVENT_MENUPOPUPEND + EVENT_MENUPOPUPEND, + EVENT_NAMECHANGE }; private: diff --git a/views/accessibility/view_accessibility.cc b/views/accessibility/view_accessibility.cc index bd1d32d..c495ff1 100644 --- a/views/accessibility/view_accessibility.cc +++ b/views/accessibility/view_accessibility.cc @@ -653,6 +653,8 @@ int32 ViewAccessibility::MSAAEvent(AccessibilityTypes::Event event) { return EVENT_SYSTEM_MENUPOPUPSTART; case AccessibilityTypes::EVENT_MENUPOPUPEND: return EVENT_SYSTEM_MENUPOPUPEND; + case AccessibilityTypes::EVENT_NAMECHANGE: + return EVENT_OBJECT_NAMECHANGE; default: // Not supported or invalid event. NOTREACHED(); |