| Index: views/focus/focus_manager.cc
|
| diff --git a/views/focus/focus_manager.cc b/views/focus/focus_manager.cc
|
| deleted file mode 100644
|
| index 3ee07552a6da5129eabd4c46fe60e0fd715b6eb1..0000000000000000000000000000000000000000
|
| --- a/views/focus/focus_manager.cc
|
| +++ /dev/null
|
| @@ -1,413 +0,0 @@
|
| -// Copyright (c) 2011 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 "views/focus/focus_manager.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/auto_reset.h"
|
| -#include "base/logging.h"
|
| -#include "build/build_config.h"
|
| -#include "ui/base/accelerator_manager.h"
|
| -#include "ui/base/keycodes/keyboard_codes.h"
|
| -#include "ui/base/models/accelerator.h"
|
| -#include "views/focus/focus_search.h"
|
| -#include "views/focus/view_storage.h"
|
| -#include "views/focus/widget_focus_manager.h"
|
| -#include "views/view.h"
|
| -#include "views/widget/root_view.h"
|
| -#include "views/widget/widget.h"
|
| -
|
| -namespace views {
|
| -
|
| -FocusManager::FocusManager(Widget* widget)
|
| - : widget_(widget),
|
| - focused_view_(NULL),
|
| - accelerator_manager_(new ui::AcceleratorManager),
|
| - focus_change_reason_(kReasonDirectFocusChange),
|
| - is_changing_focus_(false) {
|
| - DCHECK(widget_);
|
| - stored_focused_view_storage_id_ =
|
| - ViewStorage::GetInstance()->CreateStorageID();
|
| -}
|
| -
|
| -FocusManager::~FocusManager() {
|
| -}
|
| -
|
| -bool FocusManager::OnKeyEvent(const KeyEvent& event) {
|
| -#if defined(OS_WIN)
|
| - // If the focused view wants to process the key event as is, let it be.
|
| - // On Linux we always dispatch key events to the focused view first, so
|
| - // we should not do this check here. See also NativeWidgetGtk::OnKeyEvent().
|
| - if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event))
|
| - return true;
|
| -#endif
|
| -
|
| - // Intercept Tab related messages for focus traversal.
|
| - // Note that we don't do focus traversal if the root window is not part of the
|
| - // active window hierarchy as this would mean we have no focused view and
|
| - // would focus the first focusable view.
|
| -#if defined(OS_WIN) && !defined(USE_AURA)
|
| - HWND top_window = widget_->GetNativeView();
|
| - HWND active_window = ::GetActiveWindow();
|
| - if ((active_window == top_window || ::IsChild(active_window, top_window)) &&
|
| - IsTabTraversalKeyEvent(event)) {
|
| - AdvanceFocus(event.IsShiftDown());
|
| - return false;
|
| - }
|
| -#else
|
| - if (IsTabTraversalKeyEvent(event)) {
|
| - AdvanceFocus(event.IsShiftDown());
|
| - return false;
|
| - }
|
| -#endif
|
| -
|
| - // Intercept arrow key messages to switch between grouped views.
|
| - ui::KeyboardCode key_code = event.key_code();
|
| - if (focused_view_ && focused_view_->GetGroup() != -1 &&
|
| - (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN ||
|
| - key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) {
|
| - bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN);
|
| - View::Views views;
|
| - focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), &views);
|
| - View::Views::const_iterator i(
|
| - std::find(views.begin(), views.end(), focused_view_));
|
| - DCHECK(i != views.end());
|
| - int index = static_cast<int>(i - views.begin());
|
| - index += next ? 1 : -1;
|
| - if (index < 0) {
|
| - index = static_cast<int>(views.size()) - 1;
|
| - } else if (index >= static_cast<int>(views.size())) {
|
| - index = 0;
|
| - }
|
| - SetFocusedViewWithReason(views[index], kReasonFocusTraversal);
|
| - return false;
|
| - }
|
| -
|
| - // Process keyboard accelerators.
|
| - // If the key combination matches an accelerator, the accelerator is
|
| - // triggered, otherwise the key event is processed as usual.
|
| - ui::Accelerator accelerator(event.key_code(),
|
| - event.IsShiftDown(),
|
| - event.IsControlDown(),
|
| - event.IsAltDown());
|
| - if (ProcessAccelerator(accelerator)) {
|
| - // If a shortcut was activated for this keydown message, do not propagate
|
| - // the event further.
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void FocusManager::ValidateFocusedView() {
|
| - if (focused_view_) {
|
| - if (!ContainsView(focused_view_))
|
| - ClearFocus();
|
| - }
|
| -}
|
| -
|
| -// Tests whether a view is valid, whether it still belongs to the window
|
| -// hierarchy of the FocusManager.
|
| -bool FocusManager::ContainsView(View* view) {
|
| - Widget* widget = view->GetWidget();
|
| - return widget ? widget->GetFocusManager() == this : false;
|
| -}
|
| -
|
| -void FocusManager::AdvanceFocus(bool reverse) {
|
| - View* v = GetNextFocusableView(focused_view_, reverse, false);
|
| - // Note: Do not skip this next block when v == focused_view_. If the user
|
| - // tabs past the last focusable element in a webpage, we'll get here, and if
|
| - // the TabContentsContainerView is the only focusable view (possible in
|
| - // fullscreen mode), we need to run this block in order to cycle around to the
|
| - // first element on the page.
|
| - if (v) {
|
| - v->AboutToRequestFocusFromTabTraversal(reverse);
|
| - SetFocusedViewWithReason(v, kReasonFocusTraversal);
|
| - }
|
| -}
|
| -
|
| -void FocusManager::ClearNativeFocus() {
|
| - // Keep the top root window focused so we get keyboard events.
|
| - widget_->ClearNativeFocus();
|
| -}
|
| -
|
| -View* FocusManager::GetNextFocusableView(View* original_starting_view,
|
| - bool reverse,
|
| - bool dont_loop) {
|
| - FocusTraversable* focus_traversable = NULL;
|
| -
|
| - // Let's revalidate the focused view.
|
| - ValidateFocusedView();
|
| -
|
| - View* starting_view = NULL;
|
| - if (original_starting_view) {
|
| - // Search up the containment hierarchy to see if a view is acting as
|
| - // a pane, and wants to implement its own focus traversable to keep
|
| - // the focus trapped within that pane.
|
| - View* pane_search = original_starting_view;
|
| - while (pane_search) {
|
| - focus_traversable = pane_search->GetPaneFocusTraversable();
|
| - if (focus_traversable) {
|
| - starting_view = original_starting_view;
|
| - break;
|
| - }
|
| - pane_search = pane_search->parent();
|
| - }
|
| -
|
| - if (!focus_traversable) {
|
| - if (!reverse) {
|
| - // If the starting view has a focus traversable, use it.
|
| - // This is the case with NativeWidgetWins for example.
|
| - focus_traversable = original_starting_view->GetFocusTraversable();
|
| -
|
| - // Otherwise default to the root view.
|
| - if (!focus_traversable) {
|
| - focus_traversable =
|
| - original_starting_view->GetWidget()->GetFocusTraversable();
|
| - starting_view = original_starting_view;
|
| - }
|
| - } else {
|
| - // When you are going back, starting view's FocusTraversable
|
| - // should not be used.
|
| - focus_traversable =
|
| - original_starting_view->GetWidget()->GetFocusTraversable();
|
| - starting_view = original_starting_view;
|
| - }
|
| - }
|
| - } else {
|
| - focus_traversable = widget_->GetFocusTraversable();
|
| - }
|
| -
|
| - // Traverse the FocusTraversable tree down to find the focusable view.
|
| - View* v = FindFocusableView(focus_traversable, starting_view, reverse);
|
| - if (v) {
|
| - return v;
|
| - } else {
|
| - // Let's go up in the FocusTraversable tree.
|
| - FocusTraversable* parent_focus_traversable =
|
| - focus_traversable->GetFocusTraversableParent();
|
| - starting_view = focus_traversable->GetFocusTraversableParentView();
|
| - while (parent_focus_traversable) {
|
| - FocusTraversable* new_focus_traversable = NULL;
|
| - View* new_starting_view = NULL;
|
| - // When we are going backward, the parent view might gain the next focus.
|
| - bool check_starting_view = reverse;
|
| - v = parent_focus_traversable->GetFocusSearch()->FindNextFocusableView(
|
| - starting_view, reverse, FocusSearch::UP,
|
| - check_starting_view, &new_focus_traversable, &new_starting_view);
|
| -
|
| - if (new_focus_traversable) {
|
| - DCHECK(!v);
|
| -
|
| - // There is a FocusTraversable, traverse it down.
|
| - v = FindFocusableView(new_focus_traversable, NULL, reverse);
|
| - }
|
| -
|
| - if (v)
|
| - return v;
|
| -
|
| - starting_view = focus_traversable->GetFocusTraversableParentView();
|
| - parent_focus_traversable =
|
| - parent_focus_traversable->GetFocusTraversableParent();
|
| - }
|
| -
|
| - // If we get here, we have reached the end of the focus hierarchy, let's
|
| - // loop. Make sure there was at least a view to start with, to prevent
|
| - // infinitely looping in empty windows.
|
| - if (!dont_loop && original_starting_view) {
|
| - // Easy, just clear the selection and press tab again.
|
| - // By calling with NULL as the starting view, we'll start from the
|
| - // top_root_view.
|
| - return GetNextFocusableView(NULL, reverse, true);
|
| - }
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -void FocusManager::SetFocusedViewWithReason(
|
| - View* view, FocusChangeReason reason) {
|
| - if (focused_view_ == view)
|
| - return;
|
| -
|
| - AutoReset<bool> auto_changing_focus(&is_changing_focus_, true);
|
| - // Update the reason for the focus change (since this is checked by
|
| - // some listeners), then notify all listeners.
|
| - focus_change_reason_ = reason;
|
| - FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_,
|
| - OnWillChangeFocus(focused_view_, view));
|
| -
|
| - View* old_focused_view = focused_view_;
|
| - focused_view_ = view;
|
| - if (old_focused_view)
|
| - old_focused_view->Blur();
|
| - if (focused_view_)
|
| - focused_view_->Focus();
|
| -
|
| - FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_,
|
| - OnDidChangeFocus(old_focused_view, focused_view_));
|
| -}
|
| -
|
| -void FocusManager::ClearFocus() {
|
| - SetFocusedView(NULL);
|
| - ClearNativeFocus();
|
| -}
|
| -
|
| -void FocusManager::StoreFocusedView() {
|
| - ViewStorage* view_storage = ViewStorage::GetInstance();
|
| - if (!view_storage) {
|
| - // This should never happen but bug 981648 seems to indicate it could.
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - // TODO (jcampan): when a TabContents containing a popup is closed, the focus
|
| - // is stored twice causing an assert. We should find a better alternative than
|
| - // removing the view from the storage explicitly.
|
| - view_storage->RemoveView(stored_focused_view_storage_id_);
|
| -
|
| - if (!focused_view_)
|
| - return;
|
| -
|
| - view_storage->StoreView(stored_focused_view_storage_id_, focused_view_);
|
| -
|
| - View* v = focused_view_;
|
| -
|
| - {
|
| - // Temporarily disable notification. ClearFocus() will set the focus to the
|
| - // main browser window. This extra focus bounce which happens during
|
| - // deactivation can confuse registered WidgetFocusListeners, as the focus
|
| - // is not changing due to a user-initiated event.
|
| - AutoNativeNotificationDisabler local_notification_disabler;
|
| - ClearFocus();
|
| - }
|
| -
|
| - if (v)
|
| - v->SchedulePaint(); // Remove focus border.
|
| -}
|
| -
|
| -void FocusManager::RestoreFocusedView() {
|
| - ViewStorage* view_storage = ViewStorage::GetInstance();
|
| - if (!view_storage) {
|
| - // This should never happen but bug 981648 seems to indicate it could.
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - View* view = view_storage->RetrieveView(stored_focused_view_storage_id_);
|
| - if (view) {
|
| - if (ContainsView(view)) {
|
| - if (!view->IsFocusableInRootView() &&
|
| - view->IsAccessibilityFocusableInRootView()) {
|
| - // RequestFocus would fail, but we want to restore focus to controls
|
| - // that had focus in accessibility mode.
|
| - SetFocusedViewWithReason(view, kReasonFocusRestore);
|
| - } else {
|
| - // This usually just sets the focus if this view is focusable, but
|
| - // let the view override RequestFocus if necessary.
|
| - view->RequestFocus();
|
| -
|
| - // If it succeeded, the reason would be incorrect; set it to
|
| - // focus restore.
|
| - if (focused_view_ == view)
|
| - focus_change_reason_ = kReasonFocusRestore;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void FocusManager::ClearStoredFocusedView() {
|
| - ViewStorage* view_storage = ViewStorage::GetInstance();
|
| - if (!view_storage) {
|
| - // This should never happen but bug 981648 seems to indicate it could.
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| - view_storage->RemoveView(stored_focused_view_storage_id_);
|
| -}
|
| -
|
| -// Find the next (previous if reverse is true) focusable view for the specified
|
| -// FocusTraversable, starting at the specified view, traversing down the
|
| -// FocusTraversable hierarchy.
|
| -View* FocusManager::FindFocusableView(FocusTraversable* focus_traversable,
|
| - View* starting_view,
|
| - bool reverse) {
|
| - FocusTraversable* new_focus_traversable = NULL;
|
| - View* new_starting_view = NULL;
|
| - View* v = focus_traversable->GetFocusSearch()->FindNextFocusableView(
|
| - starting_view,
|
| - reverse,
|
| - FocusSearch::DOWN,
|
| - false,
|
| - &new_focus_traversable,
|
| - &new_starting_view);
|
| -
|
| - // Let's go down the FocusTraversable tree as much as we can.
|
| - while (new_focus_traversable) {
|
| - DCHECK(!v);
|
| - focus_traversable = new_focus_traversable;
|
| - starting_view = new_starting_view;
|
| - new_focus_traversable = NULL;
|
| - starting_view = NULL;
|
| - v = focus_traversable->GetFocusSearch()->FindNextFocusableView(
|
| - starting_view,
|
| - reverse,
|
| - FocusSearch::DOWN,
|
| - false,
|
| - &new_focus_traversable,
|
| - &new_starting_view);
|
| - }
|
| - return v;
|
| -}
|
| -
|
| -void FocusManager::RegisterAccelerator(
|
| - const ui::Accelerator& accelerator,
|
| - ui::AcceleratorTarget* target) {
|
| - accelerator_manager_->Register(accelerator, target);
|
| -}
|
| -
|
| -void FocusManager::UnregisterAccelerator(const ui::Accelerator& accelerator,
|
| - ui::AcceleratorTarget* target) {
|
| - accelerator_manager_->Unregister(accelerator, target);
|
| -}
|
| -
|
| -void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) {
|
| - accelerator_manager_->UnregisterAll(target);
|
| -}
|
| -
|
| -bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) {
|
| - return accelerator_manager_->Process(accelerator);
|
| -}
|
| -
|
| -ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator(
|
| - const ui::Accelerator& accelerator) const {
|
| - return accelerator_manager_->GetCurrentTarget(accelerator);
|
| -}
|
| -
|
| -void FocusManager::FocusNativeView(gfx::NativeView native_view) {
|
| - widget_->FocusNativeView(native_view);
|
| -}
|
| -
|
| -// static
|
| -bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) {
|
| - return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown();
|
| -}
|
| -
|
| -void FocusManager::ViewRemoved(View* removed) {
|
| - // If the view being removed contains (or is) the focused view,
|
| - // clear the focus. However, it's not safe to call ClearFocus()
|
| - // (and in turn ClearNativeFocus()) here because ViewRemoved() can
|
| - // be called while the top level widget is being destroyed.
|
| - if (focused_view_ && removed && removed->Contains(focused_view_))
|
| - SetFocusedView(NULL);
|
| -}
|
| -
|
| -void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) {
|
| - focus_change_listeners_.AddObserver(listener);
|
| -}
|
| -
|
| -void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) {
|
| - focus_change_listeners_.RemoveObserver(listener);
|
| -}
|
| -
|
| -} // namespace views
|
|
|