summaryrefslogtreecommitdiffstats
path: root/views/widget/root_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'views/widget/root_view.cc')
-rw-r--r--views/widget/root_view.cc228
1 files changed, 3 insertions, 225 deletions
diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc
index 12faf68..ff08d29 100644
--- a/views/widget/root_view.cc
+++ b/views/widget/root_view.cc
@@ -62,6 +62,7 @@ RootView::RootView(Widget* widget)
mouse_move_handler_(NULL),
last_click_handler_(NULL),
widget_(widget),
+ ALLOW_THIS_IN_INITIALIZER_LIST(focus_search_(this, false, false)),
invalid_rect_urgent_(false),
pending_paint_task_(NULL),
paint_task_needed_(false),
@@ -575,210 +576,8 @@ View* RootView::GetFocusedView() {
return NULL;
}
-View* RootView::FindNextFocusableView(View* starting_view,
- bool reverse,
- Direction direction,
- bool check_starting_view,
- FocusTraversable** focus_traversable,
- View** focus_traversable_view) {
- *focus_traversable = NULL;
- *focus_traversable_view = NULL;
-
- if (GetChildViewCount() == 0) {
- NOTREACHED();
- // Nothing to focus on here.
- return NULL;
- }
-
- if (!starting_view) {
- // Default to the first/last child
- starting_view = reverse ? GetChildViewAt(GetChildViewCount() - 1) :
- GetChildViewAt(0);
- // If there was no starting view, then the one we select is a potential
- // focus candidate.
- check_starting_view = true;
- } else {
- // The starting view should be part of this RootView.
- DCHECK(IsParentOf(starting_view));
- }
-
- View* v = NULL;
- if (!reverse) {
- v = FindNextFocusableViewImpl(starting_view, check_starting_view,
- true,
- (direction == DOWN) ? true : false,
- starting_view->GetGroup(),
- focus_traversable,
- focus_traversable_view);
- } else {
- // If the starting view is focusable, we don't want to go down, as we are
- // traversing the view hierarchy tree bottom-up.
- bool can_go_down = (direction == DOWN) && !starting_view->IsFocusable();
- v = FindPreviousFocusableViewImpl(starting_view, check_starting_view,
- true,
- can_go_down,
- starting_view->GetGroup(),
- focus_traversable,
- focus_traversable_view);
- }
-
- // Doing some sanity checks.
- if (v) {
- DCHECK(v->IsFocusable());
- return v;
- }
- if (*focus_traversable) {
- DCHECK(*focus_traversable_view);
- return NULL;
- }
- // Nothing found.
- return NULL;
-}
-
-// Strategy for finding the next focusable view:
-// - keep going down the first child, stop when you find a focusable view or
-// a focus traversable view (in that case return it) or when you reach a view
-// with no children.
-// - go to the right sibling and start the search from there (by invoking
-// FindNextFocusableViewImpl on that view).
-// - if the view has no right sibling, go up the parents until you find a parent
-// with a right sibling and start the search from there.
-View* RootView::FindNextFocusableViewImpl(View* starting_view,
- bool check_starting_view,
- bool can_go_up,
- bool can_go_down,
- int skip_group_id,
- FocusTraversable** focus_traversable,
- View** focus_traversable_view) {
- if (check_starting_view) {
- if (IsViewFocusableCandidate(starting_view, skip_group_id)) {
- View* v = FindSelectedViewForGroup(starting_view);
- // The selected view might not be focusable (if it is disabled for
- // example).
- if (v && v->IsFocusable())
- return v;
- }
-
- *focus_traversable = starting_view->GetFocusTraversable();
- if (*focus_traversable) {
- *focus_traversable_view = starting_view;
- return NULL;
- }
- }
-
- // First let's try the left child.
- if (can_go_down) {
- if (starting_view->GetChildViewCount() > 0) {
- View* v = FindNextFocusableViewImpl(starting_view->GetChildViewAt(0),
- true, false, true, skip_group_id,
- focus_traversable,
- focus_traversable_view);
- if (v || *focus_traversable)
- return v;
- }
- }
-
- // Then try the right sibling.
- View* sibling = starting_view->GetNextFocusableView();
- if (sibling) {
- View* v = FindNextFocusableViewImpl(sibling,
- true, false, true, skip_group_id,
- focus_traversable,
- focus_traversable_view);
- if (v || *focus_traversable)
- return v;
- }
-
- // Then go up to the parent sibling.
- if (can_go_up) {
- View* parent = starting_view->GetParent();
- while (parent) {
- sibling = parent->GetNextFocusableView();
- if (sibling) {
- return FindNextFocusableViewImpl(sibling,
- true, true, true,
- skip_group_id,
- focus_traversable,
- focus_traversable_view);
- }
- parent = parent->GetParent();
- }
- }
-
- // We found nothing.
- return NULL;
-}
-
-// Strategy for finding the previous focusable view:
-// - keep going down on the right until you reach a view with no children, if it
-// it is a good candidate return it.
-// - start the search on the left sibling.
-// - if there are no left sibling, start the search on the parent (without going
-// down).
-View* RootView::FindPreviousFocusableViewImpl(
- View* starting_view,
- bool check_starting_view,
- bool can_go_up,
- bool can_go_down,
- int skip_group_id,
- FocusTraversable** focus_traversable,
- View** focus_traversable_view) {
- // Let's go down and right as much as we can.
- if (can_go_down) {
- // Before we go into the direct children, we have to check if this view has
- // a FocusTraversable.
- *focus_traversable = starting_view->GetFocusTraversable();
- if (*focus_traversable) {
- *focus_traversable_view = starting_view;
- return NULL;
- }
-
- if (starting_view->GetChildViewCount() > 0) {
- View* view =
- starting_view->GetChildViewAt(starting_view->GetChildViewCount() - 1);
- View* v = FindPreviousFocusableViewImpl(view, true, false, true,
- skip_group_id,
- focus_traversable,
- focus_traversable_view);
- if (v || *focus_traversable)
- return v;
- }
- }
-
- // Then look at this view. Here, we do not need to see if the view has
- // a FocusTraversable, since we do not want to go down any more.
- if (check_starting_view &&
- IsViewFocusableCandidate(starting_view, skip_group_id)) {
- View* v = FindSelectedViewForGroup(starting_view);
- // The selected view might not be focusable (if it is disabled for
- // example).
- if (v && v->IsFocusable())
- return v;
- }
-
- // Then try the left sibling.
- View* sibling = starting_view->GetPreviousFocusableView();
- if (sibling) {
- return FindPreviousFocusableViewImpl(sibling,
- true, true, true,
- skip_group_id,
- focus_traversable,
- focus_traversable_view);
- }
-
- // Then go up the parent.
- if (can_go_up) {
- View* parent = starting_view->GetParent();
- if (parent)
- return FindPreviousFocusableViewImpl(parent,
- true, true, false,
- skip_group_id,
- focus_traversable,
- focus_traversable_view);
- }
-
- // We found nothing.
- return NULL;
+FocusSearch* RootView::GetFocusSearch() {
+ return &focus_search_;
}
FocusTraversable* RootView::GetFocusTraversableParent() {
@@ -803,27 +602,6 @@ void RootView::NotifyNativeViewHierarchyChanged(bool attached,
PropagateNativeViewHierarchyChanged(attached, native_view, this);
}
-// static
-View* RootView::FindSelectedViewForGroup(View* view) {
- if (view->IsGroupFocusTraversable() ||
- view->GetGroup() == -1) // No group for that view.
- return view;
-
- View* selected_view = view->GetSelectedViewForGroup(view->GetGroup());
- if (selected_view)
- return selected_view;
-
- // No view selected for that group, default to the specified view.
- return view;
-}
-
-// static
-bool RootView::IsViewFocusableCandidate(View* v, int skip_group_id) {
- return v->IsFocusable() &&
- (v->IsGroupFocusTraversable() || skip_group_id == -1 ||
- v->GetGroup() != skip_group_id);
-}
-
bool RootView::ProcessKeyEvent(const KeyEvent& event) {
bool consumed = false;