This source file includes following definitions.
- is_changing_focus_
- OnKeyEvent
- ValidateFocusedView
- ContainsView
- AdvanceFocus
- ClearNativeFocus
- RotatePaneFocus
- GetNextFocusableView
- SetFocusedViewWithReason
- ClearFocus
- StoreFocusedView
- RestoreFocusedView
- SetStoredFocusView
- GetStoredFocusView
- ClearStoredFocusedView
- FindFocusableView
- RegisterAccelerator
- UnregisterAccelerator
- UnregisterAccelerators
- ProcessAccelerator
- GetCurrentTargetForAccelerator
- HasPriorityHandler
- IsTabTraversalKeyEvent
- ViewRemoved
- AddFocusChangeListener
- RemoveFocusChangeListener
- ProcessArrowKeyTraversal
#include "ui/views/focus/focus_manager.h"
#include <algorithm>
#include <vector>
#include "base/auto_reset.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/focus/focus_manager_delegate.h"
#include "ui/views/focus/focus_search.h"
#include "ui/views/focus/view_storage.h"
#include "ui/views/focus/widget_focus_manager.h"
#include "ui/views/view.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
namespace views {
namespace {
}
bool FocusManager::shortcut_handling_suspended_ = false;
bool FocusManager::arrow_key_traversal_enabled_ = false;
FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate)
: widget_(widget),
delegate_(delegate),
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 ui::KeyEvent& event) {
const int key_code = event.key_code();
if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED)
return false;
if (shortcut_handling_suspended())
return true;
int modifiers = ui::EF_NONE;
if (event.IsShiftDown())
modifiers |= ui::EF_SHIFT_DOWN;
if (event.IsControlDown())
modifiers |= ui::EF_CONTROL_DOWN;
if (event.IsAltDown())
modifiers |= ui::EF_ALT_DOWN;
ui::Accelerator accelerator(event.key_code(), modifiers);
accelerator.set_type(event.type());
if (event.type() == ui::ET_KEY_PRESSED) {
if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event) &&
!accelerator_manager_->HasPriorityHandler(accelerator))
return true;
if (IsTabTraversalKeyEvent(event)) {
AdvanceFocus(event.IsShiftDown());
return false;
}
if (arrow_key_traversal_enabled_ && ProcessArrowKeyTraversal(event))
return false;
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;
}
}
if (ProcessAccelerator(accelerator)) {
return false;
}
return true;
}
void FocusManager::ValidateFocusedView() {
if (focused_view_ && !ContainsView(focused_view_))
ClearFocus();
}
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_, NULL, reverse, false);
if (v) {
views::View* focused_view = focused_view_;
v->AboutToRequestFocusFromTabTraversal(reverse);
if (focused_view == focused_view_)
SetFocusedViewWithReason(v, kReasonFocusTraversal);
}
}
void FocusManager::ClearNativeFocus() {
widget_->ClearNativeFocus();
}
bool FocusManager::RotatePaneFocus(Direction direction,
FocusCycleWrappingBehavior wrap) {
std::vector<View*> panes;
widget_->widget_delegate()->GetAccessiblePanes(&panes);
int count = static_cast<int>(panes.size());
if (count == 0)
return false;
int index = direction == kBackward ? 0 : count - 1;
const views::View* focused_view = GetFocusedView();
if (focused_view) {
for (int i = 0; i < count; i++) {
if (panes[i] && panes[i]->Contains(focused_view)) {
index = i;
break;
}
}
}
int start_index = index;
for (;;) {
if (direction == kBackward)
index--;
else
index++;
if (wrap == kNoWrap && (index >= count || index < 0))
return false;
index = (index + count) % count;
if (index == start_index)
break;
views::View* pane = panes[index];
DCHECK(pane);
if (!pane->visible())
continue;
pane->RequestFocus();
focused_view = GetFocusedView();
if (pane == focused_view || pane->Contains(focused_view))
return true;
}
return false;
}
View* FocusManager::GetNextFocusableView(View* original_starting_view,
Widget* starting_widget,
bool reverse,
bool dont_loop) {
FocusTraversable* focus_traversable = NULL;
ValidateFocusedView();
View* starting_view = NULL;
if (original_starting_view) {
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) {
focus_traversable = original_starting_view->GetFocusTraversable();
if (!focus_traversable) {
focus_traversable =
original_starting_view->GetWidget()->GetFocusTraversable();
starting_view = original_starting_view;
}
} else {
focus_traversable =
original_starting_view->GetWidget()->GetFocusTraversable();
starting_view = original_starting_view;
}
}
} else {
Widget* widget = starting_widget ? starting_widget : widget_;
focus_traversable = widget->GetFocusTraversable();
}
View* v = FindFocusableView(focus_traversable, starting_view, reverse);
if (v) {
return v;
} else {
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;
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);
v = FindFocusableView(new_focus_traversable, NULL, reverse);
}
if (v)
return v;
starting_view = focus_traversable->GetFocusTraversableParentView();
parent_focus_traversable =
parent_focus_traversable->GetFocusTraversableParent();
}
if (!dont_loop && original_starting_view) {
Widget* widget = original_starting_view->GetWidget();
if (widget->widget_delegate()->ShouldAdvanceFocusToTopLevelWidget())
widget = widget_;
return GetNextFocusableView(NULL, widget, reverse, true);
}
}
return NULL;
}
void FocusManager::SetFocusedViewWithReason(
View* view, FocusChangeReason reason) {
if (focused_view_ == view)
return;
base::AutoReset<bool> auto_changing_focus(&is_changing_focus_, true);
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();
SetStoredFocusView(focused_view_);
if (focused_view_)
focused_view_->Focus();
FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_,
OnDidChangeFocus(old_focused_view, focused_view_));
}
void FocusManager::ClearFocus() {
views::View* focused_view = GetStoredFocusView();
SetFocusedView(NULL);
ClearNativeFocus();
SetStoredFocusView(focused_view);
}
void FocusManager::StoreFocusedView(bool clear_native_focus) {
View* focused_view = focused_view_;
if (!focused_view_)
return;
View* v = focused_view_;
if (clear_native_focus) {
AutoNativeNotificationDisabler local_notification_disabler;
ClearFocus();
} else {
SetFocusedView(NULL);
SetStoredFocusView(focused_view);
}
if (v)
v->SchedulePaint();
}
bool FocusManager::RestoreFocusedView() {
View* view = GetStoredFocusView();
if (view) {
if (ContainsView(view)) {
if (!view->IsFocusable() && view->IsAccessibilityFocusable()) {
SetFocusedViewWithReason(view, kReasonFocusRestore);
} else {
view->RequestFocus();
if (focused_view_ == view)
focus_change_reason_ = kReasonFocusRestore;
}
}
return true;
}
return false;
}
void FocusManager::SetStoredFocusView(View* focus_view) {
ViewStorage* view_storage = ViewStorage::GetInstance();
if (!view_storage) {
NOTREACHED();
return;
}
view_storage->RemoveView(stored_focused_view_storage_id_);
if (!focus_view)
return;
view_storage->StoreView(stored_focused_view_storage_id_, focus_view);
}
View* FocusManager::GetStoredFocusView() {
ViewStorage* view_storage = ViewStorage::GetInstance();
if (!view_storage) {
NOTREACHED();
return NULL;
}
return view_storage->RetrieveView(stored_focused_view_storage_id_);
}
void FocusManager::ClearStoredFocusedView() {
SetStoredFocusView(NULL);
}
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);
while (new_focus_traversable) {
DCHECK(!v);
focus_traversable = new_focus_traversable;
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::AcceleratorManager::HandlerPriority priority,
ui::AcceleratorTarget* target) {
accelerator_manager_->Register(accelerator, priority, 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) {
if (accelerator_manager_->Process(accelerator))
return true;
if (delegate_.get())
return delegate_->ProcessAccelerator(accelerator);
return false;
}
ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator(
const ui::Accelerator& accelerator) const {
ui::AcceleratorTarget* target =
accelerator_manager_->GetCurrentTarget(accelerator);
if (!target && delegate_.get())
target = delegate_->GetCurrentTargetForAccelerator(accelerator);
return target;
}
bool FocusManager::HasPriorityHandler(
const ui::Accelerator& accelerator) const {
return accelerator_manager_->HasPriorityHandler(accelerator);
}
bool FocusManager::IsTabTraversalKeyEvent(const ui::KeyEvent& key_event) {
return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown();
}
void FocusManager::ViewRemoved(View* removed) {
if (focused_view_ && 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);
}
bool FocusManager::ProcessArrowKeyTraversal(const ui::KeyEvent& event) {
if (event.IsShiftDown() || event.IsControlDown() || event.IsAltDown())
return false;
const int key_code = event.key_code();
if (key_code == ui::VKEY_LEFT || key_code == ui::VKEY_UP) {
AdvanceFocus(true);
return true;
}
if (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN) {
AdvanceFocus(false);
return true;
}
return false;
}
}