| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ash/app_list/app_list.h" | |
| 6 | |
| 7 #include "ash/app_list/app_list_view.h" | |
| 8 #include "ash/app_list/icon_cache.h" | |
| 9 #include "ash/ash_switches.h" | |
| 10 #include "ash/shell.h" | |
| 11 #include "ash/shell_delegate.h" | |
| 12 #include "ash/shell_window_ids.h" | |
| 13 #include "ash/wm/shelf_layout_manager.h" | |
| 14 #include "ash/wm/window_util.h" | |
| 15 #include "base/command_line.h" | |
| 16 #include "ui/aura/event.h" | |
| 17 #include "ui/aura/root_window.h" | |
| 18 #include "ui/aura/window.h" | |
| 19 #include "ui/compositor/layer.h" | |
| 20 #include "ui/compositor/scoped_layer_animation_settings.h" | |
| 21 #include "ui/gfx/transform_util.h" | |
| 22 | |
| 23 namespace ash { | |
| 24 namespace internal { | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 const float kContainerAnimationScaleFactor = 1.05f; | |
| 29 | |
| 30 // Duration for both default container and app list animation in milliseconds. | |
| 31 const int kAnimationDurationMs = 130; | |
| 32 | |
| 33 // Delayed time of 2nd animation in milliseconds. | |
| 34 const int kSecondAnimationStartDelay = kAnimationDurationMs - 20; | |
| 35 | |
| 36 ui::Layer* GetLayer(views::Widget* widget) { | |
| 37 return widget->GetNativeView()->layer(); | |
| 38 } | |
| 39 | |
| 40 } // namespace | |
| 41 | |
| 42 //////////////////////////////////////////////////////////////////////////////// | |
| 43 // AppList, public: | |
| 44 | |
| 45 AppList::AppList() : is_visible_(false), view_(NULL) { | |
| 46 IconCache::CreateInstance(); | |
| 47 } | |
| 48 | |
| 49 AppList::~AppList() { | |
| 50 ResetView(); | |
| 51 IconCache::DeleteInstance(); | |
| 52 } | |
| 53 | |
| 54 // static | |
| 55 bool AppList::UseAppListV2() { | |
| 56 return CommandLine::ForCurrentProcess()->HasSwitch( | |
| 57 switches::kEnableAppListV2); | |
| 58 } | |
| 59 | |
| 60 void AppList::SetVisible(bool visible) { | |
| 61 if (visible == is_visible_) | |
| 62 return; | |
| 63 | |
| 64 is_visible_ = visible; | |
| 65 | |
| 66 // App list needs to know the new shelf layout in order to calculate its | |
| 67 // UI layout when AppListView visibility changes. | |
| 68 Shell::GetInstance()->shelf()->UpdateAutoHideState(); | |
| 69 | |
| 70 if (view_) { | |
| 71 ScheduleAnimation(); | |
| 72 } else if (is_visible_) { | |
| 73 // AppListModel and AppListViewDelegate are owned by AppListView. They | |
| 74 // will be released with AppListView on close. | |
| 75 SetView(new AppListView( | |
| 76 Shell::GetInstance()->delegate()->CreateAppListViewDelegate())); | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 bool AppList::IsVisible() { | |
| 81 return view_ && view_->GetWidget()->IsVisible(); | |
| 82 } | |
| 83 | |
| 84 aura::Window* AppList::GetWindow() { | |
| 85 return is_visible_ && view_ ? view_->GetWidget()->GetNativeWindow() : NULL; | |
| 86 } | |
| 87 | |
| 88 //////////////////////////////////////////////////////////////////////////////// | |
| 89 // AppList, private: | |
| 90 | |
| 91 void AppList::SetView(AppListView* view) { | |
| 92 DCHECK(view_ == NULL); | |
| 93 | |
| 94 if (is_visible_) { | |
| 95 IconCache::GetInstance()->MarkAllEntryUnused(); | |
| 96 | |
| 97 view_ = view; | |
| 98 views::Widget* widget = view_->GetWidget(); | |
| 99 widget->AddObserver(this); | |
| 100 Shell::GetInstance()->AddRootWindowEventFilter(this); | |
| 101 widget->GetNativeView()->GetRootWindow()->AddRootWindowObserver(this); | |
| 102 | |
| 103 widget->SetOpacity(0); | |
| 104 ScheduleAnimation(); | |
| 105 | |
| 106 view_->GetWidget()->Show(); | |
| 107 } else { | |
| 108 view->GetWidget()->Close(); | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 void AppList::ResetView() { | |
| 113 if (!view_) | |
| 114 return; | |
| 115 | |
| 116 views::Widget* widget = view_->GetWidget(); | |
| 117 widget->RemoveObserver(this); | |
| 118 GetLayer(widget)->GetAnimator()->RemoveObserver(this); | |
| 119 Shell::GetInstance()->RemoveRootWindowEventFilter(this); | |
| 120 widget->GetNativeView()->GetRootWindow()->RemoveRootWindowObserver(this); | |
| 121 view_ = NULL; | |
| 122 | |
| 123 IconCache::GetInstance()->PurgeAllUnused(); | |
| 124 } | |
| 125 | |
| 126 void AppList::ScheduleAnimation() { | |
| 127 second_animation_timer_.Stop(); | |
| 128 | |
| 129 // Stop observing previous animation. | |
| 130 StopObservingImplicitAnimations(); | |
| 131 | |
| 132 ScheduleDimmingAnimation(); | |
| 133 | |
| 134 // No browser window fading and app list secondary animation for v2. | |
| 135 if (UseAppListV2()) | |
| 136 return; | |
| 137 | |
| 138 if (is_visible_) { | |
| 139 ScheduleBrowserWindowsAnimation(); | |
| 140 second_animation_timer_.Start( | |
| 141 FROM_HERE, | |
| 142 base::TimeDelta::FromMilliseconds(kSecondAnimationStartDelay), | |
| 143 this, | |
| 144 &AppList::ScheduleAppListAnimation); | |
| 145 } else { | |
| 146 ScheduleAppListAnimation(); | |
| 147 second_animation_timer_.Start( | |
| 148 FROM_HERE, | |
| 149 base::TimeDelta::FromMilliseconds(kSecondAnimationStartDelay), | |
| 150 this, | |
| 151 &AppList::ScheduleBrowserWindowsAnimation); | |
| 152 } | |
| 153 | |
| 154 } | |
| 155 | |
| 156 void AppList::ScheduleBrowserWindowsAnimationForContainer( | |
| 157 aura::Window* container) { | |
| 158 DCHECK(container); | |
| 159 ui::Layer* layer = container->layer(); | |
| 160 layer->GetAnimator()->StopAnimating(); | |
| 161 | |
| 162 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); | |
| 163 animation.SetTransitionDuration( | |
| 164 base::TimeDelta::FromMilliseconds(kAnimationDurationMs)); | |
| 165 animation.SetTweenType( | |
| 166 is_visible_ ? ui::Tween::EASE_IN : ui::Tween::EASE_OUT); | |
| 167 | |
| 168 layer->SetOpacity(is_visible_ ? 0.0 : 1.0); | |
| 169 layer->SetTransform(is_visible_ ? | |
| 170 ui::GetScaleTransform( | |
| 171 gfx::Point(layer->bounds().width() / 2, | |
| 172 layer->bounds().height() / 2), | |
| 173 kContainerAnimationScaleFactor) : | |
| 174 ui::Transform()); | |
| 175 } | |
| 176 | |
| 177 void AppList::ScheduleBrowserWindowsAnimation() { | |
| 178 // Note: containers could be NULL during Shell shutdown. | |
| 179 aura::Window* default_container = Shell::GetInstance()->GetContainer( | |
| 180 internal::kShellWindowId_DefaultContainer); | |
| 181 if (default_container) | |
| 182 ScheduleBrowserWindowsAnimationForContainer(default_container); | |
| 183 aura::Window* always_on_top_container = Shell::GetInstance()->GetContainer( | |
| 184 internal::kShellWindowId_AlwaysOnTopContainer); | |
| 185 if (always_on_top_container) | |
| 186 ScheduleBrowserWindowsAnimationForContainer(always_on_top_container); | |
| 187 } | |
| 188 | |
| 189 void AppList::ScheduleDimmingAnimation() { | |
| 190 ui::Layer* layer = GetLayer(view_->GetWidget()); | |
| 191 layer->GetAnimator()->StopAnimating(); | |
| 192 | |
| 193 int duration = UseAppListV2() ? | |
| 194 kAnimationDurationMs : 2 * kAnimationDurationMs; | |
| 195 | |
| 196 ui::ScopedLayerAnimationSettings animation(layer->GetAnimator()); | |
| 197 animation.SetTransitionDuration( | |
| 198 base::TimeDelta::FromMilliseconds(duration)); | |
| 199 animation.AddObserver(this); | |
| 200 | |
| 201 layer->SetOpacity(is_visible_ ? 1.0 : 0.0); | |
| 202 } | |
| 203 | |
| 204 void AppList::ScheduleAppListAnimation() { | |
| 205 if (is_visible_) | |
| 206 view_->AnimateShow(kAnimationDurationMs); | |
| 207 else | |
| 208 view_->AnimateHide(kAnimationDurationMs); | |
| 209 } | |
| 210 | |
| 211 //////////////////////////////////////////////////////////////////////////////// | |
| 212 // AppList, aura::EventFilter implementation: | |
| 213 | |
| 214 bool AppList::PreHandleKeyEvent(aura::Window* target, | |
| 215 aura::KeyEvent* event) { | |
| 216 return false; | |
| 217 } | |
| 218 | |
| 219 bool AppList::PreHandleMouseEvent(aura::Window* target, | |
| 220 aura::MouseEvent* event) { | |
| 221 if (view_ && is_visible_ && event->type() == ui::ET_MOUSE_PRESSED) { | |
| 222 views::Widget* widget = view_->GetWidget(); | |
| 223 aura::MouseEvent translated(*event, target, widget->GetNativeView()); | |
| 224 if (!widget->GetNativeView()->ContainsPoint(translated.location())) | |
| 225 SetVisible(false); | |
| 226 } | |
| 227 return false; | |
| 228 } | |
| 229 | |
| 230 ui::TouchStatus AppList::PreHandleTouchEvent(aura::Window* target, | |
| 231 aura::TouchEvent* event) { | |
| 232 return ui::TOUCH_STATUS_UNKNOWN; | |
| 233 } | |
| 234 | |
| 235 ui::GestureStatus AppList::PreHandleGestureEvent( | |
| 236 aura::Window* target, | |
| 237 aura::GestureEvent* event) { | |
| 238 return ui::GESTURE_STATUS_UNKNOWN; | |
| 239 } | |
| 240 | |
| 241 //////////////////////////////////////////////////////////////////////////////// | |
| 242 // AppList, ura::RootWindowObserver implementation: | |
| 243 void AppList::OnRootWindowResized(const aura::RootWindow* root, | |
| 244 const gfx::Size& old_size) { | |
| 245 if (view_ && is_visible_) | |
| 246 view_->UpdateBounds(); | |
| 247 } | |
| 248 | |
| 249 void AppList::OnWindowFocused(aura::Window* window) { | |
| 250 if (view_ && is_visible_) { | |
| 251 aura::Window* applist_container = Shell::GetInstance()->GetContainer( | |
| 252 internal::kShellWindowId_AppListContainer); | |
| 253 aura::Window* bubble_container = Shell::GetInstance()->GetContainer( | |
| 254 internal::kShellWindowId_SettingBubbleContainer); | |
| 255 if (window->parent() != applist_container && | |
| 256 window->parent() != bubble_container) { | |
| 257 SetVisible(false); | |
| 258 } | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 //////////////////////////////////////////////////////////////////////////////// | |
| 263 // AppList, ui::ImplicitAnimationObserver implementation: | |
| 264 | |
| 265 void AppList::OnImplicitAnimationsCompleted() { | |
| 266 if (is_visible_ ) | |
| 267 view_->GetWidget()->Activate(); | |
| 268 else | |
| 269 view_->GetWidget()->Close(); | |
| 270 } | |
| 271 | |
| 272 //////////////////////////////////////////////////////////////////////////////// | |
| 273 // AppList, views::Widget::Observer implementation: | |
| 274 | |
| 275 void AppList::OnWidgetClosing(views::Widget* widget) { | |
| 276 DCHECK(view_->GetWidget() == widget); | |
| 277 if (is_visible_) | |
| 278 SetVisible(false); | |
| 279 ResetView(); | |
| 280 } | |
| 281 | |
| 282 } // namespace internal | |
| 283 } // namespace ash | |
| OLD | NEW |