| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |