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

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

Issue 333010: Implement keyboard access between bookmarks and toolbar. (Closed)
Patch Set: Add more null checks Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/logging.h"
6 #include "chrome/browser/view_ids.h"
7 #include "chrome/browser/views/frame/browser_view.h"
8 #include "chrome/browser/views/accessible_toolbar_view.h"
9 #include "views/controls/button/menu_button.h"
10 #include "views/focus/view_storage.h"
11 #include "views/widget/tooltip_manager.h"
12 #include "views/widget/widget.h"
13
14 AccessibleToolbarView::AccessibleToolbarView()
15 : selected_focused_view_(NULL),
16 last_focused_view_storage_id_(-1) {
17 }
18
19 AccessibleToolbarView::~AccessibleToolbarView() {
20 }
21
22 void AccessibleToolbarView::InitiateTraversal(int view_storage_id) {
23 // We only traverse if accessibility is active.
24 if (selected_focused_view_)
25 return;
26
27 // Save the storage id to the last focused view. This would be used to request
28 // focus to the view when the traversal is ended.
29 last_focused_view_storage_id_ = view_storage_id;
30
31 // Request focus to the toolbar.
32 RequestFocus();
33 }
34
35 views::View* AccessibleToolbarView::GetNextAccessibleView(int view_index,
36 bool forward) {
37 int modifier = forward ? 1 : -1;
38 int current_view_index = view_index + modifier;
39
40 while ((current_view_index >= 0) &&
41 (current_view_index < GetChildViewCount())) {
42 // Try to find the next available view that can be interacted with. That
43 // view must be enabled, visible, and traversable.
44 views::View* current_view = GetChildViewAt(current_view_index);
45 if (current_view->IsEnabled() && current_view->IsVisible() &&
46 IsAccessibleViewTraversable(current_view)) {
47 return current_view;
48 }
49 current_view_index += modifier;
50 }
51
52 // No button is available in the specified direction.
53 return NULL;
54 }
55
56 bool AccessibleToolbarView::IsAccessibleViewTraversable(views::View* view) {
57 return true;
58 }
59
60 void AccessibleToolbarView::DidGainFocus() {
61 // Check to see if the accessible focus should be restored to previously
62 // focused button. The must be enabled and visible in the toolbar.
63 if (!selected_focused_view_ ||
64 !selected_focused_view_->IsEnabled() ||
65 !selected_focused_view_->IsVisible()) {
66 // Find first accessible child (-1 to start search at parent).
67 selected_focused_view_ = GetNextAccessibleView(-1, true);
68
69 // No buttons enabled or visible.
70 if (!selected_focused_view_)
71 return;
72 }
73
74 // Set the focus to the current accessible view.
75 SetFocusToAccessibleView();
76 }
77
78 void AccessibleToolbarView::WillLoseFocus() {
79 // Any tooltips that are active should be hidden when toolbar loses focus.
80 if (GetWidget() && GetWidget()->GetTooltipManager())
81 GetWidget()->GetTooltipManager()->HideKeyboardTooltip();
82
83 // Removes the child accessibility view's focus when toolbar loses focus. It
84 // will not remove the view from the ViewStorage because it might be
85 // traversing to another toolbar hence the last focused view should not be
86 // removed.
87 if (selected_focused_view_) {
88 selected_focused_view_->SetHotTracked(false);
89 selected_focused_view_ = NULL;
90 }
91 }
92
93 void AccessibleToolbarView::ShowContextMenu(int x, int y,
94 bool is_mouse_gesture) {
95 if (selected_focused_view_)
96 selected_focused_view_->ShowContextMenu(x, y, is_mouse_gesture);
97 }
98
99 void AccessibleToolbarView::RequestFocus() {
100 // When the toolbar needs to request focus, the default implementation of
101 // View::RequestFocus requires the View to be focusable. Since ToolbarView is
102 // not technically focused, we need to temporarily set and remove focus so
103 // that it can focus back to its focused state. |selected_focused_view_| is
104 // not necessarily set since it can be null if this view has already lost
105 // focus, such as traversing through the context menu.
106 SetFocusable(true);
107 View::RequestFocus();
108 SetFocusable(false);
109 }
110
111 bool AccessibleToolbarView::OnKeyPressed(const views::KeyEvent& e) {
112 if (!HasFocus())
113 return View::OnKeyPressed(e);
114
115 int focused_view = GetChildIndex(selected_focused_view_);
116 views::View* next_view = NULL;
117
118 switch (e.GetKeyCode()) {
119 case base::VKEY_LEFT:
120 next_view = GetNextAccessibleView(focused_view, false);
121 break;
122 case base::VKEY_RIGHT:
123 next_view = GetNextAccessibleView(focused_view, true);
124 break;
125 case base::VKEY_DOWN:
126 case base::VKEY_RETURN:
127 if (selected_focused_view_ && selected_focused_view_->GetClassName() ==
128 views::MenuButton::kViewClassName) {
129 // If a menu button is activated and its menu is displayed, then the
130 // active tooltip should be hidden.
131 if (GetWidget()->GetTooltipManager())
132 GetWidget()->GetTooltipManager()->HideKeyboardTooltip();
133
134 // Safe to cast, given to above check.
135 static_cast<views::MenuButton*>(selected_focused_view_)->Activate();
136
137 // If activate did not trigger a focus change, the menu button should
138 // remain hot tracked since the view is still focused.
139 if (selected_focused_view_)
140 selected_focused_view_->SetHotTracked(true);
141 return true;
142 }
143 default:
144 // If key is not handled explicitly, pass it on to view.
145 if (selected_focused_view_)
146 return selected_focused_view_->OnKeyPressed(e);
147 else
148 return View::OnKeyPressed(e);
149 }
150
151 // No buttons enabled, visible, or focus hasn't moved.
152 if (next_view == NULL || !selected_focused_view_)
153 return false;
154
155 // Remove hot-tracking from old focused button.
156 selected_focused_view_->SetHotTracked(false);
157
158 // All is well, update the focused child member variable.
159 selected_focused_view_ = next_view;
160
161 // Set the focus to the current accessible view.
162 SetFocusToAccessibleView();
163 return true;
164 }
165
166 bool AccessibleToolbarView::OnKeyReleased(const views::KeyEvent& e) {
167 if (!selected_focused_view_)
168 return false;
169
170 // Have keys be handled by the views themselves.
171 return selected_focused_view_->OnKeyReleased(e);
172 }
173
174 bool AccessibleToolbarView::SkipDefaultKeyEventProcessing(
175 const views::KeyEvent& e) {
176 // Accessibility focus must be present in order to handle ESC and TAB related
177 // key events.
178 if (!HasFocus())
179 return false;
180
181 // The ancestor *must* be a BrowserView.
182 views::View* view = GetAncestorWithClassName(BrowserView::kViewClassName);
183 if (!view)
184 return false;
185
186 // Given the check above, we can ensure its a BrowserView.
187 BrowserView* browser_view = static_cast<BrowserView*>(view);
188
189 // Handle ESC and TAB events.
190 switch (e.GetKeyCode()) {
191 case base::VKEY_ESCAPE: {
192 SetFocusToLastFocusedView();
193 return true;
194 }
195 case base::VKEY_TAB: {
196 if (e.IsShiftDown()) {
197 browser_view->TraverseNextAccessibleToolbar(false);
198 } else {
199 browser_view->TraverseNextAccessibleToolbar(true);
200 }
201 return true;
202 }
203 default: return false;
204 }
205 }
206
207 bool AccessibleToolbarView::GetAccessibleName(std::wstring* name) {
208 *name = accessible_name_;
209 return !accessible_name_.empty();
210 }
211
212 bool AccessibleToolbarView::GetAccessibleRole(AccessibilityTypes::Role* role) {
213 DCHECK(role);
214
215 *role = AccessibilityTypes::ROLE_TOOLBAR;
216 return true;
217 }
218
219 void AccessibleToolbarView::SetAccessibleName(const std::wstring& name) {
220 accessible_name_ = name;
221 }
222
223 void AccessibleToolbarView::ViewHierarchyChanged(bool is_add, View* parent,
224 View* child) {
225 // When the toolbar is removed, traverse to the next accessible toolbar.
226 if (child == selected_focused_view_ && !is_add) {
227 selected_focused_view_->SetHotTracked(false);
228 selected_focused_view_ = NULL;
229 SetFocusToLastFocusedView();
230 }
231 }
232
233 void AccessibleToolbarView::SetFocusToAccessibleView() {
234 // Hot-track new focused button.
235 selected_focused_view_->SetHotTracked(true);
236
237 // Show the tooltip for the view that got the focus.
238 if (GetWidget()->GetTooltipManager()) {
239 GetWidget()->GetTooltipManager()->ShowKeyboardTooltip(
240 selected_focused_view_);
241 }
242
243 #if defined(OS_WIN)
244 // Retrieve information to generate an accessible focus event.
245 gfx::NativeView wnd = GetWidget()->GetNativeView();
246 int view_id = selected_focused_view_->GetID();
247 // Notify Access Technology that there was a change in keyboard focus.
248 ::NotifyWinEvent(EVENT_OBJECT_FOCUS, wnd, OBJID_CLIENT,
249 static_cast<LONG>(view_id));
250 #else
251 NOTIMPLEMENTED();
252 #endif
253 }
254
255 void AccessibleToolbarView::SetFocusToLastFocusedView() {
256 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
257 views::View* focused_view =
258 view_storage->RetrieveView(last_focused_view_storage_id_);
259 if (focused_view) {
260 view_storage->RemoveView(last_focused_view_storage_id_);
261 focused_view->RequestFocus();
262 } else {
263 // The ancestor *must* be a BrowserView. The check below can ensure that.
264 views::View* view = GetAncestorWithClassName(BrowserView::kViewClassName);
265 if (!view)
266 return;
267 BrowserView* browser_view = static_cast<BrowserView*>(view);
268
269 // Force the focus to be set on the location bar.
270 browser_view->SetFocusToLocationBar();
271 }
272 }
OLDNEW
« no previous file with comments | « chrome/browser/views/accessible_toolbar_view.h ('k') | chrome/browser/views/bookmark_bar_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698