summaryrefslogtreecommitdiffstats
path: root/ui/views/focus/focus_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/views/focus/focus_manager.cc')
-rw-r--r--ui/views/focus/focus_manager.cc300
1 files changed, 152 insertions, 148 deletions
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 93c299f..501d270 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -69,7 +69,8 @@ FocusManager::WidgetFocusManager::GetInstance() {
return Singleton<WidgetFocusManager>::get();
}
-// FocusManager -----------------------------------------------------
+////////////////////////////////////////////////////////////////////////////////
+// FocusManager, public:
FocusManager::FocusManager(Widget* widget)
: widget_(widget),
@@ -154,13 +155,6 @@ bool FocusManager::OnKeyEvent(const KeyEvent& event) {
return true;
}
-void FocusManager::ValidateFocusedView() {
- if (focused_view_) {
- if (!ContainsView(focused_view_))
- ClearFocus();
- }
-}
-
bool FocusManager::ContainsView(View* view) const {
Widget* widget = view->GetWidget();
return widget ? widget->GetFocusManager() == this : false;
@@ -187,99 +181,6 @@ void FocusManager::AdvanceFocus(bool reverse) {
}
}
-View* FocusManager::GetNextFocusableView(View* original_starting_view,
- bool reverse,
- bool dont_loop) {
- FocusTraversable* focus_traversable = NULL;
-
- // Let's re-validate 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 WidgetWins 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) {
focus_change_reason_ = reason;
@@ -315,6 +216,13 @@ void FocusManager::ClearFocus() {
widget_->native_widget()->FocusNativeView(NULL);
}
+void FocusManager::ValidateFocusedView() {
+ if (focused_view_) {
+ if (!ContainsView(focused_view_))
+ ClearFocus();
+ }
+}
+
void FocusManager::StoreFocusedView() {
ViewStorage* view_storage = ViewStorage::GetInstance();
if (!view_storage) {
@@ -392,40 +300,6 @@ void FocusManager::ClearStoredFocusedView() {
view_storage->RemoveViewByID(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 Accelerator& accelerator,
AcceleratorTarget* target) {
@@ -477,6 +351,24 @@ bool FocusManager::ProcessAccelerator(const Accelerator& accelerator) {
return false;
}
+void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) {
+ DCHECK(std::find(focus_change_listeners_.begin(),
+ focus_change_listeners_.end(), listener) ==
+ focus_change_listeners_.end()) << "Adding a listener twice.";
+ focus_change_listeners_.push_back(listener);
+}
+
+void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) {
+ FocusChangeListenerList::iterator place =
+ std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(),
+ listener);
+ if (place == focus_change_listeners_.end()) {
+ NOTREACHED() << "Removing a listener that isn't registered.";
+ return;
+ }
+ focus_change_listeners_.erase(place);
+}
+
AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator(
const Accelerator& accelerator) const {
AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator);
@@ -507,22 +399,134 @@ FocusManager* FocusManager::GetFocusManagerForNativeWindow(
return native_widget ? native_widget->GetWidget()->GetFocusManager() : NULL;
}
-void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) {
- DCHECK(std::find(focus_change_listeners_.begin(),
- focus_change_listeners_.end(), listener) ==
- focus_change_listeners_.end()) << "Adding a listener twice.";
- focus_change_listeners_.push_back(listener);
+////////////////////////////////////////////////////////////////////////////////
+// FocusManager, private:
+
+View* FocusManager::GetNextFocusableView(View* original_starting_view,
+ bool reverse,
+ bool dont_loop) {
+ FocusTraversable* focus_traversable = NULL;
+
+ // Let's re-validate 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 WidgetWins 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::RemoveFocusChangeListener(FocusChangeListener* listener) {
- FocusChangeListenerList::iterator place =
- std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(),
- listener);
- if (place == focus_change_listeners_.end()) {
- NOTREACHED() << "Removing a listener that isn't registered.";
- return;
+// 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);
}
- focus_change_listeners_.erase(place);
+ return v;
}
} // namespace ui