summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/views/accessible_toolbar_view.cc272
-rw-r--r--chrome/browser/views/accessible_toolbar_view.h72
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc30
-rw-r--r--chrome/browser/views/bookmark_bar_view.h11
-rw-r--r--chrome/browser/views/detachable_toolbar_view.h4
-rw-r--r--chrome/browser/views/frame/browser_view.cc34
-rw-r--r--chrome/browser/views/frame/browser_view.h10
-rw-r--r--chrome/browser/views/toolbar_view.cc249
-rw-r--r--chrome/browser/views/toolbar_view.h39
-rwxr-xr-xchrome/chrome_browser.gypi4
10 files changed, 410 insertions, 315 deletions
diff --git a/chrome/browser/views/accessible_toolbar_view.cc b/chrome/browser/views/accessible_toolbar_view.cc
new file mode 100644
index 0000000..3556fe7
--- /dev/null
+++ b/chrome/browser/views/accessible_toolbar_view.cc
@@ -0,0 +1,272 @@
+// Copyright (c) 2009 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.
+
+#include "base/logging.h"
+#include "chrome/browser/view_ids.h"
+#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/browser/views/accessible_toolbar_view.h"
+#include "views/controls/button/menu_button.h"
+#include "views/focus/view_storage.h"
+#include "views/widget/tooltip_manager.h"
+#include "views/widget/widget.h"
+
+AccessibleToolbarView::AccessibleToolbarView()
+ : selected_focused_view_(NULL),
+ last_focused_view_storage_id_(-1) {
+}
+
+AccessibleToolbarView::~AccessibleToolbarView() {
+}
+
+void AccessibleToolbarView::InitiateTraversal(int view_storage_id) {
+ // We only traverse if accessibility is active.
+ if (selected_focused_view_)
+ return;
+
+ // Save the storage id to the last focused view. This would be used to request
+ // focus to the view when the traversal is ended.
+ last_focused_view_storage_id_ = view_storage_id;
+
+ // Request focus to the toolbar.
+ RequestFocus();
+}
+
+views::View* AccessibleToolbarView::GetNextAccessibleView(int view_index,
+ bool forward) {
+ int modifier = forward ? 1 : -1;
+ int current_view_index = view_index + modifier;
+
+ while ((current_view_index >= 0) &&
+ (current_view_index < GetChildViewCount())) {
+ // Try to find the next available view that can be interacted with. That
+ // view must be enabled, visible, and traversable.
+ views::View* current_view = GetChildViewAt(current_view_index);
+ if (current_view->IsEnabled() && current_view->IsVisible() &&
+ IsAccessibleViewTraversable(current_view)) {
+ return current_view;
+ }
+ current_view_index += modifier;
+ }
+
+ // No button is available in the specified direction.
+ return NULL;
+}
+
+bool AccessibleToolbarView::IsAccessibleViewTraversable(views::View* view) {
+ return true;
+}
+
+void AccessibleToolbarView::DidGainFocus() {
+ // Check to see if the accessible focus should be restored to previously
+ // focused button. The must be enabled and visible in the toolbar.
+ if (!selected_focused_view_ ||
+ !selected_focused_view_->IsEnabled() ||
+ !selected_focused_view_->IsVisible()) {
+ // Find first accessible child (-1 to start search at parent).
+ selected_focused_view_ = GetNextAccessibleView(-1, true);
+
+ // No buttons enabled or visible.
+ if (!selected_focused_view_)
+ return;
+ }
+
+ // Set the focus to the current accessible view.
+ SetFocusToAccessibleView();
+}
+
+void AccessibleToolbarView::WillLoseFocus() {
+ // Any tooltips that are active should be hidden when toolbar loses focus.
+ if (GetWidget() && GetWidget()->GetTooltipManager())
+ GetWidget()->GetTooltipManager()->HideKeyboardTooltip();
+
+ // Removes the child accessibility view's focus when toolbar loses focus. It
+ // will not remove the view from the ViewStorage because it might be
+ // traversing to another toolbar hence the last focused view should not be
+ // removed.
+ if (selected_focused_view_) {
+ selected_focused_view_->SetHotTracked(false);
+ selected_focused_view_ = NULL;
+ }
+}
+
+void AccessibleToolbarView::ShowContextMenu(int x, int y,
+ bool is_mouse_gesture) {
+ if (selected_focused_view_)
+ selected_focused_view_->ShowContextMenu(x, y, is_mouse_gesture);
+}
+
+void AccessibleToolbarView::RequestFocus() {
+ // When the toolbar needs to request focus, the default implementation of
+ // View::RequestFocus requires the View to be focusable. Since ToolbarView is
+ // not technically focused, we need to temporarily set and remove focus so
+ // that it can focus back to its focused state. |selected_focused_view_| is
+ // not necessarily set since it can be null if this view has already lost
+ // focus, such as traversing through the context menu.
+ SetFocusable(true);
+ View::RequestFocus();
+ SetFocusable(false);
+}
+
+bool AccessibleToolbarView::OnKeyPressed(const views::KeyEvent& e) {
+ if (!HasFocus())
+ return View::OnKeyPressed(e);
+
+ int focused_view = GetChildIndex(selected_focused_view_);
+ views::View* next_view = NULL;
+
+ switch (e.GetKeyCode()) {
+ case base::VKEY_LEFT:
+ next_view = GetNextAccessibleView(focused_view, false);
+ break;
+ case base::VKEY_RIGHT:
+ next_view = GetNextAccessibleView(focused_view, true);
+ break;
+ case base::VKEY_DOWN:
+ case base::VKEY_RETURN:
+ if (selected_focused_view_ && selected_focused_view_->GetClassName() ==
+ views::MenuButton::kViewClassName) {
+ // If a menu button is activated and its menu is displayed, then the
+ // active tooltip should be hidden.
+ if (GetWidget()->GetTooltipManager())
+ GetWidget()->GetTooltipManager()->HideKeyboardTooltip();
+
+ // Safe to cast, given to above check.
+ static_cast<views::MenuButton*>(selected_focused_view_)->Activate();
+
+ // If activate did not trigger a focus change, the menu button should
+ // remain hot tracked since the view is still focused.
+ if (selected_focused_view_)
+ selected_focused_view_->SetHotTracked(true);
+ return true;
+ }
+ default:
+ // If key is not handled explicitly, pass it on to view.
+ if (selected_focused_view_)
+ return selected_focused_view_->OnKeyPressed(e);
+ else
+ return View::OnKeyPressed(e);
+ }
+
+ // No buttons enabled, visible, or focus hasn't moved.
+ if (!next_view || !selected_focused_view_)
+ return false;
+
+ // Remove hot-tracking from old focused button.
+ selected_focused_view_->SetHotTracked(false);
+
+ // All is well, update the focused child member variable.
+ selected_focused_view_ = next_view;
+
+ // Set the focus to the current accessible view.
+ SetFocusToAccessibleView();
+ return true;
+}
+
+bool AccessibleToolbarView::OnKeyReleased(const views::KeyEvent& e) {
+ if (!selected_focused_view_)
+ return false;
+
+ // Have keys be handled by the views themselves.
+ return selected_focused_view_->OnKeyReleased(e);
+}
+
+bool AccessibleToolbarView::SkipDefaultKeyEventProcessing(
+ const views::KeyEvent& e) {
+ // Accessibility focus must be present in order to handle ESC and TAB related
+ // key events.
+ if (!HasFocus())
+ return false;
+
+ // The ancestor *must* be a BrowserView.
+ views::View* view = GetAncestorWithClassName(BrowserView::kViewClassName);
+ if (!view)
+ return false;
+
+ // Given the check above, we can ensure its a BrowserView.
+ BrowserView* browser_view = static_cast<BrowserView*>(view);
+
+ // Handle ESC and TAB events.
+ switch (e.GetKeyCode()) {
+ case base::VKEY_ESCAPE: {
+ SetFocusToLastFocusedView();
+ return true;
+ }
+ case base::VKEY_TAB: {
+ if (e.IsShiftDown()) {
+ browser_view->TraverseNextAccessibleToolbar(false);
+ } else {
+ browser_view->TraverseNextAccessibleToolbar(true);
+ }
+ return true;
+ }
+ default: return false;
+ }
+}
+
+bool AccessibleToolbarView::GetAccessibleName(std::wstring* name) {
+ *name = accessible_name_;
+ return !accessible_name_.empty();
+}
+
+bool AccessibleToolbarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
+ DCHECK(role);
+
+ *role = AccessibilityTypes::ROLE_TOOLBAR;
+ return true;
+}
+
+void AccessibleToolbarView::SetAccessibleName(const std::wstring& name) {
+ accessible_name_ = name;
+}
+
+void AccessibleToolbarView::ViewHierarchyChanged(bool is_add, View* parent,
+ View* child) {
+ // When the toolbar is removed, traverse to the next accessible toolbar.
+ if (child == selected_focused_view_ && !is_add) {
+ selected_focused_view_->SetHotTracked(false);
+ selected_focused_view_ = NULL;
+ SetFocusToLastFocusedView();
+ }
+}
+
+void AccessibleToolbarView::SetFocusToAccessibleView() {
+ // Hot-track new focused button.
+ selected_focused_view_->SetHotTracked(true);
+
+ // Show the tooltip for the view that got the focus.
+ if (GetWidget()->GetTooltipManager()) {
+ GetWidget()->GetTooltipManager()->ShowKeyboardTooltip(
+ selected_focused_view_);
+ }
+
+#if defined(OS_WIN)
+ // Retrieve information to generate an accessible focus event.
+ gfx::NativeView wnd = GetWidget()->GetNativeView();
+ int view_id = selected_focused_view_->GetID();
+ // Notify Access Technology that there was a change in keyboard focus.
+ ::NotifyWinEvent(EVENT_OBJECT_FOCUS, wnd, OBJID_CLIENT,
+ static_cast<LONG>(view_id));
+#else
+ NOTIMPLEMENTED();
+#endif
+}
+
+void AccessibleToolbarView::SetFocusToLastFocusedView() {
+ views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
+ views::View* focused_view =
+ view_storage->RetrieveView(last_focused_view_storage_id_);
+ if (focused_view) {
+ view_storage->RemoveView(last_focused_view_storage_id_);
+ focused_view->RequestFocus();
+ } else {
+ // The ancestor *must* be a BrowserView. The check below can ensure that.
+ views::View* view = GetAncestorWithClassName(BrowserView::kViewClassName);
+ if (!view)
+ return;
+ BrowserView* browser_view = static_cast<BrowserView*>(view);
+
+ // Force the focus to be set on the location bar.
+ browser_view->SetFocusToLocationBar();
+ }
+}
diff --git a/chrome/browser/views/accessible_toolbar_view.h b/chrome/browser/views/accessible_toolbar_view.h
new file mode 100644
index 0000000..f892a74
--- /dev/null
+++ b/chrome/browser/views/accessible_toolbar_view.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2009 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.
+
+#ifndef CHROME_BROWSER_VIEWS_ACCESSIBLE_TOOLBAR_VIEW_H_
+#define CHROME_BROWSER_VIEWS_ACCESSIBLE_TOOLBAR_VIEW_H_
+
+#include "views/view.h"
+
+// This class provides keyboard access to any view that extends it by intiating
+// ALT+SHIFT+T. And once you press TAB or SHIFT-TAB, it will traverse all the
+// toolbars within Chrome. Child views are traversed in the order they were
+// added.
+
+class AccessibleToolbarView : public views::View {
+ public:
+ AccessibleToolbarView();
+ virtual ~AccessibleToolbarView();
+
+ // Initiate the traversal on the toolbar. The last focused view is stored in
+ // the ViewStorage with the corresponding |view_storage_id|.
+ void InitiateTraversal(int view_storage_id);
+
+ // Overridden from views::View:
+ virtual void DidGainFocus();
+ virtual void WillLoseFocus();
+ virtual bool OnKeyPressed(const views::KeyEvent& e);
+ virtual bool OnKeyReleased(const views::KeyEvent& e);
+ virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e);
+ virtual void ShowContextMenu(int x, int y, bool is_mouse_gesture);
+ virtual void RequestFocus();
+ virtual bool GetAccessibleName(std::wstring* name);
+ virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
+ virtual void SetAccessibleName(const std::wstring& name);
+ virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child);
+ virtual View* GetAccFocusedChildView() { return selected_focused_view_; }
+
+ protected:
+ // Returns the next accessible view on the toolbar, starting from the given
+ // |view_index|. |forward| when true means it will navigate from left to right
+ // and vice versa when false. If |view_index| is -1 the first accessible child
+ // is returned.
+ views::View* GetNextAccessibleView(int view_index, bool forward);
+
+ // Invoked from GetNextAccessibleViewIndex to determine if |view| can be
+ // traversed to. Default implementation returns true, override to return false
+ // for views you don't want reachable.
+ virtual bool IsAccessibleViewTraversable(views::View* view);
+
+ private:
+ // Sets the focus to the currently |acc_focused_view_| view.
+ void SetFocusToAccessibleView();
+
+ // Retrieve the focused view from the storage so we can request focus back
+ // to it. If |focus_view| is null, we place focus on the default view.
+ // |selected_focused_view_| doesn't need to reset here since it will be
+ // dealt within the WillLoseFocus method.
+ void SetFocusToLastFocusedView();
+
+ // Storage of strings needed for accessibility.
+ std::wstring accessible_name_;
+
+ // Selected child view currently having accessibility focus.
+ views::View* selected_focused_view_;
+
+ // Last focused view that issued this traversal.
+ int last_focused_view_storage_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessibleToolbarView);
+};
+
+#endif // CHROME_BROWSER_VIEWS_ACCESSIBLE_TOOLBAR_VIEW_H_
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc
index 47a13be0..5237069 100644
--- a/chrome/browser/views/bookmark_bar_view.cc
+++ b/chrome/browser/views/bookmark_bar_view.cc
@@ -39,7 +39,6 @@
#include "grit/theme_resources.h"
#include "views/controls/button/menu_button.h"
#include "views/controls/label.h"
-#include "views/controls/button/menu_button.h"
#include "views/controls/menu/menu_item_view.h"
#include "views/drag_utils.h"
#include "views/view_constants.h"
@@ -716,25 +715,8 @@ int BookmarkBarView::OnPerformDrop(const DropTargetEvent& event) {
index);
}
-bool BookmarkBarView::GetAccessibleName(std::wstring* name) {
- DCHECK(name);
-
- if (!accessible_name_.empty()) {
- name->assign(accessible_name_);
- return true;
- }
- return false;
-}
-
-bool BookmarkBarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
- DCHECK(role);
-
- *role = AccessibilityTypes::ROLE_TOOLBAR;
- return true;
-}
-
-void BookmarkBarView::SetAccessibleName(const std::wstring& name) {
- accessible_name_.assign(name);
+bool BookmarkBarView::IsAccessibleViewTraversable(views::View* view) {
+ return view != bookmarks_separator_view_ && view != instructions_;
}
void BookmarkBarView::OnStateChanged() {
@@ -903,15 +885,17 @@ void BookmarkBarView::Init() {
if (!kDefaultFavIcon)
kDefaultFavIcon = rb.GetBitmapNamed(IDR_DEFAULT_FAVICON);
- other_bookmarked_button_ = CreateOtherBookmarkedButton();
- AddChildView(other_bookmarked_button_);
-
+ // Child views are traversed in the order they are added. Make sure the order
+ // they are added matches the visual order.
sync_error_button_ = CreateSyncErrorButton();
AddChildView(sync_error_button_);
overflow_button_ = CreateOverflowButton();
AddChildView(overflow_button_);
+ other_bookmarked_button_ = CreateOtherBookmarkedButton();
+ AddChildView(other_bookmarked_button_);
+
bookmarks_separator_view_ = new ButtonSeparatorView();
bookmarks_separator_view_->SetAccessibleName(
l10n_util::GetString(IDS_ACCNAME_SEPARATOR));
diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h
index a9cc397..bb3d975 100644
--- a/chrome/browser/views/bookmark_bar_view.h
+++ b/chrome/browser/views/bookmark_bar_view.h
@@ -71,7 +71,7 @@ class BookmarkBarView : public DetachableToolbarView,
static const int kNewtabBarHeight;
- explicit BookmarkBarView(Profile* profile, Browser* browser);
+ BookmarkBarView(Profile* profile, Browser* browser);
virtual ~BookmarkBarView();
// Resets the profile. This removes any buttons for the current profile and
@@ -112,9 +112,9 @@ class BookmarkBarView : public DetachableToolbarView,
virtual int OnDragUpdated(const views::DropTargetEvent& event);
virtual void OnDragExited();
virtual int OnPerformDrop(const views::DropTargetEvent& event);
- virtual bool GetAccessibleName(std::wstring* name);
- virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
- virtual void SetAccessibleName(const std::wstring& name);
+
+ // AccessibleToolbarView methods:
+ virtual bool IsAccessibleViewTraversable(views::View* view);
// ProfileSyncServiceObserver method.
virtual void OnStateChanged();
@@ -488,9 +488,6 @@ class BookmarkBarView : public DetachableToolbarView,
// Background for extension toolstrips.
SkBitmap toolstrip_background_;
- // Storage of strings needed for accessibility.
- std::wstring accessible_name_;
-
DISALLOW_COPY_AND_ASSIGN(BookmarkBarView);
};
diff --git a/chrome/browser/views/detachable_toolbar_view.h b/chrome/browser/views/detachable_toolbar_view.h
index 875ad98..d27ee53 100644
--- a/chrome/browser/views/detachable_toolbar_view.h
+++ b/chrome/browser/views/detachable_toolbar_view.h
@@ -5,14 +5,14 @@
#ifndef CHROME_BROWSER_VIEWS_DETACHABLE_TOOLBAR_VIEW_H_
#define CHROME_BROWSER_VIEWS_DETACHABLE_TOOLBAR_VIEW_H_
-#include "views/view.h"
+#include "chrome/browser/views/accessible_toolbar_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 views::View {
+class DetachableToolbarView : public AccessibleToolbarView {
public:
// The color gradient start value close to the edge of the divider.
static const SkColor kEdgeDividerColor;
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 50d1dbe..0572717 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -66,6 +66,7 @@
#include "views/controls/single_split_view.h"
#include "views/fill_layout.h"
#include "views/focus/external_focus_tracker.h"
+#include "views/focus/view_storage.h"
#include "views/grid_layout.h"
#include "views/view.h"
#include "views/widget/root_view.h"
@@ -124,7 +125,7 @@ static const int kNewtabBarRoundness = 5;
// ------------
// Returned from BrowserView::GetClassName.
-static const char kBrowserViewClassName[] = "browser/views/BrowserView";
+const char BrowserView::kViewClassName[] = "browser/views/BrowserView";
///////////////////////////////////////////////////////////////////////////////
// BookmarkExtensionBackground, private:
@@ -412,7 +413,9 @@ BrowserView::BrowserView(Browser* browser)
hung_window_detector_(&hung_plugin_action_),
ticker_(0),
#endif
- extension_shelf_(NULL) {
+ extension_shelf_(NULL),
+ last_focused_view_storage_id_(
+ views::ViewStorage::GetSharedInstance()->CreateStorageID()) {
InitClass();
browser_->tabstrip_model()->AddObserver(this);
}
@@ -656,6 +659,17 @@ void BrowserView::PrepareToRunSystemMenu(HMENU menu) {
}
#endif
+void BrowserView::TraverseNextAccessibleToolbar(bool forward) {
+ // TODO(mohamed) This needs to be smart, that applies to all toolbars.
+ // Currently it just traverses between bookmarks and toolbar.
+ if (!forward && toolbar_->IsVisible() && toolbar_->IsEnabled()) {
+ toolbar_->InitiateTraversal(last_focused_view_storage_id_);
+ } else if (forward && bookmark_bar_view_->IsVisible() &&
+ bookmark_bar_view_->IsEnabled()) {
+ bookmark_bar_view_->InitiateTraversal(last_focused_view_storage_id_);
+ }
+}
+
// static
void BrowserView::RegisterBrowserViewPrefs(PrefService* prefs) {
prefs->RegisterIntegerPref(prefs::kPluginMessageResponseTimeout,
@@ -958,7 +972,17 @@ void BrowserView::UpdateToolbar(TabContents* contents,
}
void BrowserView::FocusToolbar() {
- toolbar_->InitializeTraversal();
+ // Remove existing views in the storage, traversal should be restarted.
+ views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
+ if (view_storage->RetrieveView(last_focused_view_storage_id_))
+ view_storage->RemoveView(last_focused_view_storage_id_);
+
+ // Store the last focused view into the storage, to handle existing traversal.
+ view_storage->StoreView(last_focused_view_storage_id_,
+ GetRootView()->GetFocusedView());
+
+ // Start the traversal within the main toolbar.
+ toolbar_->InitiateTraversal(last_focused_view_storage_id_);
}
void BrowserView::DestroyBrowser() {
@@ -1642,7 +1666,7 @@ gfx::Size BrowserView::GetMinimumSize() {
// BrowserView, views::View overrides:
std::string BrowserView::GetClassName() const {
- return kBrowserViewClassName;
+ return kViewClassName;
}
void BrowserView::Layout() {
@@ -2074,7 +2098,7 @@ bool BrowserView::UpdateChildViewAndLayout(views::View* new_view,
new_view->SetBounds((*old_view)->bounds());
new_view->SchedulePaint();
} else if (new_view) {
- DCHECK(new_height == 0);
+ DCHECK_EQ(0, new_height);
// The heights are the same, but the old view is null. This only happens
// when the height is zero. Zero out the bounds.
new_view->SetBounds(0, 0, 0, 0);
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index 8354226..4ec827e 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -70,6 +70,9 @@ class BrowserView : public BrowserWindow,
public views::WindowDelegate,
public views::ClientView {
public:
+ // The browser view's class name.
+ static const char kViewClassName[];
+
// Explicitly sets how windows are shown. Use a value of -1 to give the
// default behavior. This is used during testing and not generally useful
// otherwise.
@@ -180,6 +183,10 @@ class BrowserView : public BrowserWindow,
void PrepareToRunSystemMenu(HMENU menu);
#endif
+ // Traverses to the next toolbar. |forward| when true, will navigate from left
+ // to right and vice versa when false.
+ void TraverseNextAccessibleToolbar(bool forward);
+
// Returns true if the Browser object associated with this BrowserView is a
// normal-type window (i.e. a browser window, not an app or popup).
bool IsBrowserTypeNormal() const {
@@ -533,6 +540,9 @@ class BrowserView : public BrowserWindow,
scoped_ptr<BrowserExtender> browser_extender_;
+ // Last focused view that issued a tab traversal.
+ int last_focused_view_storage_id_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};
diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc
index 29a1e7a..f5e189d 100644
--- a/chrome/browser/views/toolbar_view.cc
+++ b/chrome/browser/views/toolbar_view.cc
@@ -52,9 +52,6 @@
#include "views/controls/button/button_dropdown.h"
#include "views/controls/label.h"
#include "views/drag_utils.h"
-#include "views/focus/view_storage.h"
-#include "views/widget/root_view.h"
-#include "views/widget/tooltip_manager.h"
#include "views/window/non_client_view.h"
#include "views/window/window.h"
@@ -154,9 +151,6 @@ void ZoomMenuModel::Build() {
ToolbarView::ToolbarView(Browser* browser)
: model_(browser->toolbar_model()),
- acc_focused_view_(NULL),
- last_focused_view_storage_id_(
- views::ViewStorage::GetSharedInstance()->CreateStorageID()),
back_(NULL),
forward_(NULL),
reload_(NULL),
@@ -225,48 +219,11 @@ void ToolbarView::Update(TabContents* tab, bool should_restore_state) {
browser_actions_->RefreshBrowserActionViews();
}
-int ToolbarView::GetNextAccessibleViewIndex(int view_index, bool nav_left) {
- int modifier = 1;
-
- if (nav_left)
- modifier = -1;
-
- int current_view_index = view_index + modifier;
-
- while ((current_view_index >= 0) &&
- (current_view_index < GetChildViewCount())) {
- // Skip the location bar, as it has its own keyboard navigation. Also skip
- // any views that cannot be interacted with.
- if (current_view_index == GetChildIndex(location_bar_) ||
- !GetChildViewAt(current_view_index)->IsEnabled() ||
- !GetChildViewAt(current_view_index)->IsVisible()) {
- current_view_index += modifier;
- continue;
- }
- // Update view_index with the available button index found.
- view_index = current_view_index;
- break;
- }
- // Returns the next available button index, or if no button is available in
- // the specified direction, remains where it was.
- return view_index;
-}
-
-void ToolbarView::InitializeTraversal() {
- // If MSAA focus exists, we don't need to traverse, since its already active.
- if (acc_focused_view_ != NULL)
- return;
-
- // Save the last focused view so that when the user presses ESC, it will
- // return back to the last focus.
- views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
- view_storage->StoreView(last_focused_view_storage_id_,
- GetRootView()->GetFocusedView());
+////////////////////////////////////////////////////////////////////////////////
+// ToolbarView, AccessibleToolbarView overrides:
- // HACK: Do not use RequestFocus() here, as the toolbar is not marked as
- // "focusable". Instead bypass the sanity check in RequestFocus() and just
- // force it to focus, which will do the right thing.
- GetRootView()->FocusView(this);
+bool ToolbarView::IsAccessibleViewTraversable(views::View* view) {
+ return view != location_bar_;
}
////////////////////////////////////////////////////////////////////////////////
@@ -630,204 +587,6 @@ void ToolbarView::ThemeChanged() {
LoadRightSideControlsImages();
}
-void ToolbarView::ShowContextMenu(int x, int y, bool is_mouse_gesture) {
- if (acc_focused_view_)
- acc_focused_view_->ShowContextMenu(x, y, is_mouse_gesture);
-}
-
-void ToolbarView::DidGainFocus() {
- // Check to see if MSAA focus should be restored to previously focused button,
- // and if button is an enabled, visibled child of toolbar.
- if (!acc_focused_view_ ||
- (acc_focused_view_->GetParent()->GetID() != VIEW_ID_TOOLBAR) ||
- !acc_focused_view_->IsEnabled() ||
- !acc_focused_view_->IsVisible()) {
- // Find first accessible child (-1 to start search at parent).
- int first_acc_child = GetNextAccessibleViewIndex(-1, false);
-
- // No buttons enabled or visible.
- if (first_acc_child == -1)
- return;
-
- set_acc_focused_view(GetChildViewAt(first_acc_child));
- }
-
- // Default focus is on the toolbar.
- int view_index = VIEW_ID_TOOLBAR;
-
- // Set hot-tracking for child, and update focused_view for MSAA focus event.
- if (acc_focused_view_) {
- acc_focused_view_->SetHotTracked(true);
-
- // Show the tooltip for the view that got the focus.
- if (GetWidget()->GetTooltipManager())
- GetWidget()->GetTooltipManager()->ShowKeyboardTooltip(acc_focused_view_);
-
- // Update focused_view with MSAA-adjusted child id.
- view_index = acc_focused_view_->GetID();
- }
-
-#if defined(OS_WIN)
- gfx::NativeView wnd = GetWidget()->GetNativeView();
-
- // Notify Access Technology that there was a change in keyboard focus.
- ::NotifyWinEvent(EVENT_OBJECT_FOCUS, wnd, OBJID_CLIENT,
- static_cast<LONG>(view_index));
-#else
- // TODO(port): deal with toolbar a11y focus.
- NOTIMPLEMENTED();
-#endif
-}
-
-void ToolbarView::WillLoseFocus() {
- // Any tooltips that are active should be hidden when toolbar loses focus.
- if (GetWidget() && GetWidget()->GetTooltipManager())
- GetWidget()->GetTooltipManager()->HideKeyboardTooltip();
-
- // Removes the Child MSAA view's focus and the view from the ViewStorage,
- // when toolbar loses focus.
- if (acc_focused_view_) {
- acc_focused_view_->SetHotTracked(false);
- acc_focused_view_ = NULL;
- views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
- view_storage->RemoveView(last_focused_view_storage_id_);
- }
-}
-
-void ToolbarView::RequestFocus() {
- // When the toolbar needs to request focus, the default implementation of
- // View::RequestFocus requires the View to be focusable. Since ToolbarView is
- // not technically focused, we need to temporarily set and remove focus so
- // that it can focus back to its MSAA focused state. |acc_focused_view_| is
- // not necessarily set since it can be null if this view has already lost
- // focus, such as traversing through the context menu.
- SetFocusable(true);
- View::RequestFocus();
- SetFocusable(false);
-}
-
-bool ToolbarView::OnKeyPressed(const views::KeyEvent& e) {
- // Paranoia check, button should be initialized upon toolbar gaining focus.
- if (!acc_focused_view_)
- return false;
-
- int focused_view = GetChildIndex(acc_focused_view_);
- int next_view = focused_view;
-
- switch (e.GetKeyCode()) {
- case base::VKEY_LEFT:
- next_view = GetNextAccessibleViewIndex(focused_view, true);
- break;
- case base::VKEY_RIGHT:
- next_view = GetNextAccessibleViewIndex(focused_view, false);
- break;
- case base::VKEY_DOWN:
- case base::VKEY_RETURN:
- // VKEY_SPACE is already handled by the default case.
- if (acc_focused_view_->GetID() == VIEW_ID_PAGE_MENU ||
- acc_focused_view_->GetID() == VIEW_ID_APP_MENU) {
- // If a menu button in toolbar is activated and its menu is displayed,
- // then active tooltip should be hidden.
- if (GetWidget()->GetTooltipManager())
- GetWidget()->GetTooltipManager()->HideKeyboardTooltip();
- // Safe to cast, given to above view id check.
- static_cast<views::MenuButton*>(acc_focused_view_)->Activate();
- if (!acc_focused_view_) {
- // Activate triggered a focus change, don't try to change focus.
- return true;
- }
- // Re-enable hot-tracking, as Activate() will disable it.
- acc_focused_view_->SetHotTracked(true);
- break;
- }
- default:
- // If key is not handled explicitly, pass it on to view.
- return acc_focused_view_->OnKeyPressed(e);
- }
-
- // No buttons enabled or visible.
- if (next_view == -1)
- return false;
-
- // Only send an event if focus moved.
- if (next_view != focused_view) {
- // Remove hot-tracking from old focused button.
- acc_focused_view_->SetHotTracked(false);
-
- // All is well, update the focused child member variable.
- acc_focused_view_ = GetChildViewAt(next_view);
-
- // Hot-track new focused button.
- acc_focused_view_->SetHotTracked(true);
-
- // Show the tooltip for the view that got the focus.
- if (GetWidget()->GetTooltipManager()) {
- GetWidget()->GetTooltipManager()->
- ShowKeyboardTooltip(GetChildViewAt(next_view));
- }
-#if defined(OS_WIN)
- // Retrieve information to generate an MSAA focus event.
- gfx::NativeView wnd = GetWidget()->GetNativeView();
- int view_id = acc_focused_view_->GetID();
- // Notify Access Technology that there was a change in keyboard focus.
- ::NotifyWinEvent(EVENT_OBJECT_FOCUS, wnd, OBJID_CLIENT,
- static_cast<LONG>(view_id));
-#else
- NOTIMPLEMENTED();
-#endif
- return true;
- }
- return false;
-}
-
-bool ToolbarView::OnKeyReleased(const views::KeyEvent& e) {
- // Paranoia check, button should be initialized upon toolbar gaining focus.
- if (!acc_focused_view_)
- return false;
-
- // Have keys be handled by the views themselves.
- return acc_focused_view_->OnKeyReleased(e);
-}
-
-bool ToolbarView::SkipDefaultKeyEventProcessing(const views::KeyEvent& e) {
- if (acc_focused_view_ && e.GetKeyCode() == base::VKEY_ESCAPE) {
- // Retrieve the focused view from the storage so we can request focus back
- // to it. If |focus_view| is null, we place focus on the location bar.
- // |acc_focused_view_| doesn't need to be resetted here since it will be
- // dealt within the WillLoseFocus method.
- views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
- views::View* focused_view =
- view_storage->RetrieveView(last_focused_view_storage_id_);
- if (focused_view) {
- view_storage->RemoveView(last_focused_view_storage_id_);
- focused_view->RequestFocus();
- } else {
- location_bar_->RequestFocus();
- }
- return true;
- }
- return false;
-}
-
-bool ToolbarView::GetAccessibleName(std::wstring* name) {
- if (!accessible_name_.empty()) {
- (*name).assign(accessible_name_);
- return true;
- }
- return false;
-}
-
-bool ToolbarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
- DCHECK(role);
-
- *role = AccessibilityTypes::ROLE_TOOLBAR;
- return true;
-}
-
-void ToolbarView::SetAccessibleName(const std::wstring& name) {
- accessible_name_.assign(name);
-}
-
////////////////////////////////////////////////////////////////////////////////
// ToolbarView, views::DragController implementation:
diff --git a/chrome/browser/views/toolbar_view.h b/chrome/browser/views/toolbar_view.h
index 94b54e4..cfca8b4 100644
--- a/chrome/browser/views/toolbar_view.h
+++ b/chrome/browser/views/toolbar_view.h
@@ -12,6 +12,7 @@
#include "chrome/browser/bubble_positioner.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/user_data_manager.h"
+#include "chrome/browser/views/accessible_toolbar_view.h"
#include "chrome/browser/views/go_button.h"
#include "chrome/browser/views/location_bar_view.h"
#include "chrome/common/pref_member.h"
@@ -63,8 +64,8 @@ class ZoomMenuModel : public views::SimpleMenuModel {
DISALLOW_COPY_AND_ASSIGN(ZoomMenuModel);
};
-// The Browser Window's toolbar. Used within BrowserView.
-class ToolbarView : public views::View,
+// The Browser Window's toolbar.
+class ToolbarView : public AccessibleToolbarView,
public views::ViewMenuDelegate,
public views::DragController,
public views::SimpleMenuModel::Delegate,
@@ -91,19 +92,6 @@ class ToolbarView : public views::View,
// (such as user editing) as well.
void Update(TabContents* tab, bool should_restore_state);
- // Returns the index of the next view of the toolbar, starting from the given
- // view index (skipping the location bar), in the given navigation direction
- // (nav_left true means navigation right to left, and vice versa). -1 finds
- // first accessible child, based on the above policy.
- int GetNextAccessibleViewIndex(int view_index, bool nav_left);
-
- // Initialize the MSAA focus traversal on the toolbar.
- void InitializeTraversal();
-
- void set_acc_focused_view(views::View* acc_focused_view) {
- acc_focused_view_ = acc_focused_view;
- }
-
// Accessors...
Browser* browser() const { return browser_; }
BrowserActionsContainer* browser_actions() const { return browser_actions_; }
@@ -113,6 +101,9 @@ class ToolbarView : public views::View,
views::MenuButton* page_menu() const { return page_menu_; }
views::MenuButton* app_menu() const { return app_menu_; }
+ // Overridden from AccessibleToolbarView:
+ virtual bool IsAccessibleViewTraversable(views::View* view);
+
// Overridden from Menu::BaseControllerDelegate:
virtual bool GetAcceleratorInfo(int id, views::Accelerator* accel);
@@ -152,17 +143,6 @@ class ToolbarView : public views::View,
virtual void Layout();
virtual void Paint(gfx::Canvas* canvas);
virtual void ThemeChanged();
- virtual void ShowContextMenu(int x, int y, bool is_mouse_gesture);
- virtual void DidGainFocus();
- virtual void WillLoseFocus();
- virtual void RequestFocus();
- virtual bool OnKeyPressed(const views::KeyEvent& e);
- virtual bool OnKeyReleased(const views::KeyEvent& e);
- virtual bool SkipDefaultKeyEventProcessing(const views::KeyEvent& e);
- virtual bool GetAccessibleName(std::wstring* name);
- virtual bool GetAccessibleRole(AccessibilityTypes::Role* role);
- virtual void SetAccessibleName(const std::wstring& name);
- virtual View* GetAccFocusedChildView() { return acc_focused_view_; }
private:
// Overridden from views::DragController:
@@ -211,13 +191,6 @@ class ToolbarView : public views::View,
// The model that contains the security level, text, icon to display...
ToolbarModel* model_;
- // Storage of strings needed for accessibility.
- std::wstring accessible_name_;
- // Child view currently having MSAA focus (location bar excluded from arrow
- // navigation).
- views::View* acc_focused_view_;
- int last_focused_view_storage_id_;
-
// Controls
views::ImageButton* back_;
views::ImageButton* forward_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 244d6ba..c34bc49 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1504,6 +1504,8 @@
'browser/views/about_network_dialog.h',
'browser/views/accelerator_table_gtk.cc',
'browser/views/accelerator_table_gtk.h',
+ 'browser/views/accessible_toolbar_view.cc',
+ 'browser/views/accessible_toolbar_view.h',
'browser/views/autocomplete/autocomplete_popup_contents_view.cc',
'browser/views/autocomplete/autocomplete_popup_contents_view.h',
'browser/views/autocomplete/autocomplete_popup_win.cc',
@@ -2064,6 +2066,8 @@
['include', '^browser/extensions/'],
['include', '^browser/views/accelerator_table_gtk.cc'],
['include', '^browser/views/accelerator_table_gtk.h'],
+ ['include', '^browser/views/accessible_toolbar_view.cc'],
+ ['include', '^browser/views/accessible_toolbar_view.h'],
['include', '^browser/views/autocomplete/autocomplete_popup_contents_view.cc'],
['include', '^browser/views/autocomplete/autocomplete_popup_contents_view.h'],
['include', '^browser/views/autocomplete/autocomplete_popup_gtk.cc'],