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

Unified Diff: views/focus/focus_manager.cc

Issue 8588064: views: Move bubble, events, focus and layout to ui/views/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « views/focus/focus_manager.h ('k') | views/focus/focus_manager_factory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « views/focus/focus_manager.h ('k') | views/focus/focus_manager_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698