| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/app_list/views/app_list_view.h" | 5 #include "ui/app_list/views/app_list_view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 #include "ui/wm/core/masked_window_targeter.h" | 48 #include "ui/wm/core/masked_window_targeter.h" |
| 49 #include "ui/wm/core/shadow_types.h" | 49 #include "ui/wm/core/shadow_types.h" |
| 50 | 50 |
| 51 namespace app_list { | 51 namespace app_list { |
| 52 | 52 |
| 53 namespace { | 53 namespace { |
| 54 | 54 |
| 55 // The margin from the edge to the speech UI. | 55 // The margin from the edge to the speech UI. |
| 56 constexpr int kSpeechUIMargin = 12; | 56 constexpr int kSpeechUIMargin = 12; |
| 57 | 57 |
| 58 // The height/width of the shelf from the bottom/side of the screen. | 58 // The height/width of the shelf. |
| 59 constexpr int kShelfSize = 48; | 59 constexpr int kShelfSize = 48; |
| 60 | 60 |
| 61 // The height of the peeking app list from the bottom of the screen. | 61 // The height of the peeking app list. |
| 62 constexpr int kPeekingAppListHeight = 320; | 62 constexpr int kPeekingAppListHeight = 320; |
| 63 | 63 |
| 64 // The height of the half app list from the bottom of the screen. | |
| 65 constexpr int kHalfAppListHeight = 561; | |
| 66 | |
| 67 // The fraction of app list height that the app list must be released at in | 64 // The fraction of app list height that the app list must be released at in |
| 68 // order to transition to the next state. | 65 // order to transition to the next state. |
| 69 constexpr int kAppListThresholdDenominator = 3; | 66 constexpr int kAppListThresholdDenominator = 3; |
| 70 | 67 |
| 71 // The velocity the app list must be dragged in order to transition to the next | 68 // The velocity the app list must be dragged in order to transition to the next |
| 72 // state, measured in DIPs/event. | 69 // state, measured in DIPs/event. |
| 73 constexpr int kAppListDragVelocityThreshold = 25; | 70 constexpr int kAppListDragVelocityThreshold = 25; |
| 74 | 71 |
| 75 // The DIP distance from the bezel that a drag event must end within to transfer | |
| 76 // the |app_list_state_|. | |
| 77 constexpr int kAppListBezelMargin = 50; | |
| 78 | |
| 79 // The opacity of the app list background. | 72 // The opacity of the app list background. |
| 80 constexpr float kAppListOpacity = 0.8; | 73 constexpr float kAppListOpacity = 0.8; |
| 81 | 74 |
| 82 // The vertical position for the appearing animation of the speech UI. | 75 // The vertical position for the appearing animation of the speech UI. |
| 83 constexpr float kSpeechUIAppearingPosition = 12; | 76 constexpr float kSpeechUIAppearingPosition = 12; |
| 84 | 77 |
| 85 // This view forwards the focus to the search box widget by providing it as a | 78 // This view forwards the focus to the search box widget by providing it as a |
| 86 // FocusTraversable when a focus search is provided. | 79 // FocusTraversable when a focus search is provided. |
| 87 class SearchBoxFocusHost : public views::View { | 80 class SearchBoxFocusHost : public views::View { |
| 88 public: | 81 public: |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 display_observer_.Add(display::Screen::GetScreen()); | 203 display_observer_.Add(display::Screen::GetScreen()); |
| 211 } | 204 } |
| 212 | 205 |
| 213 AppListView::~AppListView() { | 206 AppListView::~AppListView() { |
| 214 delegate_->GetSpeechUI()->RemoveObserver(this); | 207 delegate_->GetSpeechUI()->RemoveObserver(this); |
| 215 animation_observer_.reset(); | 208 animation_observer_.reset(); |
| 216 // Remove child views first to ensure no remaining dependencies on delegate_. | 209 // Remove child views first to ensure no remaining dependencies on delegate_. |
| 217 RemoveAllChildViews(true); | 210 RemoveAllChildViews(true); |
| 218 } | 211 } |
| 219 | 212 |
| 220 void AppListView::Initialize(gfx::NativeView parent, | 213 void AppListView::Initialize(gfx::NativeView parent, int initial_apps_page) { |
| 221 int initial_apps_page, | |
| 222 bool is_maximize_mode, | |
| 223 bool is_side_shelf) { | |
| 224 base::Time start_time = base::Time::Now(); | 214 base::Time start_time = base::Time::Now(); |
| 225 is_maximize_mode_ = is_maximize_mode; | |
| 226 is_side_shelf_ = is_side_shelf; | |
| 227 InitContents(parent, initial_apps_page); | 215 InitContents(parent, initial_apps_page); |
| 228 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); | 216 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); |
| 229 set_color(kContentsBackgroundColor); | 217 set_color(kContentsBackgroundColor); |
| 230 set_parent_window(parent); | 218 set_parent_window(parent); |
| 231 | 219 |
| 232 if (is_fullscreen_app_list_enabled_) | 220 if (is_fullscreen_app_list_enabled_) |
| 233 InitializeFullscreen(parent, initial_apps_page); | 221 InitializeFullscreen(parent, initial_apps_page); |
| 234 else | 222 else |
| 235 InitializeBubble(parent, initial_apps_page); | 223 InitializeBubble(parent, initial_apps_page); |
| 236 | 224 |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 | 505 |
| 518 void AppListView::EndDrag(const gfx::Point& location) { | 506 void AppListView::EndDrag(const gfx::Point& location) { |
| 519 // Change the app list state based on where the drag ended. If fling velocity | 507 // Change the app list state based on where the drag ended. If fling velocity |
| 520 // was over the threshold, snap to the next state in the direction of the | 508 // was over the threshold, snap to the next state in the direction of the |
| 521 // fling. | 509 // fling. |
| 522 int const new_y_position = location.y() - initial_drag_point_.y() + | 510 int const new_y_position = location.y() - initial_drag_point_.y() + |
| 523 fullscreen_widget_->GetWindowBoundsInScreen().y(); | 511 fullscreen_widget_->GetWindowBoundsInScreen().y(); |
| 524 if (std::abs(last_fling_velocity_) > kAppListDragVelocityThreshold) { | 512 if (std::abs(last_fling_velocity_) > kAppListDragVelocityThreshold) { |
| 525 // If the user releases drag with velocity over the threshold, snap to | 513 // If the user releases drag with velocity over the threshold, snap to |
| 526 // the next state, ignoring the drag release position. | 514 // the next state, ignoring the drag release position. |
| 515 if (app_list_state_ == FULLSCREEN) { |
| 516 if (last_fling_velocity_ > 0) |
| 517 SetState(PEEKING); |
| 527 | 518 |
| 528 if (last_fling_velocity_ > 0) { | |
| 529 switch (app_list_state_) { | |
| 530 case PEEKING: | |
| 531 case HALF: | |
| 532 case FULLSCREEN_SEARCH: | |
| 533 SetState(CLOSED); | |
| 534 break; | |
| 535 case FULLSCREEN_ALL_APPS: | |
| 536 SetState(is_maximize_mode_ || is_side_shelf_ ? CLOSED : PEEKING); | |
| 537 break; | |
| 538 case CLOSED: | |
| 539 NOTREACHED(); | |
| 540 break; | |
| 541 } | |
| 542 } else { | 519 } else { |
| 543 switch (app_list_state_) { | 520 SetState(last_fling_velocity_ > 0 ? CLOSED : FULLSCREEN); |
| 544 case FULLSCREEN_ALL_APPS: | |
| 545 case FULLSCREEN_SEARCH: | |
| 546 SetState(app_list_state_); | |
| 547 break; | |
| 548 case HALF: | |
| 549 SetState(FULLSCREEN_SEARCH); | |
| 550 break; | |
| 551 case PEEKING: | |
| 552 SetState(FULLSCREEN_ALL_APPS); | |
| 553 break; | |
| 554 case CLOSED: | |
| 555 NOTREACHED(); | |
| 556 break; | |
| 557 } | |
| 558 } | 521 } |
| 522 last_fling_velocity_ = 0; |
| 559 } else { | 523 } else { |
| 560 int display_height = display::Screen::GetScreen() | 524 int display_height = display::Screen::GetScreen() |
| 561 ->GetDisplayNearestView(parent_window()) | 525 ->GetDisplayNearestView(parent_window()) |
| 562 .size().height(); | 526 .work_area() |
| 563 int app_list_y_for_state = 0; | 527 .height(); |
| 564 int app_list_height = 0; | 528 int default_peeking_y = display_height + kShelfSize - kPeekingAppListHeight; |
| 565 switch (app_list_state_) { | 529 // The drag release velocity was too low, so use the release point. |
| 566 case FULLSCREEN_ALL_APPS: | 530 int app_list_snap_y = |
| 567 case FULLSCREEN_SEARCH: | 531 (app_list_state_ == FULLSCREEN) ? 0 : default_peeking_y; |
| 568 app_list_y_for_state = 0; | 532 // The DIP delta that must be exceeded for the app list to snap to the next |
| 569 app_list_height = display_height; | 533 // state. |
| 570 break; | 534 int app_list_threshold = |
| 571 case HALF: | 535 (fullscreen_widget_->GetWindowBoundsInScreen().height() + kShelfSize) / |
| 572 app_list_y_for_state = display_height - kHalfAppListHeight; | 536 kAppListThresholdDenominator; |
| 573 app_list_height = kHalfAppListHeight; | 537 app_list_threshold -= |
| 574 break; | 538 (app_list_state_ == FULLSCREEN ? 0 : kPeekingAppListHeight) / |
| 575 case PEEKING: | 539 kAppListThresholdDenominator; |
| 576 app_list_y_for_state = display_height - kPeekingAppListHeight; | |
| 577 app_list_height = kPeekingAppListHeight; | |
| 578 break; | |
| 579 case CLOSED: | |
| 580 NOTREACHED(); | |
| 581 break; | |
| 582 } | |
| 583 | 540 |
| 584 int app_list_threshold = app_list_height / kAppListThresholdDenominator; | 541 // If the user releases +/- 1/3 of |app_list_threshold|, snap to the |
| 585 int drag_delta = app_list_y_for_state - new_y_position; | 542 // next state. |
| 586 gfx::Point location_in_screen_coordinates = location; | 543 if (std::abs(app_list_snap_y - new_y_position) < app_list_threshold) { |
| 587 ConvertPointToScreen(this, &location_in_screen_coordinates); | 544 // The drag was not far enough so set the app list bounds to the target |
| 588 switch (app_list_state_) { | 545 // bounds for the current state. |
| 589 case FULLSCREEN_ALL_APPS: | 546 SetState(app_list_state_); |
| 590 if (std::abs(drag_delta) > app_list_threshold) | 547 } else if ((app_list_snap_y + app_list_threshold) < new_y_position) { |
| 591 SetState(is_maximize_mode_ || is_side_shelf_ ? CLOSED : PEEKING); | 548 // The drag was far enough to change states and was a downward drag, so |
| 592 else | 549 // set the app list bounds to the next state. |
| 593 SetState(app_list_state_); | 550 SetState(app_list_state_ == FULLSCREEN ? PEEKING : CLOSED); |
| 594 break; | 551 } else { |
| 595 case FULLSCREEN_SEARCH: | 552 // The drag was far enough to change states and was an upward drag, so |
| 596 if (std::abs(drag_delta) > app_list_threshold) | 553 // set the app list bounds to the next state. |
| 597 SetState(CLOSED); | 554 SetState(FULLSCREEN); |
| 598 else | |
| 599 SetState(app_list_state_); | |
| 600 break; | |
| 601 case HALF: | |
| 602 if (std::abs(drag_delta) > app_list_threshold) { | |
| 603 SetState(drag_delta > 0 ? FULLSCREEN_SEARCH : CLOSED); | |
| 604 } else if (location_in_screen_coordinates.y() >= | |
| 605 display_height - kAppListBezelMargin) { | |
| 606 // If the user drags to the bezel, close the app list. | |
| 607 SetState(CLOSED); | |
| 608 } else { | |
| 609 SetState(app_list_state_); | |
| 610 } | |
| 611 break; | |
| 612 case PEEKING: | |
| 613 if (std::abs(drag_delta) > app_list_threshold) { | |
| 614 SetState(drag_delta > 0 ? FULLSCREEN_ALL_APPS : CLOSED); | |
| 615 } else if (location_in_screen_coordinates.y() >= | |
| 616 display_height - kAppListBezelMargin) { | |
| 617 // If the user drags to the bezel, close the app list. | |
| 618 SetState(CLOSED); | |
| 619 } else { | |
| 620 SetState(app_list_state_); | |
| 621 } | |
| 622 break; | |
| 623 case CLOSED: | |
| 624 NOTREACHED(); | |
| 625 break; | |
| 626 } | 555 } |
| 627 } | 556 } |
| 628 } | 557 } |
| 629 | 558 |
| 630 void AppListView::SetStateFromSearchBoxView(bool search_box_is_empty) { | |
| 631 switch (app_list_state_) { | |
| 632 case PEEKING: | |
| 633 if (!search_box_is_empty) | |
| 634 SetState(HALF); | |
| 635 break; | |
| 636 case HALF: | |
| 637 if (search_box_is_empty) | |
| 638 SetState(PEEKING); | |
| 639 break; | |
| 640 case FULLSCREEN_SEARCH: | |
| 641 if (search_box_is_empty) { | |
| 642 SetState(FULLSCREEN_ALL_APPS); | |
| 643 app_list_main_view()->contents_view()->SetActiveState( | |
| 644 AppListModel::State::STATE_APPS); | |
| 645 } | |
| 646 break; | |
| 647 case FULLSCREEN_ALL_APPS: | |
| 648 if (!search_box_is_empty) | |
| 649 SetState(FULLSCREEN_SEARCH); | |
| 650 break; | |
| 651 case CLOSED: | |
| 652 NOTREACHED(); | |
| 653 break; | |
| 654 } | |
| 655 } | |
| 656 | |
| 657 void AppListView::OnMaximizeModeChanged(bool started) { | |
| 658 is_maximize_mode_ = started; | |
| 659 if (is_maximize_mode_ && !is_fullscreen()) { | |
| 660 // Set |app_list_state_| to a maximize mode friendly state. | |
| 661 SetState(app_list_state_ == PEEKING ? FULLSCREEN_ALL_APPS | |
| 662 : FULLSCREEN_SEARCH); | |
| 663 } | |
| 664 } | |
| 665 | |
| 666 void AppListView::OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, | 559 void AppListView::OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, |
| 667 views::Widget* widget) const { | 560 views::Widget* widget) const { |
| 668 if (!params->native_widget) { | 561 if (!params->native_widget) { |
| 669 views::ViewsDelegate* views_delegate = views::ViewsDelegate::GetInstance(); | 562 views::ViewsDelegate* views_delegate = views::ViewsDelegate::GetInstance(); |
| 670 if (views_delegate && !views_delegate->native_widget_factory().is_null()) { | 563 if (views_delegate && !views_delegate->native_widget_factory().is_null()) { |
| 671 params->native_widget = | 564 params->native_widget = |
| 672 views_delegate->native_widget_factory().Run(*params, widget); | 565 views_delegate->native_widget_factory().Run(*params, widget); |
| 673 } | 566 } |
| 674 } | 567 } |
| 675 // Apply a WM-provided shadow (see ui/wm/core/). | 568 // Apply a WM-provided shadow (see ui/wm/core/). |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 } | 681 } |
| 789 } | 682 } |
| 790 | 683 |
| 791 void AppListView::SchedulePaintInRect(const gfx::Rect& rect) { | 684 void AppListView::SchedulePaintInRect(const gfx::Rect& rect) { |
| 792 BubbleDialogDelegateView::SchedulePaintInRect(rect); | 685 BubbleDialogDelegateView::SchedulePaintInRect(rect); |
| 793 if (GetBubbleFrameView()) | 686 if (GetBubbleFrameView()) |
| 794 GetBubbleFrameView()->SchedulePaint(); | 687 GetBubbleFrameView()->SchedulePaint(); |
| 795 } | 688 } |
| 796 | 689 |
| 797 void AppListView::SetState(AppListState new_state) { | 690 void AppListView::SetState(AppListState new_state) { |
| 798 AppListState new_state_override = new_state; | |
| 799 if (is_side_shelf_ || is_maximize_mode_) { | |
| 800 // If side shelf or maximize mode are active, all transitions should be | |
| 801 // made to the maximize mode/side shelf friendly versions. | |
| 802 if (new_state == PEEKING) | |
| 803 new_state_override = FULLSCREEN_ALL_APPS; | |
| 804 else if (new_state == HALF) | |
| 805 new_state_override = FULLSCREEN_SEARCH; | |
| 806 } | |
| 807 | |
| 808 gfx::Rect new_widget_bounds = fullscreen_widget_->GetWindowBoundsInScreen(); | 691 gfx::Rect new_widget_bounds = fullscreen_widget_->GetWindowBoundsInScreen(); |
| 809 int display_height = display::Screen::GetScreen() | 692 switch (new_state) { |
| 810 ->GetDisplayNearestView(parent_window()) | |
| 811 .work_area() | |
| 812 .bottom(); | |
| 813 | |
| 814 switch (new_state_override) { | |
| 815 case PEEKING: { | 693 case PEEKING: { |
| 816 switch (app_list_state_) { | 694 int display_height = display::Screen::GetScreen() |
| 817 case HALF: | 695 ->GetDisplayNearestView(parent_window()) |
| 818 case FULLSCREEN_ALL_APPS: | 696 .work_area() |
| 819 case PEEKING: { | 697 .bottom(); |
| 820 int peeking_app_list_y = display_height - kPeekingAppListHeight; | 698 int default_peeking_y = |
| 821 new_widget_bounds.set_y(peeking_app_list_y); | 699 display_height + kShelfSize - kPeekingAppListHeight; |
| 822 app_list_main_view_->contents_view()->SetActiveState( | 700 new_widget_bounds.set_y(default_peeking_y); |
| 823 AppListModel::STATE_START); | |
| 824 break; | |
| 825 } | |
| 826 case FULLSCREEN_SEARCH: | |
| 827 case CLOSED: | |
| 828 NOTREACHED(); | |
| 829 break; | |
| 830 } | |
| 831 break; | 701 break; |
| 832 } | 702 } |
| 833 case HALF: | 703 case FULLSCREEN: |
| 834 switch (app_list_state_) { | |
| 835 case PEEKING: | |
| 836 case HALF: { | |
| 837 int half_app_list_y = display_height - kHalfAppListHeight; | |
| 838 new_widget_bounds.set_y(half_app_list_y); | |
| 839 break; | |
| 840 } | |
| 841 case FULLSCREEN_SEARCH: | |
| 842 case FULLSCREEN_ALL_APPS: | |
| 843 case CLOSED: | |
| 844 NOTREACHED(); | |
| 845 break; | |
| 846 } | |
| 847 break; | |
| 848 case FULLSCREEN_ALL_APPS: | |
| 849 new_widget_bounds.set_y(0); | |
| 850 app_list_main_view_->contents_view()->SetActiveState( | |
| 851 AppListModel::STATE_APPS); | |
| 852 break; | |
| 853 case FULLSCREEN_SEARCH: | |
| 854 new_widget_bounds.set_y(0); | 704 new_widget_bounds.set_y(0); |
| 855 break; | 705 break; |
| 856 case CLOSED: | 706 case CLOSED: |
| 857 app_list_main_view_->Close(); | 707 app_list_main_view_->Close(); |
| 858 delegate_->Dismiss(); | 708 delegate_->Dismiss(); |
| 859 break; | 709 break; |
| 860 } | 710 } |
| 861 fullscreen_widget_->SetBounds(new_widget_bounds); | 711 fullscreen_widget_->SetBounds(new_widget_bounds); |
| 862 app_list_state_ = new_state_override; | 712 app_list_state_ = new_state; |
| 863 } | 713 } |
| 864 | 714 |
| 865 void AppListView::OnWidgetDestroying(views::Widget* widget) { | 715 void AppListView::OnWidgetDestroying(views::Widget* widget) { |
| 866 BubbleDialogDelegateView::OnWidgetDestroying(widget); | 716 BubbleDialogDelegateView::OnWidgetDestroying(widget); |
| 867 if (delegate_ && widget == GetWidget()) | 717 if (delegate_ && widget == GetWidget()) |
| 868 delegate_->ViewClosing(); | 718 delegate_->ViewClosing(); |
| 869 } | 719 } |
| 870 | 720 |
| 871 void AppListView::OnWidgetVisibilityChanged(views::Widget* widget, | 721 void AppListView::OnWidgetVisibilityChanged(views::Widget* widget, |
| 872 bool visible) { | 722 bool visible) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 .work_area() | 807 .work_area() |
| 958 .size(); | 808 .size(); |
| 959 size.Enlarge(0, kShelfSize); | 809 size.Enlarge(0, kShelfSize); |
| 960 fullscreen_widget_->SetSize(size); | 810 fullscreen_widget_->SetSize(size); |
| 961 | 811 |
| 962 // Update the |fullscreen_widget_| bounds to accomodate the new work area. | 812 // Update the |fullscreen_widget_| bounds to accomodate the new work area. |
| 963 SetState(app_list_state_); | 813 SetState(app_list_state_); |
| 964 } | 814 } |
| 965 | 815 |
| 966 } // namespace app_list | 816 } // namespace app_list |
| OLD | NEW |