blob: 455986f2fbfd73594447918e110c724386a63f89 [file] [log] [blame]
[email protected]1b62b892012-01-17 17:08:151// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ae18b9112011-11-07 16:59:132// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]7634f962011-12-23 21:35:525#include "ash/wm/shelf_layout_manager.h"
[email protected]ae18b9112011-11-07 16:59:136
[email protected]c2d58b42012-05-30 08:11:297#include <algorithm>
8
[email protected]7634f962011-12-23 21:35:529#include "ash/launcher/launcher.h"
[email protected]1a2145b2012-03-13 21:09:1710#include "ash/screen_ash.h"
[email protected]b65bdda2011-12-23 23:35:3111#include "ash/shell.h"
[email protected]c758fbf2012-03-25 22:53:5912#include "ash/shell_delegate.h"
13#include "ash/shell_window_ids.h"
[email protected]6d6546e2012-05-30 23:12:0214#include "ash/system/status_area_widget.h"
[email protected]a160baec2012-03-21 20:52:1515#include "ash/system/tray/system_tray.h"
[email protected]82a1cc92012-06-13 22:06:1016#include "ash/system/web_notification/web_notification_tray.h"
[email protected]c758fbf2012-03-25 22:53:5917#include "ash/wm/workspace/workspace_manager.h"
[email protected]4bb16502011-12-06 14:44:5818#include "base/auto_reset.h"
[email protected]e24b6092012-04-12 18:58:5119#include "base/i18n/rtl.h"
[email protected]8676f0472012-03-29 20:30:1220#include "ui/aura/client/activation_client.h"
[email protected]b1c37fc2012-03-22 03:36:1321#include "ui/aura/event.h"
22#include "ui/aura/event_filter.h"
[email protected]99f07e02011-12-07 00:02:5923#include "ui/aura/root_window.h"
[email protected]116302fc2012-05-05 21:45:4124#include "ui/compositor/layer.h"
25#include "ui/compositor/layer_animation_observer.h"
26#include "ui/compositor/layer_animator.h"
27#include "ui/compositor/scoped_layer_animation_settings.h"
[email protected]b82c42c42012-04-25 20:03:4128#include "ui/gfx/screen.h"
[email protected]c13be0d2011-11-22 02:09:5829#include "ui/views/widget/widget.h"
[email protected]ae18b9112011-11-07 16:59:1330
[email protected]55f593352011-12-24 05:42:4631namespace ash {
[email protected]ae18b9112011-11-07 16:59:1332namespace internal {
33
34namespace {
35
[email protected]cadd8c42012-03-27 02:44:3136// Delay before showing the launcher. This is after the mouse stops moving.
37const int kAutoHideDelayMS = 200;
[email protected]27f6af62012-03-21 05:34:4038
[email protected]ae18b9112011-11-07 16:59:1339ui::Layer* GetLayer(views::Widget* widget) {
40 return widget->GetNativeView()->layer();
41}
42
43} // namespace
44
[email protected]bbb59f82012-03-14 04:04:3545// static
46const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2;
47
[email protected]b1c37fc2012-03-22 03:36:1348// static
[email protected]55444502012-05-10 15:43:5349const int ShelfLayoutManager::kAutoHideSize = 2;
[email protected]b1c37fc2012-03-22 03:36:1350
51// Notifies ShelfLayoutManager any time the mouse moves.
52class ShelfLayoutManager::AutoHideEventFilter : public aura::EventFilter {
53 public:
54 explicit AutoHideEventFilter(ShelfLayoutManager* shelf);
55 virtual ~AutoHideEventFilter();
56
[email protected]5f1d99dc2012-04-12 21:42:3757 // Returns true if the last mouse event was a mouse drag.
58 bool in_mouse_drag() const { return in_mouse_drag_; }
59
[email protected]b1c37fc2012-03-22 03:36:1360 // Overridden from aura::EventFilter:
61 virtual bool PreHandleKeyEvent(aura::Window* target,
62 aura::KeyEvent* event) OVERRIDE;
63 virtual bool PreHandleMouseEvent(aura::Window* target,
64 aura::MouseEvent* event) OVERRIDE;
65 virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target,
66 aura::TouchEvent* event) OVERRIDE;
67 virtual ui::GestureStatus PreHandleGestureEvent(
68 aura::Window* target,
69 aura::GestureEvent* event) OVERRIDE;
70
71 private:
72 ShelfLayoutManager* shelf_;
[email protected]5f1d99dc2012-04-12 21:42:3773 bool in_mouse_drag_;
[email protected]b1c37fc2012-03-22 03:36:1374
75 DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter);
76};
77
78ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter(
79 ShelfLayoutManager* shelf)
[email protected]5f1d99dc2012-04-12 21:42:3780 : shelf_(shelf),
81 in_mouse_drag_(false) {
[email protected]1aad3322012-06-06 06:37:0982 Shell::GetInstance()->AddEnvEventFilter(this);
[email protected]b1c37fc2012-03-22 03:36:1383}
84
85ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() {
[email protected]1aad3322012-06-06 06:37:0986 Shell::GetInstance()->RemoveEnvEventFilter(this);
[email protected]b1c37fc2012-03-22 03:36:1387}
88
89bool ShelfLayoutManager::AutoHideEventFilter::PreHandleKeyEvent(
90 aura::Window* target,
91 aura::KeyEvent* event) {
92 return false; // Always let the event propagate.
93}
94
95bool ShelfLayoutManager::AutoHideEventFilter::PreHandleMouseEvent(
96 aura::Window* target,
97 aura::MouseEvent* event) {
[email protected]5f1d99dc2012-04-12 21:42:3798 // This also checks IsShelfWindow() to make sure we don't attempt to hide the
99 // shelf if the mouse down occurs on the shelf.
100 in_mouse_drag_ = (event->type() == ui::ET_MOUSE_DRAGGED ||
101 (in_mouse_drag_ && event->type() != ui::ET_MOUSE_RELEASED &&
102 event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)) &&
103 !shelf_->IsShelfWindow(target);
[email protected]b1c37fc2012-03-22 03:36:13104 if (event->type() == ui::ET_MOUSE_MOVED)
105 shelf_->UpdateAutoHideState();
106 return false; // Not handled.
107}
108
109ui::TouchStatus ShelfLayoutManager::AutoHideEventFilter::PreHandleTouchEvent(
110 aura::Window* target,
111 aura::TouchEvent* event) {
112 return ui::TOUCH_STATUS_UNKNOWN; // Not handled.
113}
114
115ui::GestureStatus
116ShelfLayoutManager::AutoHideEventFilter::PreHandleGestureEvent(
117 aura::Window* target,
118 aura::GestureEvent* event) {
119 return ui::GESTURE_STATUS_UNKNOWN; // Not handled.
120}
121
[email protected]4bb16502011-12-06 14:44:58122////////////////////////////////////////////////////////////////////////////////
123// ShelfLayoutManager, public:
124
[email protected]27f6af62012-03-21 05:34:40125ShelfLayoutManager::ShelfLayoutManager(views::Widget* status)
[email protected]42713f72012-05-25 00:41:50126 : root_window_(Shell::GetPrimaryRootWindow()),
[email protected]8676f0472012-03-29 20:30:12127 in_layout_(false),
[email protected]09f3fc82012-03-26 23:26:56128 auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT),
[email protected]55444502012-05-10 15:43:53129 alignment_(SHELF_ALIGNMENT_BOTTOM),
[email protected]27f6af62012-03-21 05:34:40130 launcher_(NULL),
131 status_(status),
[email protected]c758fbf2012-03-25 22:53:59132 workspace_manager_(NULL),
[email protected]b1c37fc2012-03-22 03:36:13133 window_overlaps_shelf_(false) {
[email protected]8e43cdf42012-05-11 17:03:31134 Shell::GetInstance()->AddShellObserver(this);
[email protected]e76310a92012-06-04 19:06:11135 aura::client::GetActivationClient(root_window_)->AddObserver(this);
[email protected]ae18b9112011-11-07 16:59:13136}
137
[email protected]4bb16502011-12-06 14:44:58138ShelfLayoutManager::~ShelfLayoutManager() {
[email protected]cbc278f2012-07-10 03:40:21139 FOR_EACH_OBSERVER(Observer, observers_, WillDeleteShelf());
[email protected]8e43cdf42012-05-11 17:03:31140 Shell::GetInstance()->RemoveShellObserver(this);
[email protected]e76310a92012-06-04 19:06:11141 aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
[email protected]ae18b9112011-11-07 16:59:13142}
143
[email protected]09f3fc82012-03-26 23:26:56144void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) {
145 if (auto_hide_behavior_ == behavior)
[email protected]c758fbf2012-03-25 22:53:59146 return;
[email protected]09f3fc82012-03-26 23:26:56147 auto_hide_behavior_ = behavior;
[email protected]c758fbf2012-03-25 22:53:59148 UpdateVisibilityState();
[email protected]cbc278f2012-07-10 03:40:21149 FOR_EACH_OBSERVER(Observer, observers_,
150 OnAutoHideStateChanged(state_.auto_hide_state));
[email protected]c758fbf2012-03-25 22:53:59151}
152
[email protected]40429f02012-03-28 20:38:50153bool ShelfLayoutManager::IsVisible() const {
[email protected]dd4b868b2012-04-10 17:20:46154 return status_->IsVisible() && (state_.visibility_state == VISIBLE ||
[email protected]40429f02012-03-28 20:38:50155 (state_.visibility_state == AUTO_HIDE &&
[email protected]dd4b868b2012-04-10 17:20:46156 state_.auto_hide_state == AUTO_HIDE_SHOWN));
[email protected]40429f02012-03-28 20:38:50157}
158
[email protected]27f6af62012-03-21 05:34:40159gfx::Rect ShelfLayoutManager::GetMaximizedWindowBounds(
[email protected]55444502012-05-10 15:43:53160 aura::Window* window) {
[email protected]27f6af62012-03-21 05:34:40161 // TODO: needs to be multi-mon aware.
[email protected]42c0a0c62012-06-17 03:50:33162 gfx::Rect bounds(gfx::Screen::GetDisplayNearestWindow(window).bounds());
[email protected]09f3fc82012-03-26 23:26:56163 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT ||
164 auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
[email protected]55444502012-05-10 15:43:53165 AdjustBoundsBasedOnAlignment(kAutoHideSize, &bounds);
[email protected]09f3fc82012-03-26 23:26:56166 return bounds;
167 }
168 // SHELF_AUTO_HIDE_BEHAVIOR_NEVER maximized windows don't get any taller.
169 return GetUnmaximizedWorkAreaBounds(window);
[email protected]27f6af62012-03-21 05:34:40170}
171
172gfx::Rect ShelfLayoutManager::GetUnmaximizedWorkAreaBounds(
[email protected]55444502012-05-10 15:43:53173 aura::Window* window) {
[email protected]27f6af62012-03-21 05:34:40174 // TODO: needs to be multi-mon aware.
[email protected]42c0a0c62012-06-17 03:50:33175 gfx::Rect bounds(gfx::Screen::GetDisplayNearestWindow(window).bounds());
[email protected]55444502012-05-10 15:43:53176 int size;
177 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
178 size = kAutoHideSize;
179 } else {
180 int width, height;
181 GetShelfSize(&width, &height);
182 size = std::max(width, height);
183 }
184 AdjustBoundsBasedOnAlignment(size, &bounds);
[email protected]27f6af62012-03-21 05:34:40185 return bounds;
186}
187
[email protected]d9456cb2012-03-21 16:41:04188void ShelfLayoutManager::SetLauncher(Launcher* launcher) {
189 if (launcher == launcher_)
190 return;
191
192 launcher_ = launcher;
[email protected]d9456cb2012-03-21 16:41:04193 LayoutShelf();
194}
195
[email protected]c2d58b42012-05-30 08:11:29196bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) {
[email protected]55444502012-05-10 15:43:53197 if (alignment_ == alignment)
[email protected]c2d58b42012-05-30 08:11:29198 return false;
[email protected]55444502012-05-10 15:43:53199
200 alignment_ = alignment;
201 if (launcher_)
202 launcher_->SetAlignment(alignment);
[email protected]82a1cc92012-06-13 22:06:10203 StatusAreaWidget* status_area_widget =
204 Shell::GetInstance()->status_area_widget();
205 if (status_area_widget)
[email protected]6d6546e2012-05-30 23:12:02206 Shell::GetInstance()->status_area_widget()->SetShelfAlignment(alignment);
[email protected]55444502012-05-10 15:43:53207 LayoutShelf();
[email protected]c2d58b42012-05-30 08:11:29208 return true;
[email protected]55444502012-05-10 15:43:53209}
210
211gfx::Rect ShelfLayoutManager::GetIdealBounds() {
[email protected]2e236a52012-06-27 22:21:47212 // TODO: this is wrong. Figure out what display shelf is on and everything
[email protected]55444502012-05-10 15:43:53213 // should be based on it.
214 gfx::Rect bounds(
[email protected]42c0a0c62012-06-17 03:50:33215 gfx::Screen::GetDisplayNearestWindow(status_->GetNativeView()).bounds());
[email protected]55444502012-05-10 15:43:53216 int width = 0, height = 0;
217 GetShelfSize(&width, &height);
218 switch (alignment_) {
219 case SHELF_ALIGNMENT_BOTTOM:
220 return gfx::Rect(bounds.x(), bounds.bottom() - height,
221 bounds.width(), height);
222 case SHELF_ALIGNMENT_LEFT:
223 return gfx::Rect(bounds.x(), bounds.y(), width, bounds.height());
224 case SHELF_ALIGNMENT_RIGHT:
[email protected]54a7c5a2012-05-24 19:54:20225 return gfx::Rect(bounds.right() - width, bounds.y(), width,
226 bounds.height());
[email protected]55444502012-05-10 15:43:53227 }
228 NOTREACHED();
229 return gfx::Rect();
230}
231
[email protected]4bb16502011-12-06 14:44:58232void ShelfLayoutManager::LayoutShelf() {
233 AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
[email protected]ae18b9112011-11-07 16:59:13234 StopAnimating();
235 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40236 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04237 if (launcher_widget()) {
238 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]cd9a61c72012-05-08 19:16:59239
[email protected]d9456cb2012-03-21 16:41:04240 launcher_widget()->SetBounds(target_bounds.launcher_bounds);
[email protected]55444502012-05-10 15:43:53241 launcher_->SetStatusSize(target_bounds.status_bounds.size());
[email protected]27f6af62012-03-21 05:34:40242 }
243 GetLayer(status_)->SetOpacity(target_bounds.opacity);
[email protected]ae18b9112011-11-07 16:59:13244 status_->SetBounds(target_bounds.status_bounds);
[email protected]2e236a52012-06-27 22:21:47245 Shell::GetInstance()->SetDisplayWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50246 Shell::GetPrimaryRootWindow(),
[email protected]ae18b9112011-11-07 16:59:13247 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12248 UpdateHitTestBounds();
[email protected]ae18b9112011-11-07 16:59:13249}
250
[email protected]c758fbf2012-03-25 22:53:59251void ShelfLayoutManager::UpdateVisibilityState() {
252 ShellDelegate* delegate = Shell::GetInstance()->delegate();
253 if (delegate && delegate->IsScreenLocked()) {
254 SetState(VISIBLE);
255 } else {
256 WorkspaceManager::WindowState window_state(
257 workspace_manager_->GetWindowState());
258 switch (window_state) {
259 case WorkspaceManager::WINDOW_STATE_FULL_SCREEN:
260 SetState(HIDDEN);
261 break;
262
263 case WorkspaceManager::WINDOW_STATE_MAXIMIZED:
[email protected]09f3fc82012-03-26 23:26:56264 SetState(auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_NEVER ?
265 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59266 break;
267
268 case WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF:
269 case WorkspaceManager::WINDOW_STATE_DEFAULT:
[email protected]09f3fc82012-03-26 23:26:56270 SetState(auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS ?
271 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59272 SetWindowOverlapsShelf(window_state ==
273 WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF);
274 }
275 }
276}
277
278void ShelfLayoutManager::UpdateAutoHideState() {
[email protected]cadd8c42012-03-27 02:44:31279 AutoHideState auto_hide_state =
280 CalculateAutoHideState(state_.visibility_state);
281 if (auto_hide_state != state_.auto_hide_state) {
282 if (auto_hide_state == AUTO_HIDE_HIDDEN) {
283 // Hides happen immediately.
284 SetState(state_.visibility_state);
[email protected]cbc278f2012-07-10 03:40:21285 FOR_EACH_OBSERVER(Observer, observers_,
286 OnAutoHideStateChanged(auto_hide_state));
[email protected]cadd8c42012-03-27 02:44:31287 } else {
288 auto_hide_timer_.Stop();
[email protected]c758fbf2012-03-25 22:53:59289 auto_hide_timer_.Start(
290 FROM_HERE,
291 base::TimeDelta::FromMilliseconds(kAutoHideDelayMS),
292 this, &ShelfLayoutManager::UpdateAutoHideStateNow);
[email protected]cbc278f2012-07-10 03:40:21293 FOR_EACH_OBSERVER(Observer, observers_, OnAutoHideStateChanged(
294 CalculateAutoHideState(state_.visibility_state)));
[email protected]c758fbf2012-03-25 22:53:59295 }
296 } else {
297 auto_hide_timer_.Stop();
298 }
299}
300
301void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) {
302 window_overlaps_shelf_ = value;
303 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
304}
305
[email protected]cbc278f2012-07-10 03:40:21306void ShelfLayoutManager::AddObserver(Observer* observer) {
307 observers_.AddObserver(observer);
308}
309
310void ShelfLayoutManager::RemoveObserver(Observer* observer) {
311 observers_.RemoveObserver(observer);
312}
313
[email protected]c758fbf2012-03-25 22:53:59314////////////////////////////////////////////////////////////////////////////////
315// ShelfLayoutManager, aura::LayoutManager implementation:
316
317void ShelfLayoutManager::OnWindowResized() {
318 LayoutShelf();
319}
320
321void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
322}
323
324void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
325}
326
[email protected]fa893ab62012-04-20 01:26:51327void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
328}
329
[email protected]c758fbf2012-03-25 22:53:59330void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
331 bool visible) {
332}
333
334void ShelfLayoutManager::SetChildBounds(aura::Window* child,
335 const gfx::Rect& requested_bounds) {
336 SetChildBoundsDirect(child, requested_bounds);
337 if (!in_layout_)
338 LayoutShelf();
339}
340
[email protected]8e43cdf42012-05-11 17:03:31341void ShelfLayoutManager::OnLockStateChanged(bool locked) {
342 UpdateVisibilityState();
343}
344
[email protected]e76310a92012-06-04 19:06:11345void ShelfLayoutManager::OnWindowActivated(aura::Window* active,
346 aura::Window* old_active) {
347 UpdateAutoHideStateNow();
[email protected]8676f0472012-03-29 20:30:12348}
349
[email protected]c758fbf2012-03-25 22:53:59350////////////////////////////////////////////////////////////////////////////////
351// ShelfLayoutManager, private:
352
[email protected]b1c37fc2012-03-22 03:36:13353void ShelfLayoutManager::SetState(VisibilityState visibility_state) {
[email protected]751444a2012-04-03 04:57:14354 ShellDelegate* delegate = Shell::GetInstance()->delegate();
[email protected]27f6af62012-03-21 05:34:40355 State state;
[email protected]c758fbf2012-03-25 22:53:59356 state.visibility_state = visibility_state;
[email protected]b1c37fc2012-03-22 03:36:13357 state.auto_hide_state = CalculateAutoHideState(visibility_state);
[email protected]751444a2012-04-03 04:57:14358 state.is_screen_locked = delegate && delegate->IsScreenLocked();
[email protected]306768162012-02-02 02:04:41359
[email protected]27f6af62012-03-21 05:34:40360 if (state_.Equals(state))
[email protected]ae18b9112011-11-07 16:59:13361 return; // Nothing changed.
362
[email protected]cbc278f2012-07-10 03:40:21363 FOR_EACH_OBSERVER(Observer, observers_,
364 WillChangeVisibilityState(visibility_state));
365
[email protected]b1c37fc2012-03-22 03:36:13366 if (state.visibility_state == AUTO_HIDE) {
367 // When state is AUTO_HIDE we need to track when the mouse is over the
368 // launcher to unhide the shelf. AutoHideEventFilter does that for us.
369 if (!event_filter_.get())
370 event_filter_.reset(new AutoHideEventFilter(this));
371 } else {
372 event_filter_.reset(NULL);
373 }
374
375 auto_hide_timer_.Stop();
376
[email protected]27f6af62012-03-21 05:34:40377 // Animating the background when transitioning from auto-hide & hidden to
378 // visibile is janking. Update the background immediately in this case.
[email protected]a160baec2012-03-21 20:52:15379 internal::BackgroundAnimator::ChangeType change_type =
[email protected]27f6af62012-03-21 05:34:40380 (state_.visibility_state == AUTO_HIDE &&
381 state_.auto_hide_state == AUTO_HIDE_HIDDEN &&
382 state.visibility_state == VISIBLE) ?
[email protected]a160baec2012-03-21 20:52:15383 internal::BackgroundAnimator::CHANGE_IMMEDIATE :
384 internal::BackgroundAnimator::CHANGE_ANIMATE;
[email protected]ae18b9112011-11-07 16:59:13385 StopAnimating();
[email protected]27f6af62012-03-21 05:34:40386 state_ = state;
[email protected]ae18b9112011-11-07 16:59:13387 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40388 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04389 if (launcher_widget()) {
[email protected]27f6af62012-03-21 05:34:40390 ui::ScopedLayerAnimationSettings launcher_animation_setter(
[email protected]d9456cb2012-03-21 16:41:04391 GetLayer(launcher_widget())->GetAnimator());
[email protected]27f6af62012-03-21 05:34:40392 launcher_animation_setter.SetTransitionDuration(
393 base::TimeDelta::FromMilliseconds(130));
394 launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59395 GetLayer(launcher_widget())->SetBounds(target_bounds.launcher_bounds);
[email protected]d9456cb2012-03-21 16:41:04396 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]27f6af62012-03-21 05:34:40397 }
[email protected]306768162012-02-02 02:04:41398 ui::ScopedLayerAnimationSettings status_animation_setter(
[email protected]27f6af62012-03-21 05:34:40399 GetLayer(status_)->GetAnimator());
400 status_animation_setter.SetTransitionDuration(
401 base::TimeDelta::FromMilliseconds(130));
402 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59403 GetLayer(status_)->SetBounds(target_bounds.status_bounds);
[email protected]27f6af62012-03-21 05:34:40404 GetLayer(status_)->SetOpacity(target_bounds.opacity);
[email protected]2e236a52012-06-27 22:21:47405 Shell::GetInstance()->SetDisplayWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50406 Shell::GetPrimaryRootWindow(),
[email protected]27f6af62012-03-21 05:34:40407 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12408 UpdateHitTestBounds();
[email protected]a160baec2012-03-21 20:52:15409 UpdateShelfBackground(change_type);
[email protected]27f6af62012-03-21 05:34:40410}
[email protected]63ef21592012-03-21 01:15:40411
[email protected]4bb16502011-12-06 14:44:58412void ShelfLayoutManager::StopAnimating() {
[email protected]d9456cb2012-03-21 16:41:04413 if (launcher_widget())
414 GetLayer(launcher_widget())->GetAnimator()->StopAnimating();
[email protected]df5954f2011-12-14 16:19:58415 GetLayer(status_)->GetAnimator()->StopAnimating();
[email protected]ae18b9112011-11-07 16:59:13416}
417
[email protected]55444502012-05-10 15:43:53418void ShelfLayoutManager::GetShelfSize(int* width, int* height) {
419 *width = *height = 0;
420 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
421 gfx::Size launcher_size = launcher_ ?
422 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
[email protected]0ab08e52012-05-19 00:04:21423 if (alignment_ == SHELF_ALIGNMENT_BOTTOM)
[email protected]55444502012-05-10 15:43:53424 *height = std::max(launcher_size.height(), status_bounds.height());
[email protected]0ab08e52012-05-19 00:04:21425 else
426 *width = std::max(launcher_size.width(), status_bounds.width());
[email protected]55444502012-05-10 15:43:53427}
428
429void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset,
430 gfx::Rect* bounds) const {
431 switch (alignment_) {
432 case SHELF_ALIGNMENT_BOTTOM:
433 bounds->Inset(gfx::Insets(0, 0, inset, 0));
434 break;
435 case SHELF_ALIGNMENT_LEFT:
436 bounds->Inset(gfx::Insets(0, inset, 0, 0));
437 break;
438 case SHELF_ALIGNMENT_RIGHT:
439 bounds->Inset(gfx::Insets(0, 0, 0, inset));
440 break;
441 }
442}
443
[email protected]27f6af62012-03-21 05:34:40444void ShelfLayoutManager::CalculateTargetBounds(
445 const State& state,
[email protected]55444502012-05-10 15:43:53446 TargetBounds* target_bounds) {
[email protected]b1c37fc2012-03-22 03:36:13447 const gfx::Rect& available_bounds(
448 status_->GetNativeView()->GetRootWindow()->bounds());
[email protected]55444502012-05-10 15:43:53449 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
450 gfx::Size launcher_size = launcher_ ?
451 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
452 int shelf_size = 0;
453 int shelf_width = 0, shelf_height = 0;
454 GetShelfSize(&shelf_width, &shelf_height);
[email protected]27f6af62012-03-21 05:34:40455 if (state.visibility_state == VISIBLE ||
456 (state.visibility_state == AUTO_HIDE &&
[email protected]55444502012-05-10 15:43:53457 state.auto_hide_state == AUTO_HIDE_SHOWN)) {
458 shelf_size = std::max(shelf_width, shelf_height);
459 } else if (state.visibility_state == AUTO_HIDE &&
460 state.auto_hide_state == AUTO_HIDE_HIDDEN) {
461 shelf_size = kAutoHideSize;
[email protected]27f6af62012-03-21 05:34:40462 }
[email protected]55444502012-05-10 15:43:53463 if (alignment_ == SHELF_ALIGNMENT_BOTTOM) {
464 int y = available_bounds.bottom();
465 y -= shelf_size;
466 // The status widget should extend to the bottom and right edges.
467 target_bounds->status_bounds = gfx::Rect(
468 base::i18n::IsRTL() ? available_bounds.x() :
469 available_bounds.right() - status_bounds.width(),
470 y + shelf_height - status_bounds.height(),
471 status_bounds.width(), status_bounds.height());
472 if (launcher_widget()) {
473 target_bounds->launcher_bounds = gfx::Rect(
474 available_bounds.x(),
475 y + (shelf_height - launcher_size.height()) / 2,
476 available_bounds.width(),
477 launcher_size.height());
478 }
479 target_bounds->work_area_insets.Set(
480 0, 0, GetWorkAreaSize(state, shelf_height), 0);
481 } else {
482 int x = (alignment_ == SHELF_ALIGNMENT_LEFT) ?
483 available_bounds.x() + shelf_size - shelf_width :
484 available_bounds.right() - shelf_size;
485 target_bounds->status_bounds = gfx::Rect(
486 x, available_bounds.bottom() - status_bounds.height(),
487 shelf_width, status_bounds.height());
488 if (launcher_widget()) {
489 target_bounds->launcher_bounds = gfx::Rect(
490 x,
491 available_bounds.y(),
492 launcher_size.width(),
493 available_bounds.height());
494 }
495 if (alignment_ == SHELF_ALIGNMENT_LEFT) {
496 target_bounds->work_area_insets.Set(
497 0, GetWorkAreaSize(state, shelf_width), 0, 0);
498 } else {
499 target_bounds->work_area_insets.Set(
500 0, 0, 0, GetWorkAreaSize(state, shelf_width));
501 }
502 }
[email protected]27f6af62012-03-21 05:34:40503 target_bounds->opacity =
504 (state.visibility_state == VISIBLE ||
505 state.visibility_state == AUTO_HIDE) ? 1.0f : 0.0f;
[email protected]ae18b9112011-11-07 16:59:13506}
507
[email protected]a160baec2012-03-21 20:52:15508void ShelfLayoutManager::UpdateShelfBackground(
509 BackgroundAnimator::ChangeType type) {
510 bool launcher_paints = GetLauncherPaintsBackground();
511 if (launcher_)
512 launcher_->SetPaintsBackground(launcher_paints, type);
513 // SystemTray normally draws a background, but we don't want it to draw a
514 // background when the launcher does.
[email protected]82a1cc92012-06-13 22:06:10515 StatusAreaWidget* status_area_widget =
516 Shell::GetInstance()->status_area_widget();
517 if (status_area_widget)
518 status_area_widget->SetPaintsBackground(!launcher_paints, type);
[email protected]a160baec2012-03-21 20:52:15519}
520
521bool ShelfLayoutManager::GetLauncherPaintsBackground() const {
[email protected]751444a2012-04-03 04:57:14522 return (!state_.is_screen_locked && window_overlaps_shelf_) ||
523 state_.visibility_state == AUTO_HIDE;
[email protected]ae18b9112011-11-07 16:59:13524}
525
[email protected]b1c37fc2012-03-22 03:36:13526void ShelfLayoutManager::UpdateAutoHideStateNow() {
527 SetState(state_.visibility_state);
528}
529
530ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState(
531 VisibilityState visibility_state) const {
532 if (visibility_state != AUTO_HIDE || !launcher_widget())
533 return AUTO_HIDE_HIDDEN;
534
535 Shell* shell = Shell::GetInstance();
[email protected]7510d1082012-03-30 21:58:34536 if (shell->GetAppListTargetVisibility())
537 return AUTO_HIDE_SHOWN;
538
[email protected]6d6546e2012-05-30 23:12:02539 if (shell->system_tray() && shell->system_tray()->should_show_launcher())
[email protected]d9d5a922012-03-26 04:38:03540 return AUTO_HIDE_SHOWN;
[email protected]b1c37fc2012-03-22 03:36:13541
[email protected]e9992b12012-03-27 00:11:27542 if (launcher_ && launcher_->IsShowingMenu())
543 return AUTO_HIDE_SHOWN;
544
[email protected]3475f5e2012-07-12 22:10:32545 if (launcher_ && launcher_->IsShowingOverflowBubble())
546 return AUTO_HIDE_SHOWN;
547
[email protected]8676f0472012-03-29 20:30:12548 if (launcher_widget()->IsActive() || status_->IsActive())
549 return AUTO_HIDE_SHOWN;
550
[email protected]5f1d99dc2012-04-12 21:42:37551 // Don't show if the user is dragging the mouse.
552 if (event_filter_.get() && event_filter_->in_mouse_drag())
553 return AUTO_HIDE_HIDDEN;
554
[email protected]b1c37fc2012-03-22 03:36:13555 aura::RootWindow* root = launcher_widget()->GetNativeView()->GetRootWindow();
556 bool mouse_over_launcher =
557 launcher_widget()->GetWindowScreenBounds().Contains(
558 root->last_mouse_location());
559 return mouse_over_launcher ? AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN;
560}
561
[email protected]128fd3732012-03-27 01:55:12562void ShelfLayoutManager::UpdateHitTestBounds() {
563 gfx::Insets insets;
564 // Only modify the hit test when the shelf is visible, so we don't mess with
565 // hover hit testing in the auto-hide state.
566 if (state_.visibility_state == VISIBLE) {
567 // Let clicks at the very top of the launcher through so windows can be
568 // resized with the bottom-right corner and bottom edge.
[email protected]55444502012-05-10 15:43:53569 switch (alignment_) {
570 case SHELF_ALIGNMENT_BOTTOM:
571 insets.Set(kWorkspaceAreaBottomInset, 0, 0, 0);
572 break;
573 case SHELF_ALIGNMENT_LEFT:
574 insets.Set(0, 0, 0, kWorkspaceAreaBottomInset);
575 break;
576 case SHELF_ALIGNMENT_RIGHT:
577 insets.Set(0, kWorkspaceAreaBottomInset, 0, 0);
578 break;
579 }
[email protected]128fd3732012-03-27 01:55:12580 }
581 if (launcher_widget() && launcher_widget()->GetNativeWindow())
582 launcher_widget()->GetNativeWindow()->set_hit_test_bounds_override_outer(
583 insets);
584 status_->GetNativeWindow()->set_hit_test_bounds_override_outer(insets);
585}
586
[email protected]5f1d99dc2012-04-12 21:42:37587bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) {
588 if (!window)
589 return false;
590 return (launcher_widget() &&
591 launcher_widget()->GetNativeWindow()->Contains(window)) ||
592 (status_ && status_->GetNativeWindow()->Contains(window));
593}
594
[email protected]55444502012-05-10 15:43:53595int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const {
596 if (state.visibility_state == VISIBLE)
597 return size;
598 if (state.visibility_state == AUTO_HIDE)
599 return kAutoHideSize;
600 return 0;
601}
602
[email protected]55f593352011-12-24 05:42:46603} // namespace internal
604} // namespace ash