blob: 99a0a653f5cef246b6f0e6152b4c25c1e57be1a2 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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
3// found in the LICENSE file.
4
5#include "ash/wm/app_list_controller.h"
6
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01007#include "ash/ash_switches.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008#include "ash/root_window_controller.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +00009#include "ash/screen_util.h"
10#include "ash/shelf/shelf.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011#include "ash/shelf/shelf_layout_manager.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "ash/shell.h"
13#include "ash/shell_delegate.h"
14#include "ash/shell_window_ids.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010015#include "base/command_line.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000016#include "ui/app_list/app_list_constants.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000017#include "ui/app_list/app_list_switches.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000018#include "ui/app_list/pagination_model.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000019#include "ui/app_list/views/app_list_view.h"
20#include "ui/aura/client/focus_client.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021#include "ui/aura/window.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000022#include "ui/aura/window_event_dispatcher.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000023#include "ui/compositor/layer.h"
24#include "ui/compositor/scoped_layer_animation_settings.h"
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +010025#include "ui/events/event.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000026#include "ui/gfx/transform_util.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010027#include "ui/keyboard/keyboard_controller.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000028#include "ui/views/widget/widget.h"
29
30namespace ash {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000031namespace {
32
33// Duration for show/hide animation in milliseconds.
34const int kAnimationDurationMs = 200;
35
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000036// Offset in pixels to animation away/towards the shelf.
Torne (Richard Coles)58218062012-11-14 11:43:16 +000037const int kAnimationOffset = 8;
38
Torne (Richard Coles)58218062012-11-14 11:43:16 +000039// The maximum shift in pixels when over-scroll happens.
40const int kMaxOverScrollShift = 48;
41
Ben Murdochbbcdd452013-07-25 10:06:34 +010042// The minimal anchor position offset to make sure that the bubble is still on
43// the screen with 8 pixels spacing on the left / right. This constant is a
44// result of minimal bubble arrow sizes and offsets.
Ben Murdoch558790d2013-07-30 15:19:42 +010045const int kMinimalAnchorPositionOffset = 57;
Ben Murdochbbcdd452013-07-25 10:06:34 +010046
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010047// The minimal margin (in pixels) around the app list when in centered mode.
48const int kMinimalCenteredAppListMargin = 10;
49
Torne (Richard Coles)58218062012-11-14 11:43:16 +000050ui::Layer* GetLayer(views::Widget* widget) {
51 return widget->GetNativeView()->layer();
52}
53
54// Gets arrow location based on shelf alignment.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010055views::BubbleBorder::Arrow GetBubbleArrow(aura::Window* window) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000056 DCHECK(Shell::HasInstance());
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000057 return ShelfLayoutManager::ForShelf(window)->
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000058 SelectValueForShelfAlignment(
59 views::BubbleBorder::BOTTOM_CENTER,
60 views::BubbleBorder::LEFT_CENTER,
61 views::BubbleBorder::RIGHT_CENTER,
62 views::BubbleBorder::TOP_CENTER);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000063}
64
65// Offset given |rect| towards shelf.
66gfx::Rect OffsetTowardsShelf(const gfx::Rect& rect, views::Widget* widget) {
67 DCHECK(Shell::HasInstance());
68 ShelfAlignment shelf_alignment = Shell::GetInstance()->GetShelfAlignment(
69 widget->GetNativeView()->GetRootWindow());
70 gfx::Rect offseted(rect);
71 switch (shelf_alignment) {
72 case SHELF_ALIGNMENT_BOTTOM:
73 offseted.Offset(0, kAnimationOffset);
74 break;
75 case SHELF_ALIGNMENT_LEFT:
76 offseted.Offset(-kAnimationOffset, 0);
77 break;
78 case SHELF_ALIGNMENT_RIGHT:
79 offseted.Offset(kAnimationOffset, 0);
80 break;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000081 case SHELF_ALIGNMENT_TOP:
82 offseted.Offset(0, -kAnimationOffset);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000083 break;
84 }
85
86 return offseted;
87}
88
Torne (Richard Coles)58537e22013-09-12 12:10:22 +010089// Using |button_bounds|, determine the anchor offset so that the bubble gets
90// shown above the shelf (used for the alternate shelf theme).
91gfx::Vector2d GetAnchorPositionOffsetToShelf(
Ben Murdochbbcdd452013-07-25 10:06:34 +010092 const gfx::Rect& button_bounds, views::Widget* widget) {
93 DCHECK(Shell::HasInstance());
94 ShelfAlignment shelf_alignment = Shell::GetInstance()->GetShelfAlignment(
95 widget->GetNativeView()->GetRootWindow());
96 gfx::Point anchor(button_bounds.CenterPoint());
97 switch (shelf_alignment) {
98 case SHELF_ALIGNMENT_TOP:
99 case SHELF_ALIGNMENT_BOTTOM:
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100100 if (base::i18n::IsRTL()) {
101 int screen_width = widget->GetWorkAreaBoundsInScreen().width();
102 return gfx::Vector2d(
103 std::min(screen_width - kMinimalAnchorPositionOffset - anchor.x(),
104 0), 0);
Ben Murdochbbcdd452013-07-25 10:06:34 +0100105 }
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100106 return gfx::Vector2d(
107 std::max(kMinimalAnchorPositionOffset - anchor.x(), 0), 0);
Ben Murdochbbcdd452013-07-25 10:06:34 +0100108 case SHELF_ALIGNMENT_LEFT:
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100109 return gfx::Vector2d(
110 0, std::max(kMinimalAnchorPositionOffset - anchor.y(), 0));
Ben Murdochbbcdd452013-07-25 10:06:34 +0100111 case SHELF_ALIGNMENT_RIGHT:
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100112 return gfx::Vector2d(
113 0, std::max(kMinimalAnchorPositionOffset - anchor.y(), 0));
114 default:
115 NOTREACHED();
116 return gfx::Vector2d();
Ben Murdochbbcdd452013-07-25 10:06:34 +0100117 }
Ben Murdochbbcdd452013-07-25 10:06:34 +0100118}
119
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100120// Gets the point at the center of the display that a particular view is on.
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100121// This calculation excludes the virtual keyboard area. If the height of the
122// display area is less than |minimum_height|, its bottom will be extended to
123// that height (so that the app list never starts above the top of the screen).
124gfx::Point GetCenterOfDisplayForView(const views::View* view,
125 int minimum_height) {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100126 gfx::Rect bounds = Shell::GetScreen()->GetDisplayNearestWindow(
127 view->GetWidget()->GetNativeView()).bounds();
128
129 // If the virtual keyboard is active, subtract it from the display bounds, so
130 // that the app list is centered in the non-keyboard area of the display.
131 // (Note that work_area excludes the keyboard, but it doesn't get updated
132 // until after this function is called.)
133 keyboard::KeyboardController* keyboard_controller =
134 keyboard::KeyboardController::GetInstance();
135 if (keyboard_controller && keyboard_controller->keyboard_visible())
136 bounds.Subtract(keyboard_controller->current_keyboard_bounds());
137
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100138 // Apply the |minimum_height|.
139 if (bounds.height() < minimum_height)
140 bounds.set_height(minimum_height);
141
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100142 return bounds.CenterPoint();
143}
144
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100145// Gets the minimum height of the rectangle to center the app list in.
146int GetMinimumBoundsHeightForAppList(const app_list::AppListView* app_list) {
147 return app_list->bounds().height() + 2 * kMinimalCenteredAppListMargin;
148}
149
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000150} // namespace
151
152////////////////////////////////////////////////////////////////////////////////
153// AppListController, public:
154
155AppListController::AppListController()
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100156 : is_visible_(false),
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100157 is_centered_(false),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000158 view_(NULL),
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100159 current_apps_page_(-1),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000160 should_snap_back_(false) {
161 Shell::GetInstance()->AddShellObserver(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000162}
163
164AppListController::~AppListController() {
165 // Ensures app list view goes before the controller since pagination model
166 // lives in the controller and app list view would access it on destruction.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100167 if (view_) {
168 view_->GetAppsPaginationModel()->RemoveObserver(this);
169 if (view_->GetWidget())
170 view_->GetWidget()->CloseNow();
171 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000172
173 Shell::GetInstance()->RemoveShellObserver(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000174}
175
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000176void AppListController::SetVisible(bool visible, aura::Window* window) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000177 if (visible == is_visible_)
178 return;
179
180 is_visible_ = visible;
181
182 // App list needs to know the new shelf layout in order to calculate its
183 // UI layout when AppListView visibility changes.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000184 Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
185 UpdateAutoHideState();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000186
187 if (view_) {
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100188 // Our widget is currently active. When the animation completes we'll hide
189 // the widget, changing activation. If a menu is shown before the animation
190 // completes then the activation change triggers the menu to close. By
191 // deactivating now we ensure there is no activation change when the
192 // animation completes and any menus stay open.
193 if (!visible)
194 view_->GetWidget()->Deactivate();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000195 ScheduleAnimation();
196 } else if (is_visible_) {
197 // AppListModel and AppListViewDelegate are owned by AppListView. They
198 // will be released with AppListView on close.
199 app_list::AppListView* view = new app_list::AppListView(
200 Shell::GetInstance()->delegate()->CreateAppListViewDelegate());
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000201 aura::Window* root_window = window->GetRootWindow();
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100202 aura::Window* container = GetRootWindowController(root_window)->
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000203 GetContainer(kShellWindowId_AppListContainer);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100204 views::View* applist_button =
205 Shelf::ForWindow(container)->GetAppListButtonView();
206 is_centered_ = view->ShouldCenterWindow();
207 if (is_centered_) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100208 // Note: We can't center the app list until we have its dimensions, so we
209 // init at (0, 0) and then reset its anchor point.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100210 view->InitAsBubbleAtFixedLocation(container,
211 current_apps_page_,
212 gfx::Point(),
213 views::BubbleBorder::FLOAT,
214 true /* border_accepts_events */);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100215 // The experimental app list is centered over the display of the app list
216 // button that was pressed (if triggered via keyboard, this is the display
217 // with the currently focused window).
218 view->SetAnchorPoint(GetCenterOfDisplayForView(
219 applist_button, GetMinimumBoundsHeightForAppList(view)));
Ben Murdocha02191e2014-04-16 11:17:03 +0100220 } else {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100221 gfx::Rect applist_button_bounds = applist_button->GetBoundsInScreen();
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100222 // We need the location of the button within the local screen.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000223 applist_button_bounds = ScreenUtil::ConvertRectFromScreen(
Torne (Richard Coles)d0247b12013-09-19 22:36:51 +0100224 root_window,
225 applist_button_bounds);
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100226 view->InitAsBubbleAttachedToAnchor(
Ben Murdocheb525c52013-07-10 11:40:50 +0100227 container,
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100228 current_apps_page_,
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000229 Shelf::ForWindow(container)->GetAppListButtonView(),
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100230 GetAnchorPositionOffsetToShelf(
231 applist_button_bounds,
232 Shelf::ForWindow(container)->GetAppListButtonView()->GetWidget()),
Ben Murdocheb525c52013-07-10 11:40:50 +0100233 GetBubbleArrow(container),
234 true /* border_accepts_events */);
Ben Murdochbbcdd452013-07-25 10:06:34 +0100235 view->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
Ben Murdocheb525c52013-07-10 11:40:50 +0100236 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000237 SetView(view);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100238 // By setting us as DnD recipient, the app list knows that we can
239 // handle items.
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000240 SetDragAndDropHostOfCurrentAppList(
241 Shelf::ForWindow(window)->GetDragAndDropHostForAppList());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000242 }
Torne (Richard Coles)58537e22013-09-12 12:10:22 +0100243 // Update applist button status when app list visibility is changed.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000244 Shelf::ForWindow(window)->GetAppListButtonView()->SchedulePaint();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000245}
246
247bool AppListController::IsVisible() const {
248 return view_ && view_->GetWidget()->IsVisible();
249}
250
251aura::Window* AppListController::GetWindow() {
252 return is_visible_ && view_ ? view_->GetWidget()->GetNativeWindow() : NULL;
253}
254
Ben Murdochbb1529c2013-08-08 10:24:53 +0100255////////////////////////////////////////////////////////////////////////////////
256// AppListController, private:
257
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100258void AppListController::SetDragAndDropHostOfCurrentAppList(
259 app_list::ApplicationDragAndDropHost* drag_and_drop_host) {
260 if (view_ && is_visible_)
261 view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
262}
263
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000264void AppListController::SetView(app_list::AppListView* view) {
265 DCHECK(view_ == NULL);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000266 DCHECK(is_visible_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000267
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000268 view_ = view;
269 views::Widget* widget = view_->GetWidget();
270 widget->AddObserver(this);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100271 keyboard::KeyboardController* keyboard_controller =
272 keyboard::KeyboardController::GetInstance();
273 if (keyboard_controller)
274 keyboard_controller->AddObserver(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000275 Shell::GetInstance()->AddPreTargetHandler(this);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000276 Shelf::ForWindow(widget->GetNativeWindow())->AddIconObserver(this);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100277 widget->GetNativeView()->GetRootWindow()->AddObserver(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000278 aura::client::GetFocusClient(widget->GetNativeView())->AddObserver(this);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000279
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100280 view_->GetAppsPaginationModel()->AddObserver(this);
281
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000282 view_->ShowWhenReady();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000283}
284
285void AppListController::ResetView() {
286 if (!view_)
287 return;
288
289 views::Widget* widget = view_->GetWidget();
290 widget->RemoveObserver(this);
291 GetLayer(widget)->GetAnimator()->RemoveObserver(this);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100292 keyboard::KeyboardController* keyboard_controller =
293 keyboard::KeyboardController::GetInstance();
294 if (keyboard_controller)
295 keyboard_controller->RemoveObserver(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000296 Shell::GetInstance()->RemovePreTargetHandler(this);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000297 Shelf::ForWindow(widget->GetNativeWindow())->RemoveIconObserver(this);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100298 widget->GetNativeView()->GetRootWindow()->RemoveObserver(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000299 aura::client::GetFocusClient(widget->GetNativeView())->RemoveObserver(this);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100300
301 view_->GetAppsPaginationModel()->RemoveObserver(this);
302
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000303 view_ = NULL;
304}
305
306void AppListController::ScheduleAnimation() {
307 // Stop observing previous animation.
308 StopObservingImplicitAnimations();
309
310 views::Widget* widget = view_->GetWidget();
311 ui::Layer* layer = GetLayer(widget);
312 layer->GetAnimator()->StopAnimating();
313
314 gfx::Rect target_bounds;
315 if (is_visible_) {
316 target_bounds = widget->GetWindowBoundsInScreen();
317 widget->SetBounds(OffsetTowardsShelf(target_bounds, widget));
318 } else {
319 target_bounds = OffsetTowardsShelf(widget->GetWindowBoundsInScreen(),
320 widget);
321 }
322
323 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator());
324 animation.SetTransitionDuration(
325 base::TimeDelta::FromMilliseconds(
326 is_visible_ ? 0 : kAnimationDurationMs));
327 animation.AddObserver(this);
328
329 layer->SetOpacity(is_visible_ ? 1.0 : 0.0);
330 widget->SetBounds(target_bounds);
331}
332
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000333void AppListController::ProcessLocatedEvent(ui::LocatedEvent* event) {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000334 if (!view_ || !is_visible_)
335 return;
336
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000337 // If the event happened on a menu, then the event should not close the app
338 // list.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000339 aura::Window* target = static_cast<aura::Window*>(event->target());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000340 if (target) {
341 RootWindowController* root_controller =
342 GetRootWindowController(target->GetRootWindow());
343 if (root_controller) {
Ben Murdochc5cede92014-04-10 11:22:14 +0100344 aura::Window* menu_container =
345 root_controller->GetContainer(kShellWindowId_MenuContainer);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000346 if (menu_container->Contains(target))
347 return;
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000348 aura::Window* keyboard_container = root_controller->GetContainer(
Ben Murdochc5cede92014-04-10 11:22:14 +0100349 kShellWindowId_VirtualKeyboardContainer);
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000350 if (keyboard_container->Contains(target))
351 return;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000352 }
353 }
354
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100355 aura::Window* window = view_->GetWidget()->GetNativeView()->parent();
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000356 if (!window->Contains(target))
357 SetVisible(false, window);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000358}
359
360void AppListController::UpdateBounds() {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100361 if (!view_ || !is_visible_)
362 return;
363
364 view_->UpdateBounds();
365
366 if (is_centered_)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100367 view_->SetAnchorPoint(GetCenterOfDisplayForView(
368 view_, GetMinimumBoundsHeightForAppList(view_)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000369}
370
371////////////////////////////////////////////////////////////////////////////////
372// AppListController, aura::EventFilter implementation:
373
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000374void AppListController::OnMouseEvent(ui::MouseEvent* event) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000375 if (event->type() == ui::ET_MOUSE_PRESSED)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000376 ProcessLocatedEvent(event);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000377}
378
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000379void AppListController::OnGestureEvent(ui::GestureEvent* event) {
380 if (event->type() == ui::ET_GESTURE_TAP_DOWN)
381 ProcessLocatedEvent(event);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000382}
383
384////////////////////////////////////////////////////////////////////////////////
385// AppListController, aura::FocusObserver implementation:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000386
387void AppListController::OnWindowFocused(aura::Window* gained_focus,
388 aura::Window* lost_focus) {
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100389 if (view_ && is_visible_) {
390 aura::Window* applist_window = view_->GetWidget()->GetNativeView();
391 aura::Window* applist_container = applist_window->parent();
392
393 if (applist_container->Contains(lost_focus) &&
394 (!gained_focus || !applist_container->Contains(gained_focus))) {
395 SetVisible(false, applist_window);
396 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000397 }
398}
399
400////////////////////////////////////////////////////////////////////////////////
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100401// AppListController, aura::WindowObserver implementation:
402void AppListController::OnWindowBoundsChanged(aura::Window* root,
403 const gfx::Rect& old_bounds,
404 const gfx::Rect& new_bounds) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000405 UpdateBounds();
406}
407
408////////////////////////////////////////////////////////////////////////////////
409// AppListController, ui::ImplicitAnimationObserver implementation:
410
411void AppListController::OnImplicitAnimationsCompleted() {
412 if (is_visible_ )
413 view_->GetWidget()->Activate();
414 else
415 view_->GetWidget()->Close();
416}
417
418////////////////////////////////////////////////////////////////////////////////
419// AppListController, views::WidgetObserver implementation:
420
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000421void AppListController::OnWidgetDestroying(views::Widget* widget) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000422 DCHECK(view_->GetWidget() == widget);
423 if (is_visible_)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000424 SetVisible(false, widget->GetNativeView());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000425 ResetView();
426}
427
428////////////////////////////////////////////////////////////////////////////////
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100429// AppListController, keyboard::KeyboardControllerObserver implementation:
430
431void AppListController::OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) {
432 UpdateBounds();
433}
434
435////////////////////////////////////////////////////////////////////////////////
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000436// AppListController, ShellObserver implementation:
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000437void AppListController::OnShelfAlignmentChanged(aura::Window* root_window) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100438 if (view_)
439 view_->SetBubbleArrow(GetBubbleArrow(view_->GetWidget()->GetNativeView()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000440}
441
442////////////////////////////////////////////////////////////////////////////////
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000443// AppListController, ShelfIconObserver implementation:
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000444
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000445void AppListController::OnShelfIconPositionsChanged() {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000446 UpdateBounds();
447}
448
449////////////////////////////////////////////////////////////////////////////////
450// AppListController, PaginationModelObserver implementation:
451
452void AppListController::TotalPagesChanged() {
453}
454
455void AppListController::SelectedPageChanged(int old_selected,
456 int new_selected) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100457 current_apps_page_ = new_selected;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000458}
459
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100460void AppListController::TransitionStarted() {
461}
462
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000463void AppListController::TransitionChanged() {
464 // |view_| could be NULL when app list is closed with a running transition.
465 if (!view_)
466 return;
467
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100468 app_list::PaginationModel* pagination_model = view_->GetAppsPaginationModel();
469
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000470 const app_list::PaginationModel::Transition& transition =
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100471 pagination_model->transition();
472 if (pagination_model->is_valid_page(transition.target_page))
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000473 return;
474
475 views::Widget* widget = view_->GetWidget();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000476 ui::LayerAnimator* widget_animator = GetLayer(widget)->GetAnimator();
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100477 if (!pagination_model->IsRevertingCurrentTransition()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000478 // Update cached |view_bounds_| if it is the first over-scroll move and
479 // widget does not have running animations.
480 if (!should_snap_back_ && !widget_animator->is_animating())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000481 view_bounds_ = widget->GetWindowBoundsInScreen();
482
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100483 const int current_page = pagination_model->selected_page();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000484 const int dir = transition.target_page > current_page ? -1 : 1;
485
486 const double progress = 1.0 - pow(1.0 - transition.progress, 4);
487 const int shift = kMaxOverScrollShift * progress * dir;
488
489 gfx::Rect shifted(view_bounds_);
490 shifted.set_x(shifted.x() + shift);
491 widget->SetBounds(shifted);
492 should_snap_back_ = true;
493 } else if (should_snap_back_) {
494 should_snap_back_ = false;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000495 ui::ScopedLayerAnimationSettings animation(widget_animator);
496 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
497 app_list::kOverscrollPageTransitionDurationMs));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000498 widget->SetBounds(view_bounds_);
499 }
500}
501
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000502} // namespace ash