blob: 3c3246f5b5632b857e7b96669c8d312d6db59bff [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]8e43cdf42012-05-11 17:03:31139 Shell::GetInstance()->RemoveShellObserver(this);
[email protected]e76310a92012-06-04 19:06:11140 aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
[email protected]ae18b9112011-11-07 16:59:13141}
142
[email protected]09f3fc82012-03-26 23:26:56143void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) {
144 if (auto_hide_behavior_ == behavior)
[email protected]c758fbf2012-03-25 22:53:59145 return;
[email protected]09f3fc82012-03-26 23:26:56146 auto_hide_behavior_ = behavior;
[email protected]c758fbf2012-03-25 22:53:59147 UpdateVisibilityState();
148}
149
[email protected]40429f02012-03-28 20:38:50150bool ShelfLayoutManager::IsVisible() const {
[email protected]dd4b868b2012-04-10 17:20:46151 return status_->IsVisible() && (state_.visibility_state == VISIBLE ||
[email protected]40429f02012-03-28 20:38:50152 (state_.visibility_state == AUTO_HIDE &&
[email protected]dd4b868b2012-04-10 17:20:46153 state_.auto_hide_state == AUTO_HIDE_SHOWN));
[email protected]40429f02012-03-28 20:38:50154}
155
[email protected]27f6af62012-03-21 05:34:40156gfx::Rect ShelfLayoutManager::GetMaximizedWindowBounds(
[email protected]55444502012-05-10 15:43:53157 aura::Window* window) {
[email protected]27f6af62012-03-21 05:34:40158 // TODO: needs to be multi-mon aware.
[email protected]42c0a0c62012-06-17 03:50:33159 gfx::Rect bounds(gfx::Screen::GetDisplayNearestWindow(window).bounds());
[email protected]09f3fc82012-03-26 23:26:56160 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT ||
161 auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
[email protected]55444502012-05-10 15:43:53162 AdjustBoundsBasedOnAlignment(kAutoHideSize, &bounds);
[email protected]09f3fc82012-03-26 23:26:56163 return bounds;
164 }
165 // SHELF_AUTO_HIDE_BEHAVIOR_NEVER maximized windows don't get any taller.
166 return GetUnmaximizedWorkAreaBounds(window);
[email protected]27f6af62012-03-21 05:34:40167}
168
169gfx::Rect ShelfLayoutManager::GetUnmaximizedWorkAreaBounds(
[email protected]55444502012-05-10 15:43:53170 aura::Window* window) {
[email protected]27f6af62012-03-21 05:34:40171 // TODO: needs to be multi-mon aware.
[email protected]42c0a0c62012-06-17 03:50:33172 gfx::Rect bounds(gfx::Screen::GetDisplayNearestWindow(window).bounds());
[email protected]55444502012-05-10 15:43:53173 int size;
174 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
175 size = kAutoHideSize;
176 } else {
177 int width, height;
178 GetShelfSize(&width, &height);
179 size = std::max(width, height);
180 }
181 AdjustBoundsBasedOnAlignment(size, &bounds);
[email protected]27f6af62012-03-21 05:34:40182 return bounds;
183}
184
[email protected]d9456cb2012-03-21 16:41:04185void ShelfLayoutManager::SetLauncher(Launcher* launcher) {
186 if (launcher == launcher_)
187 return;
188
189 launcher_ = launcher;
[email protected]d9456cb2012-03-21 16:41:04190 LayoutShelf();
191}
192
[email protected]c2d58b42012-05-30 08:11:29193bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) {
[email protected]55444502012-05-10 15:43:53194 if (alignment_ == alignment)
[email protected]c2d58b42012-05-30 08:11:29195 return false;
[email protected]55444502012-05-10 15:43:53196
197 alignment_ = alignment;
198 if (launcher_)
199 launcher_->SetAlignment(alignment);
[email protected]82a1cc92012-06-13 22:06:10200 StatusAreaWidget* status_area_widget =
201 Shell::GetInstance()->status_area_widget();
202 if (status_area_widget)
[email protected]6d6546e2012-05-30 23:12:02203 Shell::GetInstance()->status_area_widget()->SetShelfAlignment(alignment);
[email protected]55444502012-05-10 15:43:53204 LayoutShelf();
[email protected]c2d58b42012-05-30 08:11:29205 return true;
[email protected]55444502012-05-10 15:43:53206}
207
208gfx::Rect ShelfLayoutManager::GetIdealBounds() {
209 // TODO: this is wrong. Figure out what monitor shelf is on and everything
210 // should be based on it.
211 gfx::Rect bounds(
[email protected]42c0a0c62012-06-17 03:50:33212 gfx::Screen::GetDisplayNearestWindow(status_->GetNativeView()).bounds());
[email protected]55444502012-05-10 15:43:53213 int width = 0, height = 0;
214 GetShelfSize(&width, &height);
215 switch (alignment_) {
216 case SHELF_ALIGNMENT_BOTTOM:
217 return gfx::Rect(bounds.x(), bounds.bottom() - height,
218 bounds.width(), height);
219 case SHELF_ALIGNMENT_LEFT:
220 return gfx::Rect(bounds.x(), bounds.y(), width, bounds.height());
221 case SHELF_ALIGNMENT_RIGHT:
[email protected]54a7c5a2012-05-24 19:54:20222 return gfx::Rect(bounds.right() - width, bounds.y(), width,
223 bounds.height());
[email protected]55444502012-05-10 15:43:53224 }
225 NOTREACHED();
226 return gfx::Rect();
227}
228
[email protected]4bb16502011-12-06 14:44:58229void ShelfLayoutManager::LayoutShelf() {
230 AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
[email protected]ae18b9112011-11-07 16:59:13231 StopAnimating();
232 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40233 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04234 if (launcher_widget()) {
235 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]cd9a61c72012-05-08 19:16:59236
[email protected]d9456cb2012-03-21 16:41:04237 launcher_widget()->SetBounds(target_bounds.launcher_bounds);
[email protected]55444502012-05-10 15:43:53238 launcher_->SetStatusSize(target_bounds.status_bounds.size());
[email protected]27f6af62012-03-21 05:34:40239 }
240 GetLayer(status_)->SetOpacity(target_bounds.opacity);
[email protected]ae18b9112011-11-07 16:59:13241 status_->SetBounds(target_bounds.status_bounds);
[email protected]8a45c972012-03-14 18:22:44242 Shell::GetInstance()->SetMonitorWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50243 Shell::GetPrimaryRootWindow(),
[email protected]ae18b9112011-11-07 16:59:13244 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12245 UpdateHitTestBounds();
[email protected]ae18b9112011-11-07 16:59:13246}
247
[email protected]c758fbf2012-03-25 22:53:59248void ShelfLayoutManager::UpdateVisibilityState() {
249 ShellDelegate* delegate = Shell::GetInstance()->delegate();
250 if (delegate && delegate->IsScreenLocked()) {
251 SetState(VISIBLE);
252 } else {
253 WorkspaceManager::WindowState window_state(
254 workspace_manager_->GetWindowState());
255 switch (window_state) {
256 case WorkspaceManager::WINDOW_STATE_FULL_SCREEN:
257 SetState(HIDDEN);
258 break;
259
260 case WorkspaceManager::WINDOW_STATE_MAXIMIZED:
[email protected]09f3fc82012-03-26 23:26:56261 SetState(auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_NEVER ?
262 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59263 break;
264
265 case WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF:
266 case WorkspaceManager::WINDOW_STATE_DEFAULT:
[email protected]09f3fc82012-03-26 23:26:56267 SetState(auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS ?
268 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59269 SetWindowOverlapsShelf(window_state ==
270 WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF);
271 }
272 }
273}
274
275void ShelfLayoutManager::UpdateAutoHideState() {
[email protected]cadd8c42012-03-27 02:44:31276 AutoHideState auto_hide_state =
277 CalculateAutoHideState(state_.visibility_state);
278 if (auto_hide_state != state_.auto_hide_state) {
279 if (auto_hide_state == AUTO_HIDE_HIDDEN) {
280 // Hides happen immediately.
281 SetState(state_.visibility_state);
282 } else {
283 auto_hide_timer_.Stop();
[email protected]c758fbf2012-03-25 22:53:59284 auto_hide_timer_.Start(
285 FROM_HERE,
286 base::TimeDelta::FromMilliseconds(kAutoHideDelayMS),
287 this, &ShelfLayoutManager::UpdateAutoHideStateNow);
288 }
289 } else {
290 auto_hide_timer_.Stop();
291 }
292}
293
294void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) {
295 window_overlaps_shelf_ = value;
296 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
297}
298
299////////////////////////////////////////////////////////////////////////////////
300// ShelfLayoutManager, aura::LayoutManager implementation:
301
302void ShelfLayoutManager::OnWindowResized() {
303 LayoutShelf();
304}
305
306void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
307}
308
309void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
310}
311
[email protected]fa893ab62012-04-20 01:26:51312void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
313}
314
[email protected]c758fbf2012-03-25 22:53:59315void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
316 bool visible) {
317}
318
319void ShelfLayoutManager::SetChildBounds(aura::Window* child,
320 const gfx::Rect& requested_bounds) {
321 SetChildBoundsDirect(child, requested_bounds);
322 if (!in_layout_)
323 LayoutShelf();
324}
325
[email protected]8e43cdf42012-05-11 17:03:31326void ShelfLayoutManager::OnLockStateChanged(bool locked) {
327 UpdateVisibilityState();
328}
329
[email protected]e76310a92012-06-04 19:06:11330void ShelfLayoutManager::OnWindowActivated(aura::Window* active,
331 aura::Window* old_active) {
332 UpdateAutoHideStateNow();
[email protected]8676f0472012-03-29 20:30:12333}
334
[email protected]c758fbf2012-03-25 22:53:59335////////////////////////////////////////////////////////////////////////////////
336// ShelfLayoutManager, private:
337
[email protected]b1c37fc2012-03-22 03:36:13338void ShelfLayoutManager::SetState(VisibilityState visibility_state) {
[email protected]751444a2012-04-03 04:57:14339 ShellDelegate* delegate = Shell::GetInstance()->delegate();
[email protected]27f6af62012-03-21 05:34:40340 State state;
[email protected]c758fbf2012-03-25 22:53:59341 state.visibility_state = visibility_state;
[email protected]b1c37fc2012-03-22 03:36:13342 state.auto_hide_state = CalculateAutoHideState(visibility_state);
[email protected]751444a2012-04-03 04:57:14343 state.is_screen_locked = delegate && delegate->IsScreenLocked();
[email protected]306768162012-02-02 02:04:41344
[email protected]27f6af62012-03-21 05:34:40345 if (state_.Equals(state))
[email protected]ae18b9112011-11-07 16:59:13346 return; // Nothing changed.
347
[email protected]b1c37fc2012-03-22 03:36:13348 if (state.visibility_state == AUTO_HIDE) {
349 // When state is AUTO_HIDE we need to track when the mouse is over the
350 // launcher to unhide the shelf. AutoHideEventFilter does that for us.
351 if (!event_filter_.get())
352 event_filter_.reset(new AutoHideEventFilter(this));
353 } else {
354 event_filter_.reset(NULL);
355 }
356
357 auto_hide_timer_.Stop();
358
[email protected]27f6af62012-03-21 05:34:40359 // Animating the background when transitioning from auto-hide & hidden to
360 // visibile is janking. Update the background immediately in this case.
[email protected]a160baec2012-03-21 20:52:15361 internal::BackgroundAnimator::ChangeType change_type =
[email protected]27f6af62012-03-21 05:34:40362 (state_.visibility_state == AUTO_HIDE &&
363 state_.auto_hide_state == AUTO_HIDE_HIDDEN &&
364 state.visibility_state == VISIBLE) ?
[email protected]a160baec2012-03-21 20:52:15365 internal::BackgroundAnimator::CHANGE_IMMEDIATE :
366 internal::BackgroundAnimator::CHANGE_ANIMATE;
[email protected]ae18b9112011-11-07 16:59:13367 StopAnimating();
[email protected]27f6af62012-03-21 05:34:40368 state_ = state;
[email protected]ae18b9112011-11-07 16:59:13369 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40370 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04371 if (launcher_widget()) {
[email protected]27f6af62012-03-21 05:34:40372 ui::ScopedLayerAnimationSettings launcher_animation_setter(
[email protected]d9456cb2012-03-21 16:41:04373 GetLayer(launcher_widget())->GetAnimator());
[email protected]27f6af62012-03-21 05:34:40374 launcher_animation_setter.SetTransitionDuration(
375 base::TimeDelta::FromMilliseconds(130));
376 launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59377 GetLayer(launcher_widget())->SetBounds(target_bounds.launcher_bounds);
[email protected]d9456cb2012-03-21 16:41:04378 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]27f6af62012-03-21 05:34:40379 }
[email protected]306768162012-02-02 02:04:41380 ui::ScopedLayerAnimationSettings status_animation_setter(
[email protected]27f6af62012-03-21 05:34:40381 GetLayer(status_)->GetAnimator());
382 status_animation_setter.SetTransitionDuration(
383 base::TimeDelta::FromMilliseconds(130));
384 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59385 GetLayer(status_)->SetBounds(target_bounds.status_bounds);
[email protected]27f6af62012-03-21 05:34:40386 GetLayer(status_)->SetOpacity(target_bounds.opacity);
387 Shell::GetInstance()->SetMonitorWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50388 Shell::GetPrimaryRootWindow(),
[email protected]27f6af62012-03-21 05:34:40389 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12390 UpdateHitTestBounds();
[email protected]a160baec2012-03-21 20:52:15391 UpdateShelfBackground(change_type);
[email protected]27f6af62012-03-21 05:34:40392}
[email protected]63ef21592012-03-21 01:15:40393
[email protected]4bb16502011-12-06 14:44:58394void ShelfLayoutManager::StopAnimating() {
[email protected]d9456cb2012-03-21 16:41:04395 if (launcher_widget())
396 GetLayer(launcher_widget())->GetAnimator()->StopAnimating();
[email protected]df5954f2011-12-14 16:19:58397 GetLayer(status_)->GetAnimator()->StopAnimating();
[email protected]ae18b9112011-11-07 16:59:13398}
399
[email protected]55444502012-05-10 15:43:53400void ShelfLayoutManager::GetShelfSize(int* width, int* height) {
401 *width = *height = 0;
402 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
403 gfx::Size launcher_size = launcher_ ?
404 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
[email protected]0ab08e52012-05-19 00:04:21405 if (alignment_ == SHELF_ALIGNMENT_BOTTOM)
[email protected]55444502012-05-10 15:43:53406 *height = std::max(launcher_size.height(), status_bounds.height());
[email protected]0ab08e52012-05-19 00:04:21407 else
408 *width = std::max(launcher_size.width(), status_bounds.width());
[email protected]55444502012-05-10 15:43:53409}
410
411void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset,
412 gfx::Rect* bounds) const {
413 switch (alignment_) {
414 case SHELF_ALIGNMENT_BOTTOM:
415 bounds->Inset(gfx::Insets(0, 0, inset, 0));
416 break;
417 case SHELF_ALIGNMENT_LEFT:
418 bounds->Inset(gfx::Insets(0, inset, 0, 0));
419 break;
420 case SHELF_ALIGNMENT_RIGHT:
421 bounds->Inset(gfx::Insets(0, 0, 0, inset));
422 break;
423 }
424}
425
[email protected]27f6af62012-03-21 05:34:40426void ShelfLayoutManager::CalculateTargetBounds(
427 const State& state,
[email protected]55444502012-05-10 15:43:53428 TargetBounds* target_bounds) {
[email protected]b1c37fc2012-03-22 03:36:13429 const gfx::Rect& available_bounds(
430 status_->GetNativeView()->GetRootWindow()->bounds());
[email protected]55444502012-05-10 15:43:53431 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
432 gfx::Size launcher_size = launcher_ ?
433 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
434 int shelf_size = 0;
435 int shelf_width = 0, shelf_height = 0;
436 GetShelfSize(&shelf_width, &shelf_height);
[email protected]27f6af62012-03-21 05:34:40437 if (state.visibility_state == VISIBLE ||
438 (state.visibility_state == AUTO_HIDE &&
[email protected]55444502012-05-10 15:43:53439 state.auto_hide_state == AUTO_HIDE_SHOWN)) {
440 shelf_size = std::max(shelf_width, shelf_height);
441 } else if (state.visibility_state == AUTO_HIDE &&
442 state.auto_hide_state == AUTO_HIDE_HIDDEN) {
443 shelf_size = kAutoHideSize;
[email protected]27f6af62012-03-21 05:34:40444 }
[email protected]55444502012-05-10 15:43:53445 if (alignment_ == SHELF_ALIGNMENT_BOTTOM) {
446 int y = available_bounds.bottom();
447 y -= shelf_size;
448 // The status widget should extend to the bottom and right edges.
449 target_bounds->status_bounds = gfx::Rect(
450 base::i18n::IsRTL() ? available_bounds.x() :
451 available_bounds.right() - status_bounds.width(),
452 y + shelf_height - status_bounds.height(),
453 status_bounds.width(), status_bounds.height());
454 if (launcher_widget()) {
455 target_bounds->launcher_bounds = gfx::Rect(
456 available_bounds.x(),
457 y + (shelf_height - launcher_size.height()) / 2,
458 available_bounds.width(),
459 launcher_size.height());
460 }
461 target_bounds->work_area_insets.Set(
462 0, 0, GetWorkAreaSize(state, shelf_height), 0);
463 } else {
464 int x = (alignment_ == SHELF_ALIGNMENT_LEFT) ?
465 available_bounds.x() + shelf_size - shelf_width :
466 available_bounds.right() - shelf_size;
467 target_bounds->status_bounds = gfx::Rect(
468 x, available_bounds.bottom() - status_bounds.height(),
469 shelf_width, status_bounds.height());
470 if (launcher_widget()) {
471 target_bounds->launcher_bounds = gfx::Rect(
472 x,
473 available_bounds.y(),
474 launcher_size.width(),
475 available_bounds.height());
476 }
477 if (alignment_ == SHELF_ALIGNMENT_LEFT) {
478 target_bounds->work_area_insets.Set(
479 0, GetWorkAreaSize(state, shelf_width), 0, 0);
480 } else {
481 target_bounds->work_area_insets.Set(
482 0, 0, 0, GetWorkAreaSize(state, shelf_width));
483 }
484 }
[email protected]27f6af62012-03-21 05:34:40485 target_bounds->opacity =
486 (state.visibility_state == VISIBLE ||
487 state.visibility_state == AUTO_HIDE) ? 1.0f : 0.0f;
[email protected]ae18b9112011-11-07 16:59:13488}
489
[email protected]a160baec2012-03-21 20:52:15490void ShelfLayoutManager::UpdateShelfBackground(
491 BackgroundAnimator::ChangeType type) {
492 bool launcher_paints = GetLauncherPaintsBackground();
493 if (launcher_)
494 launcher_->SetPaintsBackground(launcher_paints, type);
495 // SystemTray normally draws a background, but we don't want it to draw a
496 // background when the launcher does.
[email protected]82a1cc92012-06-13 22:06:10497 StatusAreaWidget* status_area_widget =
498 Shell::GetInstance()->status_area_widget();
499 if (status_area_widget)
500 status_area_widget->SetPaintsBackground(!launcher_paints, type);
[email protected]a160baec2012-03-21 20:52:15501}
502
503bool ShelfLayoutManager::GetLauncherPaintsBackground() const {
[email protected]751444a2012-04-03 04:57:14504 return (!state_.is_screen_locked && window_overlaps_shelf_) ||
505 state_.visibility_state == AUTO_HIDE;
[email protected]ae18b9112011-11-07 16:59:13506}
507
[email protected]b1c37fc2012-03-22 03:36:13508void ShelfLayoutManager::UpdateAutoHideStateNow() {
509 SetState(state_.visibility_state);
510}
511
512ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState(
513 VisibilityState visibility_state) const {
514 if (visibility_state != AUTO_HIDE || !launcher_widget())
515 return AUTO_HIDE_HIDDEN;
516
517 Shell* shell = Shell::GetInstance();
[email protected]7510d1082012-03-30 21:58:34518 if (shell->GetAppListTargetVisibility())
519 return AUTO_HIDE_SHOWN;
520
[email protected]6d6546e2012-05-30 23:12:02521 if (shell->system_tray() && shell->system_tray()->should_show_launcher())
[email protected]d9d5a922012-03-26 04:38:03522 return AUTO_HIDE_SHOWN;
[email protected]b1c37fc2012-03-22 03:36:13523
[email protected]e9992b12012-03-27 00:11:27524 if (launcher_ && launcher_->IsShowingMenu())
525 return AUTO_HIDE_SHOWN;
526
[email protected]8676f0472012-03-29 20:30:12527 if (launcher_widget()->IsActive() || status_->IsActive())
528 return AUTO_HIDE_SHOWN;
529
[email protected]5f1d99dc2012-04-12 21:42:37530 // Don't show if the user is dragging the mouse.
531 if (event_filter_.get() && event_filter_->in_mouse_drag())
532 return AUTO_HIDE_HIDDEN;
533
[email protected]b1c37fc2012-03-22 03:36:13534 aura::RootWindow* root = launcher_widget()->GetNativeView()->GetRootWindow();
535 bool mouse_over_launcher =
536 launcher_widget()->GetWindowScreenBounds().Contains(
537 root->last_mouse_location());
538 return mouse_over_launcher ? AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN;
539}
540
[email protected]128fd3732012-03-27 01:55:12541void ShelfLayoutManager::UpdateHitTestBounds() {
542 gfx::Insets insets;
543 // Only modify the hit test when the shelf is visible, so we don't mess with
544 // hover hit testing in the auto-hide state.
545 if (state_.visibility_state == VISIBLE) {
546 // Let clicks at the very top of the launcher through so windows can be
547 // resized with the bottom-right corner and bottom edge.
[email protected]55444502012-05-10 15:43:53548 switch (alignment_) {
549 case SHELF_ALIGNMENT_BOTTOM:
550 insets.Set(kWorkspaceAreaBottomInset, 0, 0, 0);
551 break;
552 case SHELF_ALIGNMENT_LEFT:
553 insets.Set(0, 0, 0, kWorkspaceAreaBottomInset);
554 break;
555 case SHELF_ALIGNMENT_RIGHT:
556 insets.Set(0, kWorkspaceAreaBottomInset, 0, 0);
557 break;
558 }
[email protected]128fd3732012-03-27 01:55:12559 }
560 if (launcher_widget() && launcher_widget()->GetNativeWindow())
561 launcher_widget()->GetNativeWindow()->set_hit_test_bounds_override_outer(
562 insets);
563 status_->GetNativeWindow()->set_hit_test_bounds_override_outer(insets);
564}
565
[email protected]5f1d99dc2012-04-12 21:42:37566bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) {
567 if (!window)
568 return false;
569 return (launcher_widget() &&
570 launcher_widget()->GetNativeWindow()->Contains(window)) ||
571 (status_ && status_->GetNativeWindow()->Contains(window));
572}
573
[email protected]55444502012-05-10 15:43:53574int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const {
575 if (state.visibility_state == VISIBLE)
576 return size;
577 if (state.visibility_state == AUTO_HIDE)
578 return kAutoHideSize;
579 return 0;
580}
581
[email protected]55f593352011-12-24 05:42:46582} // namespace internal
583} // namespace ash