diff options
Diffstat (limited to 'ui/views/focus/focus_manager.cc')
-rw-r--r-- | ui/views/focus/focus_manager.cc | 300 |
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 |