app_list_controller.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/app_list_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ash/ash_switches.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/launcher/launcher.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/root_window_controller.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shelf/shelf_layout_manager.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_delegate.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_window_ids.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/property_util.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/app_list_constants.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/app_list/pagination_model.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/app_list/views/app_list_view.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/focus_client.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/transform_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Duration for show/hide animation in milliseconds.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kAnimationDurationMs = 200;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Offset in pixels to animation away/towards the launcher.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kAnimationOffset = 8;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The maximum shift in pixels when over-scroll happens.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxOverScrollShift = 48;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::Layer* GetLayer(views::Widget* widget) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return widget->GetNativeView()->layer();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets arrow location based on shelf alignment.
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)views::BubbleBorder::Arrow GetBubbleArrow(aura::Window* window) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(Shell::HasInstance());
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ShelfLayoutManager::ForLauncher(window)->
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SelectValueForShelfAlignment(
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::BOTTOM_CENTER,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::LEFT_CENTER,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::RIGHT_CENTER,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          views::BubbleBorder::TOP_CENTER);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Offset given |rect| towards shelf.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect OffsetTowardsShelf(const gfx::Rect& rect, views::Widget* widget) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(Shell::HasInstance());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShelfAlignment shelf_alignment = Shell::GetInstance()->GetShelfAlignment(
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      widget->GetNativeView()->GetRootWindow());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect offseted(rect);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (shelf_alignment) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SHELF_ALIGNMENT_BOTTOM:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offseted.Offset(0, kAnimationOffset);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SHELF_ALIGNMENT_LEFT:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offseted.Offset(-kAnimationOffset, 0);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SHELF_ALIGNMENT_RIGHT:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offseted.Offset(kAnimationOffset, 0);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SHELF_ALIGNMENT_TOP:
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      offseted.Offset(0, -kAnimationOffset);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return offseted;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, public:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppListController::AppListController()
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pagination_model_(new app_list::PaginationModel),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_visible_(false),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view_(NULL),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      should_snap_back_(false) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shell::GetInstance()->AddShellObserver(this);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pagination_model_->AddObserver(this);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AppListController::~AppListController() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensures app list view goes before the controller since pagination model
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lives in the controller and app list view would access it on destruction.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_ && view_->GetWidget())
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->GetWidget()->CloseNow();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shell::GetInstance()->RemoveShellObserver(this);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pagination_model_->RemoveObserver(this);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListController::SetVisible(bool visible, aura::Window* window) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (visible == is_visible_)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_visible_ = visible;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // App list needs to know the new shelf layout in order to calculate its
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UI layout when AppListView visibility changes.
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdateAutoHideState();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleAnimation();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_visible_) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // AppListModel and AppListViewDelegate are owned by AppListView. They
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // will be released with AppListView on close.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_list::AppListView* view = new app_list::AppListView(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Shell::GetInstance()->delegate()->CreateAppListViewDelegate());
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::Window* container = GetRootWindowController(window->GetRootWindow())->
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetContainer(kShellWindowId_AppListContainer);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view->InitAsBubble(
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        container,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pagination_model_.get(),
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Launcher::ForWindow(container)->GetAppListButtonView(),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gfx::Point(),
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GetBubbleArrow(container),
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        true /* border_accepts_events */);
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (ash::switches::UseAlternateShelfLayout())
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      view->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetView(view);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AppListController::IsVisible() const {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return view_ && view_->GetWidget()->IsVisible();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)aura::Window* AppListController::GetWindow() {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return is_visible_ && view_ ? view_->GetWidget()->GetNativeWindow() : NULL;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void AppListController::SetDragAndDropHostOfCurrentAppList(
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    app_list::ApplicationDragAndDropHost* drag_and_drop_host) {
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (view_ && is_visible_)
148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, private:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::SetView(app_list::AppListView* view) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(view_ == NULL);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(is_visible_);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  view_ = view;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget* widget = view_->GetWidget();
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  widget->AddObserver(this);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetInstance()->AddPreTargetHandler(this);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Launcher::ForWindow(widget->GetNativeWindow())->AddIconObserver(this);
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  widget->GetNativeView()->GetRootWindow()->AddObserver(this);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::client::GetFocusClient(widget->GetNativeView())->AddObserver(this);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  view_->ShowWhenReady();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::ResetView() {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!view_)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Widget* widget = view_->GetWidget();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  widget->RemoveObserver(this);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetLayer(widget)->GetAnimator()->RemoveObserver(this);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Shell::GetInstance()->RemovePreTargetHandler(this);
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Launcher::ForWindow(widget->GetNativeWindow())->RemoveIconObserver(this);
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  widget->GetNativeView()->GetRootWindow()->RemoveObserver(this);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::client::GetFocusClient(widget->GetNativeView())->RemoveObserver(this);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_ = NULL;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::ScheduleAnimation() {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop observing previous animation.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopObservingImplicitAnimations();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Widget* widget = view_->GetWidget();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::Layer* layer = GetLayer(widget);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layer->GetAnimator()->StopAnimating();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect target_bounds;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_visible_) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_bounds = widget->GetWindowBoundsInScreen();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    widget->SetBounds(OffsetTowardsShelf(target_bounds, widget));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    target_bounds = OffsetTowardsShelf(widget->GetWindowBoundsInScreen(),
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       widget);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  animation.SetTransitionDuration(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          is_visible_ ? 0 : kAnimationDurationMs));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  animation.AddObserver(this);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layer->SetOpacity(is_visible_ ? 1.0 : 0.0);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  widget->SetBounds(target_bounds);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListController::ProcessLocatedEvent(ui::LocatedEvent* event) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the event happened on a menu, then the event should not close the app
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // list.
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* target = static_cast<aura::Window*>(event->target());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RootWindowController* root_controller =
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetRootWindowController(target->GetRootWindow());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (root_controller) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::Window* menu_container = root_controller->GetContainer(
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ash::internal::kShellWindowId_MenuContainer);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (menu_container->Contains(target))
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_ && is_visible_) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::Window* window = view_->GetWidget()->GetNativeView();
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Point window_local_point(event->root_location());
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::Window::ConvertPointToTarget(window->GetRootWindow(),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       window,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &window_local_point);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use HitTest to respect the hit test mask of the bubble.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!window->HitTest(window_local_point))
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SetVisible(false, window);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::UpdateBounds() {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_ && is_visible_)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->UpdateBounds();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, aura::EventFilter implementation:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListController::OnMouseEvent(ui::MouseEvent* event) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event->type() == ui::ET_MOUSE_PRESSED)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProcessLocatedEvent(event);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListController::OnGestureEvent(ui::GestureEvent* event) {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event->type() == ui::ET_GESTURE_TAP_DOWN)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProcessLocatedEvent(event);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController,  aura::FocusObserver implementation:
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListController::OnWindowFocused(aura::Window* gained_focus,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        aura::Window* lost_focus) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (gained_focus && view_ && is_visible_) {
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::Window* applist_container =
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetRootWindowController(gained_focus->GetRootWindow())->GetContainer(
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            kShellWindowId_AppListContainer);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (gained_focus->parent() != applist_container)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SetVisible(false, gained_focus);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// AppListController,  aura::WindowObserver implementation:
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void AppListController::OnWindowBoundsChanged(aura::Window* root,
2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                              const gfx::Rect& old_bounds,
2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                              const gfx::Rect& new_bounds) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateBounds();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, ui::ImplicitAnimationObserver implementation:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::OnImplicitAnimationsCompleted() {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_visible_ )
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->GetWidget()->Activate();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->GetWidget()->Close();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, views::WidgetObserver implementation:
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListController::OnWidgetDestroying(views::Widget* widget) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(view_->GetWidget() == widget);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_visible_)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetVisible(false, widget->GetNativeView());
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetView();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, ShellObserver implementation:
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppListController::OnShelfAlignmentChanged(aura::RootWindow* root_window) {
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (view_)
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    view_->SetBubbleArrow(GetBubbleArrow(view_->GetWidget()->GetNativeView()));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, LauncherIconObserver implementation:
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::OnLauncherIconPositionsChanged() {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateBounds();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AppListController, PaginationModelObserver implementation:
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::TotalPagesChanged() {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::SelectedPageChanged(int old_selected,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int new_selected) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppListController::TransitionChanged() {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |view_| could be NULL when app list is closed with a running transition.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!view_)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const app_list::PaginationModel::Transition& transition =
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pagination_model_->transition();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pagination_model_->is_valid_page(transition.target_page))
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::Widget* widget = view_->GetWidget();
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::LayerAnimator* widget_animator = GetLayer(widget)->GetAnimator();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pagination_model_->IsRevertingCurrentTransition()) {
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Update cached |view_bounds_| if it is the first over-scroll move and
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // widget does not have running animations.
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!should_snap_back_ && !widget_animator->is_animating())
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view_bounds_ = widget->GetWindowBoundsInScreen();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int current_page = pagination_model_->selected_page();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int dir = transition.target_page > current_page ? -1 : 1;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const double progress = 1.0 - pow(1.0 - transition.progress, 4);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int shift = kMaxOverScrollShift * progress * dir;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect shifted(view_bounds_);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shifted.set_x(shifted.x() + shift);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    widget->SetBounds(shifted);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    should_snap_back_ = true;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (should_snap_back_) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    should_snap_back_ = false;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::ScopedLayerAnimationSettings animation(widget_animator);
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        app_list::kOverscrollPageTransitionDurationMs));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    widget->SetBounds(view_bounds_);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
360