blob: 2b4031f325ce6d607deb2f29601c7882521dc801 [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]d9456cb2012-03-21 16:41:04159void ShelfLayoutManager::SetLauncher(Launcher* launcher) {
160 if (launcher == launcher_)
161 return;
162
163 launcher_ = launcher;
[email protected]d9456cb2012-03-21 16:41:04164 LayoutShelf();
165}
166
[email protected]c2d58b42012-05-30 08:11:29167bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) {
[email protected]55444502012-05-10 15:43:53168 if (alignment_ == alignment)
[email protected]c2d58b42012-05-30 08:11:29169 return false;
[email protected]55444502012-05-10 15:43:53170
171 alignment_ = alignment;
172 if (launcher_)
173 launcher_->SetAlignment(alignment);
[email protected]82a1cc92012-06-13 22:06:10174 StatusAreaWidget* status_area_widget =
175 Shell::GetInstance()->status_area_widget();
176 if (status_area_widget)
[email protected]6d6546e2012-05-30 23:12:02177 Shell::GetInstance()->status_area_widget()->SetShelfAlignment(alignment);
[email protected]55444502012-05-10 15:43:53178 LayoutShelf();
[email protected]c2d58b42012-05-30 08:11:29179 return true;
[email protected]55444502012-05-10 15:43:53180}
181
182gfx::Rect ShelfLayoutManager::GetIdealBounds() {
[email protected]8d625fb2012-07-18 16:40:06183 // TODO(oshima): this is wrong. Figure out what display shelf is on
184 // and everything should be based on it.
185 gfx::Rect bounds(ScreenAsh::GetDisplayParentBounds(
186 status_->GetNativeView()));
[email protected]55444502012-05-10 15:43:53187 int width = 0, height = 0;
188 GetShelfSize(&width, &height);
189 switch (alignment_) {
190 case SHELF_ALIGNMENT_BOTTOM:
191 return gfx::Rect(bounds.x(), bounds.bottom() - height,
192 bounds.width(), height);
193 case SHELF_ALIGNMENT_LEFT:
194 return gfx::Rect(bounds.x(), bounds.y(), width, bounds.height());
195 case SHELF_ALIGNMENT_RIGHT:
[email protected]54a7c5a2012-05-24 19:54:20196 return gfx::Rect(bounds.right() - width, bounds.y(), width,
197 bounds.height());
[email protected]55444502012-05-10 15:43:53198 }
199 NOTREACHED();
200 return gfx::Rect();
201}
202
[email protected]4bb16502011-12-06 14:44:58203void ShelfLayoutManager::LayoutShelf() {
204 AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
[email protected]ae18b9112011-11-07 16:59:13205 StopAnimating();
206 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40207 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04208 if (launcher_widget()) {
209 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]cd9a61c72012-05-08 19:16:59210
[email protected]d9456cb2012-03-21 16:41:04211 launcher_widget()->SetBounds(target_bounds.launcher_bounds);
[email protected]55444502012-05-10 15:43:53212 launcher_->SetStatusSize(target_bounds.status_bounds.size());
[email protected]27f6af62012-03-21 05:34:40213 }
214 GetLayer(status_)->SetOpacity(target_bounds.opacity);
[email protected]ae18b9112011-11-07 16:59:13215 status_->SetBounds(target_bounds.status_bounds);
[email protected]2e236a52012-06-27 22:21:47216 Shell::GetInstance()->SetDisplayWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50217 Shell::GetPrimaryRootWindow(),
[email protected]ae18b9112011-11-07 16:59:13218 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12219 UpdateHitTestBounds();
[email protected]ae18b9112011-11-07 16:59:13220}
221
[email protected]c758fbf2012-03-25 22:53:59222void ShelfLayoutManager::UpdateVisibilityState() {
223 ShellDelegate* delegate = Shell::GetInstance()->delegate();
224 if (delegate && delegate->IsScreenLocked()) {
225 SetState(VISIBLE);
226 } else {
227 WorkspaceManager::WindowState window_state(
228 workspace_manager_->GetWindowState());
229 switch (window_state) {
230 case WorkspaceManager::WINDOW_STATE_FULL_SCREEN:
231 SetState(HIDDEN);
232 break;
233
234 case WorkspaceManager::WINDOW_STATE_MAXIMIZED:
[email protected]09f3fc82012-03-26 23:26:56235 SetState(auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_NEVER ?
236 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59237 break;
238
239 case WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF:
240 case WorkspaceManager::WINDOW_STATE_DEFAULT:
[email protected]09f3fc82012-03-26 23:26:56241 SetState(auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS ?
242 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59243 SetWindowOverlapsShelf(window_state ==
244 WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF);
245 }
246 }
247}
248
249void ShelfLayoutManager::UpdateAutoHideState() {
[email protected]cadd8c42012-03-27 02:44:31250 AutoHideState auto_hide_state =
251 CalculateAutoHideState(state_.visibility_state);
252 if (auto_hide_state != state_.auto_hide_state) {
253 if (auto_hide_state == AUTO_HIDE_HIDDEN) {
254 // Hides happen immediately.
255 SetState(state_.visibility_state);
[email protected]cbc278f2012-07-10 03:40:21256 FOR_EACH_OBSERVER(Observer, observers_,
257 OnAutoHideStateChanged(auto_hide_state));
[email protected]cadd8c42012-03-27 02:44:31258 } else {
259 auto_hide_timer_.Stop();
[email protected]c758fbf2012-03-25 22:53:59260 auto_hide_timer_.Start(
261 FROM_HERE,
262 base::TimeDelta::FromMilliseconds(kAutoHideDelayMS),
263 this, &ShelfLayoutManager::UpdateAutoHideStateNow);
[email protected]cbc278f2012-07-10 03:40:21264 FOR_EACH_OBSERVER(Observer, observers_, OnAutoHideStateChanged(
265 CalculateAutoHideState(state_.visibility_state)));
[email protected]c758fbf2012-03-25 22:53:59266 }
267 } else {
268 auto_hide_timer_.Stop();
269 }
270}
271
272void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) {
273 window_overlaps_shelf_ = value;
274 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
275}
276
[email protected]cbc278f2012-07-10 03:40:21277void ShelfLayoutManager::AddObserver(Observer* observer) {
278 observers_.AddObserver(observer);
279}
280
281void ShelfLayoutManager::RemoveObserver(Observer* observer) {
282 observers_.RemoveObserver(observer);
283}
284
[email protected]c758fbf2012-03-25 22:53:59285////////////////////////////////////////////////////////////////////////////////
286// ShelfLayoutManager, aura::LayoutManager implementation:
287
288void ShelfLayoutManager::OnWindowResized() {
289 LayoutShelf();
290}
291
292void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
293}
294
295void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
296}
297
[email protected]fa893ab62012-04-20 01:26:51298void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
299}
300
[email protected]c758fbf2012-03-25 22:53:59301void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
302 bool visible) {
303}
304
305void ShelfLayoutManager::SetChildBounds(aura::Window* child,
306 const gfx::Rect& requested_bounds) {
307 SetChildBoundsDirect(child, requested_bounds);
308 if (!in_layout_)
309 LayoutShelf();
310}
311
[email protected]8e43cdf42012-05-11 17:03:31312void ShelfLayoutManager::OnLockStateChanged(bool locked) {
313 UpdateVisibilityState();
314}
315
[email protected]e76310a92012-06-04 19:06:11316void ShelfLayoutManager::OnWindowActivated(aura::Window* active,
317 aura::Window* old_active) {
318 UpdateAutoHideStateNow();
[email protected]8676f0472012-03-29 20:30:12319}
320
[email protected]c758fbf2012-03-25 22:53:59321////////////////////////////////////////////////////////////////////////////////
322// ShelfLayoutManager, private:
323
[email protected]8d625fb2012-07-18 16:40:06324gfx::Rect ShelfLayoutManager::GetMaximizedWindowBounds(
325 aura::Window* window) {
326 gfx::Rect bounds(ScreenAsh::GetDisplayParentBounds(window));
327 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT ||
328 auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
329 AdjustBoundsBasedOnAlignment(kAutoHideSize, &bounds);
330 return bounds;
331 }
332 // SHELF_AUTO_HIDE_BEHAVIOR_NEVER maximized windows don't get any taller.
333 return GetUnmaximizedWorkAreaBounds(window);
334}
335
336gfx::Rect ShelfLayoutManager::GetUnmaximizedWorkAreaBounds(
337 aura::Window* window) {
338 gfx::Rect bounds(ScreenAsh::GetDisplayParentBounds(window));
339 int size;
340 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
341 size = kAutoHideSize;
342 } else {
343 int width, height;
344 GetShelfSize(&width, &height);
345 size = std::max(width, height);
346 }
347 AdjustBoundsBasedOnAlignment(size, &bounds);
348 return bounds;
349}
350
[email protected]b1c37fc2012-03-22 03:36:13351void ShelfLayoutManager::SetState(VisibilityState visibility_state) {
[email protected]751444a2012-04-03 04:57:14352 ShellDelegate* delegate = Shell::GetInstance()->delegate();
[email protected]27f6af62012-03-21 05:34:40353 State state;
[email protected]c758fbf2012-03-25 22:53:59354 state.visibility_state = visibility_state;
[email protected]b1c37fc2012-03-22 03:36:13355 state.auto_hide_state = CalculateAutoHideState(visibility_state);
[email protected]751444a2012-04-03 04:57:14356 state.is_screen_locked = delegate && delegate->IsScreenLocked();
[email protected]306768162012-02-02 02:04:41357
[email protected]27f6af62012-03-21 05:34:40358 if (state_.Equals(state))
[email protected]ae18b9112011-11-07 16:59:13359 return; // Nothing changed.
360
[email protected]cbc278f2012-07-10 03:40:21361 FOR_EACH_OBSERVER(Observer, observers_,
362 WillChangeVisibilityState(visibility_state));
363
[email protected]b1c37fc2012-03-22 03:36:13364 if (state.visibility_state == AUTO_HIDE) {
365 // When state is AUTO_HIDE we need to track when the mouse is over the
366 // launcher to unhide the shelf. AutoHideEventFilter does that for us.
367 if (!event_filter_.get())
368 event_filter_.reset(new AutoHideEventFilter(this));
369 } else {
370 event_filter_.reset(NULL);
371 }
372
373 auto_hide_timer_.Stop();
374
[email protected]27f6af62012-03-21 05:34:40375 // Animating the background when transitioning from auto-hide & hidden to
376 // visibile is janking. Update the background immediately in this case.
[email protected]a160baec2012-03-21 20:52:15377 internal::BackgroundAnimator::ChangeType change_type =
[email protected]27f6af62012-03-21 05:34:40378 (state_.visibility_state == AUTO_HIDE &&
379 state_.auto_hide_state == AUTO_HIDE_HIDDEN &&
380 state.visibility_state == VISIBLE) ?
[email protected]a160baec2012-03-21 20:52:15381 internal::BackgroundAnimator::CHANGE_IMMEDIATE :
382 internal::BackgroundAnimator::CHANGE_ANIMATE;
[email protected]ae18b9112011-11-07 16:59:13383 StopAnimating();
[email protected]27f6af62012-03-21 05:34:40384 state_ = state;
[email protected]ae18b9112011-11-07 16:59:13385 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40386 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04387 if (launcher_widget()) {
[email protected]27f6af62012-03-21 05:34:40388 ui::ScopedLayerAnimationSettings launcher_animation_setter(
[email protected]d9456cb2012-03-21 16:41:04389 GetLayer(launcher_widget())->GetAnimator());
[email protected]27f6af62012-03-21 05:34:40390 launcher_animation_setter.SetTransitionDuration(
391 base::TimeDelta::FromMilliseconds(130));
392 launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59393 GetLayer(launcher_widget())->SetBounds(target_bounds.launcher_bounds);
[email protected]d9456cb2012-03-21 16:41:04394 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]27f6af62012-03-21 05:34:40395 }
[email protected]306768162012-02-02 02:04:41396 ui::ScopedLayerAnimationSettings status_animation_setter(
[email protected]27f6af62012-03-21 05:34:40397 GetLayer(status_)->GetAnimator());
398 status_animation_setter.SetTransitionDuration(
399 base::TimeDelta::FromMilliseconds(130));
400 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59401 GetLayer(status_)->SetBounds(target_bounds.status_bounds);
[email protected]27f6af62012-03-21 05:34:40402 GetLayer(status_)->SetOpacity(target_bounds.opacity);
[email protected]2e236a52012-06-27 22:21:47403 Shell::GetInstance()->SetDisplayWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50404 Shell::GetPrimaryRootWindow(),
[email protected]27f6af62012-03-21 05:34:40405 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12406 UpdateHitTestBounds();
[email protected]a160baec2012-03-21 20:52:15407 UpdateShelfBackground(change_type);
[email protected]27f6af62012-03-21 05:34:40408}
[email protected]63ef21592012-03-21 01:15:40409
[email protected]4bb16502011-12-06 14:44:58410void ShelfLayoutManager::StopAnimating() {
[email protected]d9456cb2012-03-21 16:41:04411 if (launcher_widget())
412 GetLayer(launcher_widget())->GetAnimator()->StopAnimating();
[email protected]df5954f2011-12-14 16:19:58413 GetLayer(status_)->GetAnimator()->StopAnimating();
[email protected]ae18b9112011-11-07 16:59:13414}
415
[email protected]55444502012-05-10 15:43:53416void ShelfLayoutManager::GetShelfSize(int* width, int* height) {
417 *width = *height = 0;
418 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
419 gfx::Size launcher_size = launcher_ ?
420 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
[email protected]0ab08e52012-05-19 00:04:21421 if (alignment_ == SHELF_ALIGNMENT_BOTTOM)
[email protected]55444502012-05-10 15:43:53422 *height = std::max(launcher_size.height(), status_bounds.height());
[email protected]0ab08e52012-05-19 00:04:21423 else
424 *width = std::max(launcher_size.width(), status_bounds.width());
[email protected]55444502012-05-10 15:43:53425}
426
427void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset,
428 gfx::Rect* bounds) const {
429 switch (alignment_) {
430 case SHELF_ALIGNMENT_BOTTOM:
431 bounds->Inset(gfx::Insets(0, 0, inset, 0));
432 break;
433 case SHELF_ALIGNMENT_LEFT:
434 bounds->Inset(gfx::Insets(0, inset, 0, 0));
435 break;
436 case SHELF_ALIGNMENT_RIGHT:
437 bounds->Inset(gfx::Insets(0, 0, 0, inset));
438 break;
439 }
440}
441
[email protected]27f6af62012-03-21 05:34:40442void ShelfLayoutManager::CalculateTargetBounds(
443 const State& state,
[email protected]55444502012-05-10 15:43:53444 TargetBounds* target_bounds) {
[email protected]b1c37fc2012-03-22 03:36:13445 const gfx::Rect& available_bounds(
446 status_->GetNativeView()->GetRootWindow()->bounds());
[email protected]55444502012-05-10 15:43:53447 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
448 gfx::Size launcher_size = launcher_ ?
449 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
450 int shelf_size = 0;
451 int shelf_width = 0, shelf_height = 0;
452 GetShelfSize(&shelf_width, &shelf_height);
[email protected]27f6af62012-03-21 05:34:40453 if (state.visibility_state == VISIBLE ||
454 (state.visibility_state == AUTO_HIDE &&
[email protected]55444502012-05-10 15:43:53455 state.auto_hide_state == AUTO_HIDE_SHOWN)) {
456 shelf_size = std::max(shelf_width, shelf_height);
457 } else if (state.visibility_state == AUTO_HIDE &&
458 state.auto_hide_state == AUTO_HIDE_HIDDEN) {
459 shelf_size = kAutoHideSize;
[email protected]27f6af62012-03-21 05:34:40460 }
[email protected]55444502012-05-10 15:43:53461 if (alignment_ == SHELF_ALIGNMENT_BOTTOM) {
462 int y = available_bounds.bottom();
463 y -= shelf_size;
464 // The status widget should extend to the bottom and right edges.
465 target_bounds->status_bounds = gfx::Rect(
466 base::i18n::IsRTL() ? available_bounds.x() :
467 available_bounds.right() - status_bounds.width(),
468 y + shelf_height - status_bounds.height(),
469 status_bounds.width(), status_bounds.height());
470 if (launcher_widget()) {
471 target_bounds->launcher_bounds = gfx::Rect(
472 available_bounds.x(),
473 y + (shelf_height - launcher_size.height()) / 2,
474 available_bounds.width(),
475 launcher_size.height());
476 }
477 target_bounds->work_area_insets.Set(
478 0, 0, GetWorkAreaSize(state, shelf_height), 0);
479 } else {
480 int x = (alignment_ == SHELF_ALIGNMENT_LEFT) ?
481 available_bounds.x() + shelf_size - shelf_width :
482 available_bounds.right() - shelf_size;
483 target_bounds->status_bounds = gfx::Rect(
484 x, available_bounds.bottom() - status_bounds.height(),
485 shelf_width, status_bounds.height());
486 if (launcher_widget()) {
487 target_bounds->launcher_bounds = gfx::Rect(
488 x,
489 available_bounds.y(),
490 launcher_size.width(),
491 available_bounds.height());
492 }
493 if (alignment_ == SHELF_ALIGNMENT_LEFT) {
494 target_bounds->work_area_insets.Set(
495 0, GetWorkAreaSize(state, shelf_width), 0, 0);
496 } else {
497 target_bounds->work_area_insets.Set(
498 0, 0, 0, GetWorkAreaSize(state, shelf_width));
499 }
500 }
[email protected]27f6af62012-03-21 05:34:40501 target_bounds->opacity =
502 (state.visibility_state == VISIBLE ||
503 state.visibility_state == AUTO_HIDE) ? 1.0f : 0.0f;
[email protected]ae18b9112011-11-07 16:59:13504}
505
[email protected]a160baec2012-03-21 20:52:15506void ShelfLayoutManager::UpdateShelfBackground(
507 BackgroundAnimator::ChangeType type) {
508 bool launcher_paints = GetLauncherPaintsBackground();
509 if (launcher_)
510 launcher_->SetPaintsBackground(launcher_paints, type);
511 // SystemTray normally draws a background, but we don't want it to draw a
512 // background when the launcher does.
[email protected]82a1cc92012-06-13 22:06:10513 StatusAreaWidget* status_area_widget =
514 Shell::GetInstance()->status_area_widget();
515 if (status_area_widget)
516 status_area_widget->SetPaintsBackground(!launcher_paints, type);
[email protected]a160baec2012-03-21 20:52:15517}
518
519bool ShelfLayoutManager::GetLauncherPaintsBackground() const {
[email protected]751444a2012-04-03 04:57:14520 return (!state_.is_screen_locked && window_overlaps_shelf_) ||
521 state_.visibility_state == AUTO_HIDE;
[email protected]ae18b9112011-11-07 16:59:13522}
523
[email protected]b1c37fc2012-03-22 03:36:13524void ShelfLayoutManager::UpdateAutoHideStateNow() {
525 SetState(state_.visibility_state);
526}
527
528ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState(
529 VisibilityState visibility_state) const {
530 if (visibility_state != AUTO_HIDE || !launcher_widget())
531 return AUTO_HIDE_HIDDEN;
532
533 Shell* shell = Shell::GetInstance();
[email protected]7510d1082012-03-30 21:58:34534 if (shell->GetAppListTargetVisibility())
535 return AUTO_HIDE_SHOWN;
536
[email protected]6d6546e2012-05-30 23:12:02537 if (shell->system_tray() && shell->system_tray()->should_show_launcher())
[email protected]d9d5a922012-03-26 04:38:03538 return AUTO_HIDE_SHOWN;
[email protected]b1c37fc2012-03-22 03:36:13539
[email protected]e9992b12012-03-27 00:11:27540 if (launcher_ && launcher_->IsShowingMenu())
541 return AUTO_HIDE_SHOWN;
542
[email protected]3475f5e2012-07-12 22:10:32543 if (launcher_ && launcher_->IsShowingOverflowBubble())
544 return AUTO_HIDE_SHOWN;
545
[email protected]8676f0472012-03-29 20:30:12546 if (launcher_widget()->IsActive() || status_->IsActive())
547 return AUTO_HIDE_SHOWN;
548
[email protected]5f1d99dc2012-04-12 21:42:37549 // Don't show if the user is dragging the mouse.
550 if (event_filter_.get() && event_filter_->in_mouse_drag())
551 return AUTO_HIDE_HIDDEN;
552
[email protected]b1c37fc2012-03-22 03:36:13553 aura::RootWindow* root = launcher_widget()->GetNativeView()->GetRootWindow();
554 bool mouse_over_launcher =
555 launcher_widget()->GetWindowScreenBounds().Contains(
556 root->last_mouse_location());
557 return mouse_over_launcher ? AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN;
558}
559
[email protected]128fd3732012-03-27 01:55:12560void ShelfLayoutManager::UpdateHitTestBounds() {
561 gfx::Insets insets;
562 // Only modify the hit test when the shelf is visible, so we don't mess with
563 // hover hit testing in the auto-hide state.
564 if (state_.visibility_state == VISIBLE) {
565 // Let clicks at the very top of the launcher through so windows can be
566 // resized with the bottom-right corner and bottom edge.
[email protected]55444502012-05-10 15:43:53567 switch (alignment_) {
568 case SHELF_ALIGNMENT_BOTTOM:
569 insets.Set(kWorkspaceAreaBottomInset, 0, 0, 0);
570 break;
571 case SHELF_ALIGNMENT_LEFT:
572 insets.Set(0, 0, 0, kWorkspaceAreaBottomInset);
573 break;
574 case SHELF_ALIGNMENT_RIGHT:
575 insets.Set(0, kWorkspaceAreaBottomInset, 0, 0);
576 break;
577 }
[email protected]128fd3732012-03-27 01:55:12578 }
579 if (launcher_widget() && launcher_widget()->GetNativeWindow())
580 launcher_widget()->GetNativeWindow()->set_hit_test_bounds_override_outer(
581 insets);
582 status_->GetNativeWindow()->set_hit_test_bounds_override_outer(insets);
583}
584
[email protected]5f1d99dc2012-04-12 21:42:37585bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) {
586 if (!window)
587 return false;
588 return (launcher_widget() &&
589 launcher_widget()->GetNativeWindow()->Contains(window)) ||
590 (status_ && status_->GetNativeWindow()->Contains(window));
591}
592
[email protected]55444502012-05-10 15:43:53593int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const {
594 if (state.visibility_state == VISIBLE)
595 return size;
596 if (state.visibility_state == AUTO_HIDE)
597 return kAutoHideSize;
598 return 0;
599}
600
[email protected]55f593352011-12-24 05:42:46601} // namespace internal
602} // namespace ash