focus_manager.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
153d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr// Copyright (c) 2012 The Chromium Authors. All rights reserved. 253d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr// Use of this source code is governed by a BSD-style license that can be 353d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr// found in the LICENSE file. 453d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 51ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbod#include "ui/views/focus/focus_manager.h" 630e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbod 74162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#include <algorithm> 84162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#include <vector> 94162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 104162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#include "base/auto_reset.h" 114162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#include "base/logging.h" 124162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#include "build/build_config.h" 134162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#include "ui/base/accelerators/accelerator.h" 1405e2541b49e530a3771b5ec14eee5f956308506ajvr#include "ui/events/event.h" 1505e2541b49e530a3771b5ec14eee5f956308506ajvr#include "ui/events/keycodes/keyboard_codes.h" 1605e2541b49e530a3771b5ec14eee5f956308506ajvr#include "ui/views/focus/focus_manager_delegate.h" 1705e2541b49e530a3771b5ec14eee5f956308506ajvr#include "ui/views/focus/focus_search.h" 1805e2541b49e530a3771b5ec14eee5f956308506ajvr#include "ui/views/focus/view_storage.h" 1905e2541b49e530a3771b5ec14eee5f956308506ajvr#include "ui/views/focus/widget_focus_manager.h" 204162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#include "ui/views/view.h" 2153d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr#include "ui/views/widget/root_view.h" 2253d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr#include "ui/views/widget/widget.h" 2353d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr#include "ui/views/widget/widget_delegate.h" 2453d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 2553d7523c1c36caf25e72c7a4ab0f9d18d594b895jvrnamespace views { 2653d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 2753d7523c1c36caf25e72c7a4ab0f9d18d594b895jvrnamespace { 2853d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 2953d7523c1c36caf25e72c7a4ab0f9d18d594b895jvrclass FocusManagerEventHandler : public ui::EventHandler { 3053d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr public: 3153d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr FocusManagerEventHandler(FocusManager* parent) : focus_manager_(parent) {} 3253d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 3353d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr // Implementation of ui::EventHandler: 3453d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE { 3553d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr if (!focus_manager_->OnKeyEvent(*event)) 3653d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr event->SetHandled(); 3753d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr } 3853d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 3953d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr private: 4053d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr FocusManager* focus_manager_; 4153d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr}; 4253d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 4353d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr} // namespace 4453d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 4553d7523c1c36caf25e72c7a4ab0f9d18d594b895jvrbool FocusManager::shortcut_handling_suspended_ = false; 4653d7523c1c36caf25e72c7a4ab0f9d18d594b895jvrbool FocusManager::arrow_key_traversal_enabled_ = false; 4753d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 4853d7523c1c36caf25e72c7a4ab0f9d18d594b895jvrFocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate) 494162de350edeb4aa09c508e5a39ac5fa20d8d619jvr : widget_(widget), 504162de350edeb4aa09c508e5a39ac5fa20d8d619jvr delegate_(delegate), 514162de350edeb4aa09c508e5a39ac5fa20d8d619jvr focused_view_(NULL), 5253d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr accelerator_manager_(new ui::AcceleratorManager), 534162de350edeb4aa09c508e5a39ac5fa20d8d619jvr focus_change_reason_(kReasonDirectFocusChange), 5453d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr is_changing_focus_(false) { 554162de350edeb4aa09c508e5a39ac5fa20d8d619jvr DCHECK(widget_); 564162de350edeb4aa09c508e5a39ac5fa20d8d619jvr stored_focused_view_storage_id_ = 574162de350edeb4aa09c508e5a39ac5fa20d8d619jvr ViewStorage::GetInstance()->CreateStorageID(); 584162de350edeb4aa09c508e5a39ac5fa20d8d619jvr} 594162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 604162de350edeb4aa09c508e5a39ac5fa20d8d619jvrFocusManager::~FocusManager() { 6153d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr} 6253d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 6353d7523c1c36caf25e72c7a4ab0f9d18d594b895jvrbool FocusManager::OnKeyEvent(const ui::KeyEvent& event) { 644162de350edeb4aa09c508e5a39ac5fa20d8d619jvr const int key_code = event.key_code(); 6553d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr 6653d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED) 674162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return false; 684162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 694162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (shortcut_handling_suspended()) 704162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return true; 714162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 724162de350edeb4aa09c508e5a39ac5fa20d8d619jvr int modifiers = ui::EF_NONE; 7353d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr if (event.IsShiftDown()) 744162de350edeb4aa09c508e5a39ac5fa20d8d619jvr modifiers |= ui::EF_SHIFT_DOWN; 754162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (event.IsControlDown()) 764162de350edeb4aa09c508e5a39ac5fa20d8d619jvr modifiers |= ui::EF_CONTROL_DOWN; 774162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (event.IsAltDown()) 784162de350edeb4aa09c508e5a39ac5fa20d8d619jvr modifiers |= ui::EF_ALT_DOWN; 7953d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr ui::Accelerator accelerator(event.key_code(), modifiers); 804162de350edeb4aa09c508e5a39ac5fa20d8d619jvr accelerator.set_type(event.type()); 814162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 8253d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr if (event.type() == ui::ET_KEY_PRESSED) { 8353d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr // If the focused view wants to process the key event as is, let it be. 844162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event) && 854162de350edeb4aa09c508e5a39ac5fa20d8d619jvr !accelerator_manager_->HasPriorityHandler(accelerator)) 8653d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr return true; 874162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 884162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // Intercept Tab related messages for focus traversal. 894162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // Note that we don't do focus traversal if the root window is not part of 904162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // the active window hierarchy as this would mean we have no focused view 914162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // and would focus the first focusable view. 924162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#if defined(OS_WIN) && !defined(USE_AURA) 934162de350edeb4aa09c508e5a39ac5fa20d8d619jvr HWND top_window = widget_->GetNativeView(); 944162de350edeb4aa09c508e5a39ac5fa20d8d619jvr HWND active_window = ::GetActiveWindow(); 954162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if ((active_window == top_window || ::IsChild(active_window, top_window)) && 964162de350edeb4aa09c508e5a39ac5fa20d8d619jvr IsTabTraversalKeyEvent(event)) { 974162de350edeb4aa09c508e5a39ac5fa20d8d619jvr AdvanceFocus(event.IsShiftDown()); 9853d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr return false; 994162de350edeb4aa09c508e5a39ac5fa20d8d619jvr } 1004162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#else 10132c10eecffb4923e0721c395e4b80fb732543f18Behdad Esfahbod if (IsTabTraversalKeyEvent(event)) { 1024162de350edeb4aa09c508e5a39ac5fa20d8d619jvr AdvanceFocus(event.IsShiftDown()); 1034162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return false; 1044162de350edeb4aa09c508e5a39ac5fa20d8d619jvr } 1054162de350edeb4aa09c508e5a39ac5fa20d8d619jvr#endif 1064162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1074162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (arrow_key_traversal_enabled_ && ProcessArrowKeyTraversal(event)) 1084162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return false; 1094162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1104162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // Intercept arrow key messages to switch between grouped views. 1114162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (focused_view_ && focused_view_->GetGroup() != -1 && 1124162de350edeb4aa09c508e5a39ac5fa20d8d619jvr (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN || 1134162de350edeb4aa09c508e5a39ac5fa20d8d619jvr key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) { 1144162de350edeb4aa09c508e5a39ac5fa20d8d619jvr bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN); 1154162de350edeb4aa09c508e5a39ac5fa20d8d619jvr View::Views views; 1164162de350edeb4aa09c508e5a39ac5fa20d8d619jvr focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), 1174162de350edeb4aa09c508e5a39ac5fa20d8d619jvr &views); 1184162de350edeb4aa09c508e5a39ac5fa20d8d619jvr View::Views::const_iterator i( 1194162de350edeb4aa09c508e5a39ac5fa20d8d619jvr std::find(views.begin(), views.end(), focused_view_)); 12053d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr DCHECK(i != views.end()); 1214162de350edeb4aa09c508e5a39ac5fa20d8d619jvr int index = static_cast<int>(i - views.begin()); 1224162de350edeb4aa09c508e5a39ac5fa20d8d619jvr index += next ? 1 : -1; 1234162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (index < 0) { 1244162de350edeb4aa09c508e5a39ac5fa20d8d619jvr index = static_cast<int>(views.size()) - 1; 125ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod } else if (index >= static_cast<int>(views.size())) { 12605e2541b49e530a3771b5ec14eee5f956308506ajvr index = 0; 1274162de350edeb4aa09c508e5a39ac5fa20d8d619jvr } 1284162de350edeb4aa09c508e5a39ac5fa20d8d619jvr SetFocusedViewWithReason(views[index], kReasonFocusTraversal); 1294162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return false; 1304162de350edeb4aa09c508e5a39ac5fa20d8d619jvr } 1314162de350edeb4aa09c508e5a39ac5fa20d8d619jvr } 1324162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1334162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // Process keyboard accelerators. 13453d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr // If the key combination matches an accelerator, the accelerator is 1354162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // triggered, otherwise the key event is processed as usual. 1364162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (ProcessAccelerator(accelerator)) { 1374162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // If a shortcut was activated for this keydown message, do not propagate 1384162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // the event further. 1394162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return false; 1404162de350edeb4aa09c508e5a39ac5fa20d8d619jvr } 1414162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return true; 1424162de350edeb4aa09c508e5a39ac5fa20d8d619jvr} 1434162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1444162de350edeb4aa09c508e5a39ac5fa20d8d619jvrvoid FocusManager::ValidateFocusedView() { 1454162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (focused_view_ && !ContainsView(focused_view_)) 1464162de350edeb4aa09c508e5a39ac5fa20d8d619jvr ClearFocus(); 1474162de350edeb4aa09c508e5a39ac5fa20d8d619jvr} 1484162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1494162de350edeb4aa09c508e5a39ac5fa20d8d619jvr// Tests whether a view is valid, whether it still belongs to the window 1504162de350edeb4aa09c508e5a39ac5fa20d8d619jvr// hierarchy of the FocusManager. 1514162de350edeb4aa09c508e5a39ac5fa20d8d619jvrbool FocusManager::ContainsView(View* view) { 1524162de350edeb4aa09c508e5a39ac5fa20d8d619jvr Widget* widget = view->GetWidget(); 1534162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return widget ? widget->GetFocusManager() == this : false; 1544162de350edeb4aa09c508e5a39ac5fa20d8d619jvr} 1554162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1564162de350edeb4aa09c508e5a39ac5fa20d8d619jvrvoid FocusManager::AdvanceFocus(bool reverse) { 1574162de350edeb4aa09c508e5a39ac5fa20d8d619jvr View* v = GetNextFocusableView(focused_view_, NULL, reverse, false); 1584162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // Note: Do not skip this next block when v == focused_view_. If the user 1594162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // tabs past the last focusable element in a webpage, we'll get here, and if 1604162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // the TabContentsContainerView is the only focusable view (possible in 1614162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // fullscreen mode), we need to run this block in order to cycle around to the 1624162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // first element on the page. 1634162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (v) { 1644162de350edeb4aa09c508e5a39ac5fa20d8d619jvr views::View* focused_view = focused_view_; 1654162de350edeb4aa09c508e5a39ac5fa20d8d619jvr v->AboutToRequestFocusFromTabTraversal(reverse); 1664162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // AboutToRequestFocusFromTabTraversal() may have changed focus. If it did, 1674162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // don't change focus again. 1684162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (focused_view == focused_view_) 1694162de350edeb4aa09c508e5a39ac5fa20d8d619jvr SetFocusedViewWithReason(v, kReasonFocusTraversal); 1704162de350edeb4aa09c508e5a39ac5fa20d8d619jvr } 1714162de350edeb4aa09c508e5a39ac5fa20d8d619jvr} 1724162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1734162de350edeb4aa09c508e5a39ac5fa20d8d619jvrvoid FocusManager::ClearNativeFocus() { 1744162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // Keep the top root window focused so we get keyboard events. 1754162de350edeb4aa09c508e5a39ac5fa20d8d619jvr widget_->ClearNativeFocus(); 1764162de350edeb4aa09c508e5a39ac5fa20d8d619jvr} 1774162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1784162de350edeb4aa09c508e5a39ac5fa20d8d619jvrbool FocusManager::RotatePaneFocus(Direction direction, 1794162de350edeb4aa09c508e5a39ac5fa20d8d619jvr FocusCycleWrappingBehavior wrap) { 180ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod // Get the list of all accessible panes. 18105e2541b49e530a3771b5ec14eee5f956308506ajvr std::vector<View*> panes; 1824162de350edeb4aa09c508e5a39ac5fa20d8d619jvr widget_->widget_delegate()->GetAccessiblePanes(&panes); 1834162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1844162de350edeb4aa09c508e5a39ac5fa20d8d619jvr // Count the number of panes and set the default index if no pane 18553d7523c1c36caf25e72c7a4ab0f9d18d594b895jvr // is initially focused. 1864162de350edeb4aa09c508e5a39ac5fa20d8d619jvr int count = static_cast<int>(panes.size()); 1874162de350edeb4aa09c508e5a39ac5fa20d8d619jvr if (count == 0) 1884162de350edeb4aa09c508e5a39ac5fa20d8d619jvr return false; 1894162de350edeb4aa09c508e5a39ac5fa20d8d619jvr 1903a98ae5baf9ebff980f02eacb4ce8509503824a2jvr // Initialize |index| to an appropriate starting index if nothing is 1913a98ae5baf9ebff980f02eacb4ce8509503824a2jvr // focused initially. 192 int index = direction == kBackward ? 0 : count - 1; 193 194 // Check to see if a pane already has focus and update the index accordingly. 195 const views::View* focused_view = GetFocusedView(); 196 if (focused_view) { 197 for (int i = 0; i < count; i++) { 198 if (panes[i] && panes[i]->Contains(focused_view)) { 199 index = i; 200 break; 201 } 202 } 203 } 204 205 // Rotate focus. 206 int start_index = index; 207 for (;;) { 208 if (direction == kBackward) 209 index--; 210 else 211 index++; 212 213 if (wrap == kNoWrap && (index >= count || index < 0)) 214 return false; 215 index = (index + count) % count; 216 217 // Ensure that we don't loop more than once. 218 if (index == start_index) 219 break; 220 221 views::View* pane = panes[index]; 222 DCHECK(pane); 223 224 if (!pane->visible()) 225 continue; 226 227 pane->RequestFocus(); 228 focused_view = GetFocusedView(); 229 if (pane == focused_view || pane->Contains(focused_view)) 230 return true; 231 } 232 233 return false; 234} 235 236View* FocusManager::GetNextFocusableView(View* original_starting_view, 237 Widget* starting_widget, 238 bool reverse, 239 bool dont_loop) { 240 FocusTraversable* focus_traversable = NULL; 241 242 // Let's revalidate the focused view. 243 ValidateFocusedView(); 244 245 View* starting_view = NULL; 246 if (original_starting_view) { 247 // Search up the containment hierarchy to see if a view is acting as 248 // a pane, and wants to implement its own focus traversable to keep 249 // the focus trapped within that pane. 250 View* pane_search = original_starting_view; 251 while (pane_search) { 252 focus_traversable = pane_search->GetPaneFocusTraversable(); 253 if (focus_traversable) { 254 starting_view = original_starting_view; 255 break; 256 } 257 pane_search = pane_search->parent(); 258 } 259 260 if (!focus_traversable) { 261 if (!reverse) { 262 // If the starting view has a focus traversable, use it. 263 // This is the case with NativeWidgetWins for example. 264 focus_traversable = original_starting_view->GetFocusTraversable(); 265 266 // Otherwise default to the root view. 267 if (!focus_traversable) { 268 focus_traversable = 269 original_starting_view->GetWidget()->GetFocusTraversable(); 270 starting_view = original_starting_view; 271 } 272 } else { 273 // When you are going back, starting view's FocusTraversable 274 // should not be used. 275 focus_traversable = 276 original_starting_view->GetWidget()->GetFocusTraversable(); 277 starting_view = original_starting_view; 278 } 279 } 280 } else { 281 Widget* widget = starting_widget ? starting_widget : widget_; 282 focus_traversable = widget->GetFocusTraversable(); 283 } 284 285 // Traverse the FocusTraversable tree down to find the focusable view. 286 View* v = FindFocusableView(focus_traversable, starting_view, reverse); 287 if (v) { 288 return v; 289 } else { 290 // Let's go up in the FocusTraversable tree. 291 FocusTraversable* parent_focus_traversable = 292 focus_traversable->GetFocusTraversableParent(); 293 starting_view = focus_traversable->GetFocusTraversableParentView(); 294 while (parent_focus_traversable) { 295 FocusTraversable* new_focus_traversable = NULL; 296 View* new_starting_view = NULL; 297 // When we are going backward, the parent view might gain the next focus. 298 bool check_starting_view = reverse; 299 v = parent_focus_traversable->GetFocusSearch()->FindNextFocusableView( 300 starting_view, reverse, FocusSearch::UP, 301 check_starting_view, &new_focus_traversable, &new_starting_view); 302 303 if (new_focus_traversable) { 304 DCHECK(!v); 305 306 // There is a FocusTraversable, traverse it down. 307 v = FindFocusableView(new_focus_traversable, NULL, reverse); 308 } 309 310 if (v) 311 return v; 312 313 starting_view = focus_traversable->GetFocusTraversableParentView(); 314 parent_focus_traversable = 315 parent_focus_traversable->GetFocusTraversableParent(); 316 } 317 318 // If we get here, we have reached the end of the focus hierarchy, let's 319 // loop. Make sure there was at least a view to start with, to prevent 320 // infinitely looping in empty windows. 321 if (!dont_loop && original_starting_view) { 322 // Easy, just clear the selection and press tab again. 323 // By calling with NULL as the starting view, we'll start from either 324 // the starting views widget or |widget_|. 325 Widget* widget = original_starting_view->GetWidget(); 326 if (widget->widget_delegate()->ShouldAdvanceFocusToTopLevelWidget()) 327 widget = widget_; 328 return GetNextFocusableView(NULL, widget, reverse, true); 329 } 330 } 331 return NULL; 332} 333 334void FocusManager::SetFocusedViewWithReason( 335 View* view, FocusChangeReason reason) { 336 if (focused_view_ == view) 337 return; 338 339 base::AutoReset<bool> auto_changing_focus(&is_changing_focus_, true); 340 // Update the reason for the focus change (since this is checked by 341 // some listeners), then notify all listeners. 342 focus_change_reason_ = reason; 343 FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, 344 OnWillChangeFocus(focused_view_, view)); 345 346 View* old_focused_view = focused_view_; 347 focused_view_ = view; 348 if (old_focused_view) 349 old_focused_view->Blur(); 350 // Also make |focused_view_| the stored focus view. This way the stored focus 351 // view is remembered if focus changes are requested prior to a show or while 352 // hidden. 353 SetStoredFocusView(focused_view_); 354 if (focused_view_) 355 focused_view_->Focus(); 356 357 FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, 358 OnDidChangeFocus(old_focused_view, focused_view_)); 359} 360 361void FocusManager::ClearFocus() { 362 // SetFocusedView(NULL) is going to clear out the stored view to. We need to 363 // persist it in this case. 364 views::View* focused_view = GetStoredFocusView(); 365 SetFocusedView(NULL); 366 ClearNativeFocus(); 367 SetStoredFocusView(focused_view); 368} 369 370void FocusManager::StoreFocusedView(bool clear_native_focus) { 371 View* focused_view = focused_view_; 372 // Don't do anything if no focused view. Storing the view (which is NULL), in 373 // this case, would clobber the view that was previously saved. 374 if (!focused_view_) 375 return; 376 377 View* v = focused_view_; 378 379 if (clear_native_focus) { 380 // Temporarily disable notification. ClearFocus() will set the focus to the 381 // main browser window. This extra focus bounce which happens during 382 // deactivation can confuse registered WidgetFocusListeners, as the focus 383 // is not changing due to a user-initiated event. 384 AutoNativeNotificationDisabler local_notification_disabler; 385 // ClearFocus() also stores the focused view. 386 ClearFocus(); 387 } else { 388 SetFocusedView(NULL); 389 SetStoredFocusView(focused_view); 390 } 391 392 if (v) 393 v->SchedulePaint(); // Remove focus border. 394} 395 396bool FocusManager::RestoreFocusedView() { 397 View* view = GetStoredFocusView(); 398 if (view) { 399 if (ContainsView(view)) { 400 if (!view->IsFocusable() && view->IsAccessibilityFocusable()) { 401 // RequestFocus would fail, but we want to restore focus to controls 402 // that had focus in accessibility mode. 403 SetFocusedViewWithReason(view, kReasonFocusRestore); 404 } else { 405 // This usually just sets the focus if this view is focusable, but 406 // let the view override RequestFocus if necessary. 407 view->RequestFocus(); 408 409 // If it succeeded, the reason would be incorrect; set it to 410 // focus restore. 411 if (focused_view_ == view) 412 focus_change_reason_ = kReasonFocusRestore; 413 } 414 } 415 return true; 416 } 417 return false; 418} 419 420void FocusManager::SetStoredFocusView(View* focus_view) { 421 ViewStorage* view_storage = ViewStorage::GetInstance(); 422 if (!view_storage) { 423 // This should never happen but bug 981648 seems to indicate it could. 424 NOTREACHED(); 425 return; 426 } 427 428 // TODO(jcivelli): when a TabContents containing a popup is closed, the focus 429 // is stored twice causing an assert. We should find a better alternative than 430 // removing the view from the storage explicitly. 431 view_storage->RemoveView(stored_focused_view_storage_id_); 432 433 if (!focus_view) 434 return; 435 436 view_storage->StoreView(stored_focused_view_storage_id_, focus_view); 437} 438 439View* FocusManager::GetStoredFocusView() { 440 ViewStorage* view_storage = ViewStorage::GetInstance(); 441 if (!view_storage) { 442 // This should never happen but bug 981648 seems to indicate it could. 443 NOTREACHED(); 444 return NULL; 445 } 446 447 return view_storage->RetrieveView(stored_focused_view_storage_id_); 448} 449 450void FocusManager::ClearStoredFocusedView() { 451 SetStoredFocusView(NULL); 452} 453 454// Find the next (previous if reverse is true) focusable view for the specified 455// FocusTraversable, starting at the specified view, traversing down the 456// FocusTraversable hierarchy. 457View* FocusManager::FindFocusableView(FocusTraversable* focus_traversable, 458 View* starting_view, 459 bool reverse) { 460 FocusTraversable* new_focus_traversable = NULL; 461 View* new_starting_view = NULL; 462 View* v = focus_traversable->GetFocusSearch()->FindNextFocusableView( 463 starting_view, 464 reverse, 465 FocusSearch::DOWN, 466 false, 467 &new_focus_traversable, 468 &new_starting_view); 469 470 // Let's go down the FocusTraversable tree as much as we can. 471 while (new_focus_traversable) { 472 DCHECK(!v); 473 focus_traversable = new_focus_traversable; 474 new_focus_traversable = NULL; 475 starting_view = NULL; 476 v = focus_traversable->GetFocusSearch()->FindNextFocusableView( 477 starting_view, 478 reverse, 479 FocusSearch::DOWN, 480 false, 481 &new_focus_traversable, 482 &new_starting_view); 483 } 484 return v; 485} 486 487void FocusManager::RegisterAccelerator( 488 const ui::Accelerator& accelerator, 489 ui::AcceleratorManager::HandlerPriority priority, 490 ui::AcceleratorTarget* target) { 491 accelerator_manager_->Register(accelerator, priority, target); 492} 493 494void FocusManager::UnregisterAccelerator(const ui::Accelerator& accelerator, 495 ui::AcceleratorTarget* target) { 496 accelerator_manager_->Unregister(accelerator, target); 497} 498 499void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) { 500 accelerator_manager_->UnregisterAll(target); 501} 502 503bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { 504 if (accelerator_manager_->Process(accelerator)) 505 return true; 506 if (delegate_.get()) 507 return delegate_->ProcessAccelerator(accelerator); 508 return false; 509} 510 511ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( 512 const ui::Accelerator& accelerator) const { 513 ui::AcceleratorTarget* target = 514 accelerator_manager_->GetCurrentTarget(accelerator); 515 if (!target && delegate_.get()) 516 target = delegate_->GetCurrentTargetForAccelerator(accelerator); 517 return target; 518} 519 520bool FocusManager::HasPriorityHandler( 521 const ui::Accelerator& accelerator) const { 522 return accelerator_manager_->HasPriorityHandler(accelerator); 523} 524 525// static 526bool FocusManager::IsTabTraversalKeyEvent(const ui::KeyEvent& key_event) { 527 return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown(); 528} 529 530ui::EventHandler* FocusManager::GetEventHandler() { 531 if (!event_handler_) 532 event_handler_.reset(new FocusManagerEventHandler(this)); 533 return event_handler_.get(); 534} 535 536void FocusManager::ViewRemoved(View* removed) { 537 // If the view being removed contains (or is) the focused view, 538 // clear the focus. However, it's not safe to call ClearFocus() 539 // (and in turn ClearNativeFocus()) here because ViewRemoved() can 540 // be called while the top level widget is being destroyed. 541 if (focused_view_ && removed->Contains(focused_view_)) 542 SetFocusedView(NULL); 543} 544 545void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { 546 focus_change_listeners_.AddObserver(listener); 547} 548 549void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { 550 focus_change_listeners_.RemoveObserver(listener); 551} 552 553bool FocusManager::ProcessArrowKeyTraversal(const ui::KeyEvent& event) { 554 if (event.IsShiftDown() || event.IsControlDown() || event.IsAltDown()) 555 return false; 556 557 const int key_code = event.key_code(); 558 if (key_code == ui::VKEY_LEFT || key_code == ui::VKEY_UP) { 559 AdvanceFocus(true); 560 return true; 561 } 562 if (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN) { 563 AdvanceFocus(false); 564 return true; 565 } 566 567 return false; 568} 569 570} // namespace views 571