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

Side by Side Diff: views/widget/root_view.cc

Issue 125062: Fix reversed focus traversal order issue. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 6 months 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/widget/root_view.h ('k') | views/widget/widget_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "views/widget/root_view.h" 5 #include "views/widget/root_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "app/drag_drop_types.h" 9 #include "app/drag_drop_types.h"
10 #include "app/gfx/canvas.h" 10 #include "app/gfx/canvas.h"
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 // Make sure the focused view belongs to this RootView's view hierarchy. 563 // Make sure the focused view belongs to this RootView's view hierarchy.
564 View* view = focus_manager->GetFocusedView(); 564 View* view = focus_manager->GetFocusedView();
565 if (view && (view->GetRootView() == this)) 565 if (view && (view->GetRootView() == this))
566 return view; 566 return view;
567 return NULL; 567 return NULL;
568 } 568 }
569 569
570 View* RootView::FindNextFocusableView(View* starting_view, 570 View* RootView::FindNextFocusableView(View* starting_view,
571 bool reverse, 571 bool reverse,
572 Direction direction, 572 Direction direction,
573 bool dont_loop, 573 bool check_starting_view,
574 FocusTraversable** focus_traversable, 574 FocusTraversable** focus_traversable,
575 View** focus_traversable_view) { 575 View** focus_traversable_view) {
576 *focus_traversable = NULL; 576 *focus_traversable = NULL;
577 *focus_traversable_view = NULL; 577 *focus_traversable_view = NULL;
578 578
579 if (GetChildViewCount() == 0) { 579 if (GetChildViewCount() == 0) {
580 NOTREACHED(); 580 NOTREACHED();
581 // Nothing to focus on here. 581 // Nothing to focus on here.
582 return NULL; 582 return NULL;
583 } 583 }
584 584
585 bool skip_starting_view = true;
586 if (!starting_view) { 585 if (!starting_view) {
587 // Default to the first/last child 586 // Default to the first/last child
588 starting_view = reverse ? GetChildViewAt(GetChildViewCount() - 1) : 587 starting_view = reverse ? GetChildViewAt(GetChildViewCount() - 1) :
589 GetChildViewAt(0) ; 588 GetChildViewAt(0) ;
590 // If there was no starting view, then the one we select is a potential 589 // If there was no starting view, then the one we select is a potential
591 // focus candidate. 590 // focus candidate.
592 skip_starting_view = false; 591 check_starting_view = true;
593 } else { 592 } else {
594 // The starting view should be part of this RootView. 593 // The starting view should be part of this RootView.
595 DCHECK(IsParentOf(starting_view)); 594 DCHECK(IsParentOf(starting_view));
596 } 595 }
597 596
598 View* v = NULL; 597 View* v = NULL;
599 if (!reverse) { 598 if (!reverse) {
600 v = FindNextFocusableViewImpl(starting_view, skip_starting_view, 599 v = FindNextFocusableViewImpl(starting_view, check_starting_view,
601 true, 600 true,
602 (direction == DOWN) ? true : false, 601 (direction == DOWN) ? true : false,
603 starting_view->GetGroup()); 602 starting_view->GetGroup(),
603 focus_traversable,
604 focus_traversable_view);
604 } else { 605 } else {
605 // If the starting view is focusable, we don't want to go down, as we are 606 // If the starting view is focusable, we don't want to go down, as we are
606 // traversing the view hierarchy tree bottom-up. 607 // traversing the view hierarchy tree bottom-up.
607 bool can_go_down = (direction == DOWN) && !starting_view->IsFocusable(); 608 bool can_go_down = (direction == DOWN) && !starting_view->IsFocusable();
608 v = FindPreviousFocusableViewImpl(starting_view, true, 609 v = FindPreviousFocusableViewImpl(starting_view, check_starting_view,
609 true, 610 true,
610 can_go_down, 611 can_go_down,
611 starting_view->GetGroup()); 612 starting_view->GetGroup(),
613 focus_traversable,
614 focus_traversable_view);
612 } 615 }
616
617 // Doing some sanity checks.
613 if (v) { 618 if (v) {
614 if (v->IsFocusable()) 619 DCHECK(v->IsFocusable());
615 return v; 620 return v;
616 *focus_traversable = v->GetFocusTraversable(); 621 }
617 DCHECK(*focus_traversable); 622 if (*focus_traversable) {
618 *focus_traversable_view = v; 623 DCHECK(*focus_traversable_view);
619 return NULL; 624 return NULL;
620 } 625 }
621 // Nothing found. 626 // Nothing found.
622 return NULL; 627 return NULL;
623 } 628 }
624 629
625 // Strategy for finding the next focusable view: 630 // Strategy for finding the next focusable view:
626 // - keep going down the first child, stop when you find a focusable view or 631 // - keep going down the first child, stop when you find a focusable view or
627 // a focus traversable view (in that case return it) or when you reach a view 632 // a focus traversable view (in that case return it) or when you reach a view
628 // with no children. 633 // with no children.
629 // - go to the right sibling and start the search from there (by invoking 634 // - go to the right sibling and start the search from there (by invoking
630 // FindNextFocusableViewImpl on that view). 635 // FindNextFocusableViewImpl on that view).
631 // - if the view has no right sibling, go up the parents until you find a parent 636 // - if the view has no right sibling, go up the parents until you find a parent
632 // with a right sibling and start the search from there. 637 // with a right sibling and start the search from there.
633 View* RootView::FindNextFocusableViewImpl(View* starting_view, 638 View* RootView::FindNextFocusableViewImpl(View* starting_view,
634 bool skip_starting_view, 639 bool check_starting_view,
635 bool can_go_up, 640 bool can_go_up,
636 bool can_go_down, 641 bool can_go_down,
637 int skip_group_id) { 642 int skip_group_id,
638 if (!skip_starting_view) { 643 FocusTraversable** focus_traversable,
644 View** focus_traversable_view) {
645 if (check_starting_view) {
639 if (IsViewFocusableCandidate(starting_view, skip_group_id)) 646 if (IsViewFocusableCandidate(starting_view, skip_group_id))
640 return FindSelectedViewForGroup(starting_view); 647 return FindSelectedViewForGroup(starting_view);
641 if (starting_view->GetFocusTraversable()) 648
642 return starting_view; 649 *focus_traversable = starting_view->GetFocusTraversable();
650 if (*focus_traversable) {
651 *focus_traversable_view = starting_view;
652 return NULL;
653 }
643 } 654 }
644 655
645 // First let's try the left child. 656 // First let's try the left child.
646 if (can_go_down) { 657 if (can_go_down) {
647 if (starting_view->GetChildViewCount() > 0) { 658 if (starting_view->GetChildViewCount() > 0) {
648 View* v = FindNextFocusableViewImpl(starting_view->GetChildViewAt(0), 659 View* v = FindNextFocusableViewImpl(starting_view->GetChildViewAt(0),
649 false, false, true, skip_group_id); 660 true, false, true, skip_group_id,
650 if (v) 661 focus_traversable,
662 focus_traversable_view);
663 if (v || *focus_traversable)
651 return v; 664 return v;
652 } 665 }
653 } 666 }
654 667
655 // Then try the right sibling. 668 // Then try the right sibling.
656 View* sibling = starting_view->GetNextFocusableView(); 669 View* sibling = starting_view->GetNextFocusableView();
657 if (sibling) { 670 if (sibling) {
658 View* v = FindNextFocusableViewImpl(sibling, 671 View* v = FindNextFocusableViewImpl(sibling,
659 false, false, true, skip_group_id); 672 true, false, true, skip_group_id,
660 if (v) 673 focus_traversable,
674 focus_traversable_view);
675 if (v || *focus_traversable)
661 return v; 676 return v;
662 } 677 }
663 678
664 // Then go up to the parent sibling. 679 // Then go up to the parent sibling.
665 if (can_go_up) { 680 if (can_go_up) {
666 View* parent = starting_view->GetParent(); 681 View* parent = starting_view->GetParent();
667 while (parent) { 682 while (parent) {
668 sibling = parent->GetNextFocusableView(); 683 sibling = parent->GetNextFocusableView();
669 if (sibling) { 684 if (sibling) {
670 return FindNextFocusableViewImpl(sibling, 685 return FindNextFocusableViewImpl(sibling,
671 false, true, true, 686 true, true, true,
672 skip_group_id); 687 skip_group_id,
688 focus_traversable,
689 focus_traversable_view);
673 } 690 }
674 parent = parent->GetParent(); 691 parent = parent->GetParent();
675 } 692 }
676 } 693 }
677 694
678 // We found nothing. 695 // We found nothing.
679 return NULL; 696 return NULL;
680 } 697 }
681 698
682 // Strategy for finding the previous focusable view: 699 // Strategy for finding the previous focusable view:
683 // - keep going down on the right until you reach a view with no children, if it 700 // - keep going down on the right until you reach a view with no children, if it
684 // it is a good candidate return it. 701 // it is a good candidate return it.
685 // - start the search on the left sibling. 702 // - start the search on the left sibling.
686 // - if there are no left sibling, start the search on the parent (without going 703 // - if there are no left sibling, start the search on the parent (without going
687 // down). 704 // down).
688 View* RootView::FindPreviousFocusableViewImpl(View* starting_view, 705 View* RootView::FindPreviousFocusableViewImpl(
689 bool skip_starting_view, 706 View* starting_view,
690 bool can_go_up, 707 bool check_starting_view,
691 bool can_go_down, 708 bool can_go_up,
692 int skip_group_id) { 709 bool can_go_down,
710 int skip_group_id,
711 FocusTraversable** focus_traversable,
712 View** focus_traversable_view) {
693 // Let's go down and right as much as we can. 713 // Let's go down and right as much as we can.
694 if (can_go_down) { 714 if (can_go_down) {
715 // Before we go into the direct children, we have to check if this view has
716 // a FocusTraversable.
717 *focus_traversable = starting_view->GetFocusTraversable();
718 if (*focus_traversable) {
719 *focus_traversable_view = starting_view;
720 return NULL;
721 }
722
695 if (starting_view->GetChildViewCount() > 0) { 723 if (starting_view->GetChildViewCount() > 0) {
696 View* view = 724 View* view =
697 starting_view->GetChildViewAt(starting_view->GetChildViewCount() - 1); 725 starting_view->GetChildViewAt(starting_view->GetChildViewCount() - 1);
698 View* v = FindPreviousFocusableViewImpl(view, false, false, true, 726 View* v = FindPreviousFocusableViewImpl(view, true, false, true,
699 skip_group_id); 727 skip_group_id,
700 if (v) 728 focus_traversable,
729 focus_traversable_view);
730 if (v || *focus_traversable)
701 return v; 731 return v;
702 } 732 }
703 } 733 }
704 734
705 if (!skip_starting_view) { 735 // Then look at this view. Here, we do not need to see if the view has
706 if (IsViewFocusableCandidate(starting_view, skip_group_id)) 736 // a FocusTraversable, since we do not want to go down any more.
707 return FindSelectedViewForGroup(starting_view); 737 if (check_starting_view &&
708 if (starting_view->GetFocusTraversable()) 738 IsViewFocusableCandidate(starting_view, skip_group_id)) {
709 return starting_view; 739 return FindSelectedViewForGroup(starting_view);
710 } 740 }
711 741
712 // Then try the left sibling. 742 // Then try the left sibling.
713 View* sibling = starting_view->GetPreviousFocusableView(); 743 View* sibling = starting_view->GetPreviousFocusableView();
714 if (sibling) { 744 if (sibling) {
715 return FindPreviousFocusableViewImpl(sibling, 745 return FindPreviousFocusableViewImpl(sibling,
716 false, true, true, 746 true, true, true,
717 skip_group_id); 747 skip_group_id,
748 focus_traversable,
749 focus_traversable_view);
718 } 750 }
719 751
720 // Then go up the parent. 752 // Then go up the parent.
721 if (can_go_up) { 753 if (can_go_up) {
722 View* parent = starting_view->GetParent(); 754 View* parent = starting_view->GetParent();
723 if (parent) 755 if (parent)
724 return FindPreviousFocusableViewImpl(parent, 756 return FindPreviousFocusableViewImpl(parent,
725 false, true, false, 757 true, true, false,
726 skip_group_id); 758 skip_group_id,
759 focus_traversable,
760 focus_traversable_view);
727 } 761 }
728 762
729 // We found nothing. 763 // We found nothing.
730 return NULL; 764 return NULL;
731 } 765 }
732 766
733 FocusTraversable* RootView::GetFocusTraversableParent() { 767 FocusTraversable* RootView::GetFocusTraversableParent() {
734 return focus_traversable_parent_; 768 return focus_traversable_parent_;
735 } 769 }
736 770
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 previous_cursor_ = NULL; 952 previous_cursor_ = NULL;
919 } 953 }
920 #elif defined(OS_LINUX) 954 #elif defined(OS_LINUX)
921 gdk_window_set_cursor(GetWidget()->GetNativeView()->window, cursor); 955 gdk_window_set_cursor(GetWidget()->GetNativeView()->window, cursor);
922 if (cursor) 956 if (cursor)
923 gdk_cursor_destroy(cursor); 957 gdk_cursor_destroy(cursor);
924 #endif 958 #endif
925 } 959 }
926 960
927 } // namespace views 961 } // namespace views
OLDNEW
« no previous file with comments | « views/widget/root_view.h ('k') | views/widget/widget_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698