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