blob: 8aff1aea8fd8bebd95f15909ea02b43a3e00d172 [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>
[email protected]91d966a72012-09-06 03:42:278#include <cmath>
[email protected]c2d58b42012-05-30 08:11:299
[email protected]fd422702012-09-25 17:45:1410#include "ash/ash_switches.h"
[email protected]7634f962011-12-23 21:35:5211#include "ash/launcher/launcher.h"
[email protected]88d71122012-10-18 07:11:0112#include "ash/root_window_controller.h"
[email protected]1a2145b2012-03-13 21:09:1713#include "ash/screen_ash.h"
[email protected]b65bdda2011-12-23 23:35:3114#include "ash/shell.h"
[email protected]c758fbf2012-03-25 22:53:5915#include "ash/shell_delegate.h"
16#include "ash/shell_window_ids.h"
[email protected]6d6546e2012-05-30 23:12:0217#include "ash/system/status_area_widget.h"
[email protected]f4bb9fde2012-08-03 19:33:5018#include "ash/wm/workspace_controller.h"
[email protected]ba38e002012-10-12 16:39:4119#include "ash/wm/workspace/workspace_animations.h"
[email protected]4bb16502011-12-06 14:44:5820#include "base/auto_reset.h"
[email protected]fd422702012-09-25 17:45:1421#include "base/command_line.h"
[email protected]e24b6092012-04-12 18:58:5122#include "base/i18n/rtl.h"
[email protected]8676f0472012-03-29 20:30:1223#include "ui/aura/client/activation_client.h"
[email protected]b1c37fc2012-03-22 03:36:1324#include "ui/aura/event_filter.h"
[email protected]99f07e02011-12-07 00:02:5925#include "ui/aura/root_window.h"
[email protected]153472d72012-09-04 21:33:0226#include "ui/base/events/event.h"
[email protected]116302fc2012-05-05 21:45:4127#include "ui/compositor/layer.h"
28#include "ui/compositor/layer_animation_observer.h"
29#include "ui/compositor/layer_animator.h"
30#include "ui/compositor/scoped_layer_animation_settings.h"
[email protected]b82c42c42012-04-25 20:03:4131#include "ui/gfx/screen.h"
[email protected]c13be0d2011-11-22 02:09:5832#include "ui/views/widget/widget.h"
[email protected]ae18b9112011-11-07 16:59:1333
[email protected]55f593352011-12-24 05:42:4634namespace ash {
[email protected]ae18b9112011-11-07 16:59:1335namespace internal {
36
37namespace {
38
[email protected]cadd8c42012-03-27 02:44:3139// Delay before showing the launcher. This is after the mouse stops moving.
40const int kAutoHideDelayMS = 200;
[email protected]27f6af62012-03-21 05:34:4041
[email protected]2e195f52012-09-22 00:24:4642// To avoid hiding the shelf when the mouse transitions from a message bubble
43// into the shelf, the hit test area is enlarged by this amount of pixels to
44// keep the shelf from hiding.
45const int kNotificationBubbleGapHeight = 6;
46
[email protected]ae18b9112011-11-07 16:59:1347ui::Layer* GetLayer(views::Widget* widget) {
48 return widget->GetNativeView()->layer();
49}
50
[email protected]fd422702012-09-25 17:45:1451bool IsDraggingTrayEnabled() {
52 static bool dragging_tray_allowed = CommandLine::ForCurrentProcess()->
53 HasSwitch(ash::switches::kAshEnableTrayDragging);
54 return dragging_tray_allowed;
55}
56
[email protected]ae18b9112011-11-07 16:59:1357} // namespace
58
[email protected]bbb59f82012-03-14 04:04:3559// static
60const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2;
61
[email protected]b1c37fc2012-03-22 03:36:1362// static
[email protected]7b675df612012-09-16 18:33:2063const int ShelfLayoutManager::kAutoHideSize = 3;
[email protected]b1c37fc2012-03-22 03:36:1364
[email protected]e4d9fe92012-09-10 14:04:4965// ShelfLayoutManager::AutoHideEventFilter -------------------------------------
66
[email protected]b1c37fc2012-03-22 03:36:1367// Notifies ShelfLayoutManager any time the mouse moves.
68class ShelfLayoutManager::AutoHideEventFilter : public aura::EventFilter {
69 public:
70 explicit AutoHideEventFilter(ShelfLayoutManager* shelf);
71 virtual ~AutoHideEventFilter();
72
[email protected]5f1d99dc2012-04-12 21:42:3773 // Returns true if the last mouse event was a mouse drag.
74 bool in_mouse_drag() const { return in_mouse_drag_; }
75
[email protected]b1c37fc2012-03-22 03:36:1376 // Overridden from aura::EventFilter:
77 virtual bool PreHandleKeyEvent(aura::Window* target,
[email protected]ca7060982012-08-08 18:05:2578 ui::KeyEvent* event) OVERRIDE;
[email protected]b1c37fc2012-03-22 03:36:1379 virtual bool PreHandleMouseEvent(aura::Window* target,
[email protected]ca7060982012-08-08 18:05:2580 ui::MouseEvent* event) OVERRIDE;
81 virtual ui::TouchStatus PreHandleTouchEvent(
82 aura::Window* target,
[email protected]8ca8d2462012-08-09 22:28:0483 ui::TouchEvent* event) OVERRIDE;
[email protected]5b174e0a2012-09-04 01:14:4384 virtual ui::EventResult PreHandleGestureEvent(
[email protected]b1c37fc2012-03-22 03:36:1385 aura::Window* target,
[email protected]2487bee42012-08-10 16:21:4486 ui::GestureEvent* event) OVERRIDE;
[email protected]b1c37fc2012-03-22 03:36:1387
88 private:
89 ShelfLayoutManager* shelf_;
[email protected]5f1d99dc2012-04-12 21:42:3790 bool in_mouse_drag_;
[email protected]b1c37fc2012-03-22 03:36:1391
92 DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter);
93};
94
95ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter(
96 ShelfLayoutManager* shelf)
[email protected]5f1d99dc2012-04-12 21:42:3797 : shelf_(shelf),
98 in_mouse_drag_(false) {
[email protected]1aad3322012-06-06 06:37:0999 Shell::GetInstance()->AddEnvEventFilter(this);
[email protected]b1c37fc2012-03-22 03:36:13100}
101
102ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() {
[email protected]1aad3322012-06-06 06:37:09103 Shell::GetInstance()->RemoveEnvEventFilter(this);
[email protected]b1c37fc2012-03-22 03:36:13104}
105
106bool ShelfLayoutManager::AutoHideEventFilter::PreHandleKeyEvent(
107 aura::Window* target,
[email protected]ca7060982012-08-08 18:05:25108 ui::KeyEvent* event) {
[email protected]b1c37fc2012-03-22 03:36:13109 return false; // Always let the event propagate.
110}
111
112bool ShelfLayoutManager::AutoHideEventFilter::PreHandleMouseEvent(
113 aura::Window* target,
[email protected]ca7060982012-08-08 18:05:25114 ui::MouseEvent* event) {
[email protected]5f1d99dc2012-04-12 21:42:37115 // This also checks IsShelfWindow() to make sure we don't attempt to hide the
116 // shelf if the mouse down occurs on the shelf.
117 in_mouse_drag_ = (event->type() == ui::ET_MOUSE_DRAGGED ||
118 (in_mouse_drag_ && event->type() != ui::ET_MOUSE_RELEASED &&
119 event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)) &&
120 !shelf_->IsShelfWindow(target);
[email protected]b1c37fc2012-03-22 03:36:13121 if (event->type() == ui::ET_MOUSE_MOVED)
122 shelf_->UpdateAutoHideState();
123 return false; // Not handled.
124}
125
126ui::TouchStatus ShelfLayoutManager::AutoHideEventFilter::PreHandleTouchEvent(
127 aura::Window* target,
[email protected]8ca8d2462012-08-09 22:28:04128 ui::TouchEvent* event) {
[email protected]b1c37fc2012-03-22 03:36:13129 return ui::TOUCH_STATUS_UNKNOWN; // Not handled.
130}
131
[email protected]5b174e0a2012-09-04 01:14:43132ui::EventResult
[email protected]b1c37fc2012-03-22 03:36:13133ShelfLayoutManager::AutoHideEventFilter::PreHandleGestureEvent(
134 aura::Window* target,
[email protected]2487bee42012-08-10 16:21:44135 ui::GestureEvent* event) {
[email protected]5b174e0a2012-09-04 01:14:43136 return ui::ER_UNHANDLED; // Not handled.
[email protected]b1c37fc2012-03-22 03:36:13137}
138
[email protected]e4d9fe92012-09-10 14:04:49139// ShelfLayoutManager:UpdateShelfObserver --------------------------------------
140
141// UpdateShelfObserver is used to delay updating the background until the
142// animation completes.
143class ShelfLayoutManager::UpdateShelfObserver
144 : public ui::ImplicitAnimationObserver {
145 public:
146 explicit UpdateShelfObserver(ShelfLayoutManager* shelf) : shelf_(shelf) {
147 shelf_->update_shelf_observer_ = this;
148 }
149
150 void Detach() {
151 shelf_ = NULL;
152 }
153
154 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
155 if (shelf_) {
156 shelf_->UpdateShelfBackground(
157 internal::BackgroundAnimator::CHANGE_ANIMATE);
158 }
159 delete this;
160 }
161
162 private:
163 virtual ~UpdateShelfObserver() {
164 if (shelf_)
165 shelf_->update_shelf_observer_ = NULL;
166 }
167
168 // Shelf we're in. NULL if deleted before we're deleted.
169 ShelfLayoutManager* shelf_;
170
171 DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver);
172};
173
174// ShelfLayoutManager ----------------------------------------------------------
[email protected]4bb16502011-12-06 14:44:58175
[email protected]88d71122012-10-18 07:11:01176ShelfLayoutManager::ShelfLayoutManager(StatusAreaWidget* status_area_widget)
177 : root_window_(status_area_widget->GetNativeView()->GetRootWindow()),
[email protected]8676f0472012-03-29 20:30:12178 in_layout_(false),
[email protected]eefd51b22012-09-25 20:26:24179 auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER),
[email protected]55444502012-05-10 15:43:53180 alignment_(SHELF_ALIGNMENT_BOTTOM),
[email protected]27f6af62012-03-21 05:34:40181 launcher_(NULL),
[email protected]88d71122012-10-18 07:11:01182 status_area_widget_(status_area_widget),
[email protected]f4bb9fde2012-08-03 19:33:50183 workspace_controller_(NULL),
[email protected]3c6abbe2012-08-30 23:48:57184 window_overlaps_shelf_(false),
185 gesture_drag_status_(GESTURE_DRAG_NONE),
[email protected]4982ee12012-09-04 22:16:10186 gesture_drag_amount_(0.f),
[email protected]e4d9fe92012-09-10 14:04:49187 gesture_drag_auto_hide_state_(AUTO_HIDE_SHOWN),
188 update_shelf_observer_(NULL) {
[email protected]8e43cdf42012-05-11 17:03:31189 Shell::GetInstance()->AddShellObserver(this);
[email protected]e76310a92012-06-04 19:06:11190 aura::client::GetActivationClient(root_window_)->AddObserver(this);
[email protected]ae18b9112011-11-07 16:59:13191}
192
[email protected]4bb16502011-12-06 14:44:58193ShelfLayoutManager::~ShelfLayoutManager() {
[email protected]e4d9fe92012-09-10 14:04:49194 if (update_shelf_observer_)
195 update_shelf_observer_->Detach();
196
[email protected]cbc278f2012-07-10 03:40:21197 FOR_EACH_OBSERVER(Observer, observers_, WillDeleteShelf());
[email protected]8e43cdf42012-05-11 17:03:31198 Shell::GetInstance()->RemoveShellObserver(this);
[email protected]e76310a92012-06-04 19:06:11199 aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
[email protected]ae18b9112011-11-07 16:59:13200}
201
[email protected]09f3fc82012-03-26 23:26:56202void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) {
203 if (auto_hide_behavior_ == behavior)
[email protected]c758fbf2012-03-25 22:53:59204 return;
[email protected]09f3fc82012-03-26 23:26:56205 auto_hide_behavior_ = behavior;
[email protected]c758fbf2012-03-25 22:53:59206 UpdateVisibilityState();
[email protected]cbc278f2012-07-10 03:40:21207 FOR_EACH_OBSERVER(Observer, observers_,
208 OnAutoHideStateChanged(state_.auto_hide_state));
[email protected]c758fbf2012-03-25 22:53:59209}
210
[email protected]40429f02012-03-28 20:38:50211bool ShelfLayoutManager::IsVisible() const {
[email protected]88d71122012-10-18 07:11:01212 return status_area_widget_->IsVisible() &&
213 (state_.visibility_state == VISIBLE ||
214 (state_.visibility_state == AUTO_HIDE &&
215 state_.auto_hide_state == AUTO_HIDE_SHOWN));
[email protected]40429f02012-03-28 20:38:50216}
217
[email protected]d9456cb2012-03-21 16:41:04218void ShelfLayoutManager::SetLauncher(Launcher* launcher) {
219 if (launcher == launcher_)
220 return;
221
222 launcher_ = launcher;
[email protected]a5c63ce82012-07-18 18:48:57223 if (launcher_)
224 launcher_->SetAlignment(alignment_);
[email protected]d9456cb2012-03-21 16:41:04225 LayoutShelf();
226}
227
[email protected]c2d58b42012-05-30 08:11:29228bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) {
[email protected]55444502012-05-10 15:43:53229 if (alignment_ == alignment)
[email protected]c2d58b42012-05-30 08:11:29230 return false;
[email protected]55444502012-05-10 15:43:53231
232 alignment_ = alignment;
233 if (launcher_)
234 launcher_->SetAlignment(alignment);
[email protected]88d71122012-10-18 07:11:01235 status_area_widget_->SetShelfAlignment(alignment);
[email protected]55444502012-05-10 15:43:53236 LayoutShelf();
[email protected]c2d58b42012-05-30 08:11:29237 return true;
[email protected]55444502012-05-10 15:43:53238}
239
240gfx::Rect ShelfLayoutManager::GetIdealBounds() {
[email protected]8d625fb2012-07-18 16:40:06241 // TODO(oshima): this is wrong. Figure out what display shelf is on
242 // and everything should be based on it.
[email protected]e2f64d102012-07-19 19:17:04243 gfx::Rect bounds(ScreenAsh::GetDisplayBoundsInParent(
[email protected]88d71122012-10-18 07:11:01244 status_area_widget_->GetNativeView()));
[email protected]55444502012-05-10 15:43:53245 int width = 0, height = 0;
246 GetShelfSize(&width, &height);
247 switch (alignment_) {
248 case SHELF_ALIGNMENT_BOTTOM:
249 return gfx::Rect(bounds.x(), bounds.bottom() - height,
250 bounds.width(), height);
251 case SHELF_ALIGNMENT_LEFT:
252 return gfx::Rect(bounds.x(), bounds.y(), width, bounds.height());
253 case SHELF_ALIGNMENT_RIGHT:
[email protected]54a7c5a2012-05-24 19:54:20254 return gfx::Rect(bounds.right() - width, bounds.y(), width,
255 bounds.height());
[email protected]55444502012-05-10 15:43:53256 }
257 NOTREACHED();
258 return gfx::Rect();
259}
260
[email protected]4bb16502011-12-06 14:44:58261void ShelfLayoutManager::LayoutShelf() {
262 AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
[email protected]ae18b9112011-11-07 16:59:13263 StopAnimating();
264 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40265 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04266 if (launcher_widget()) {
267 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]b7d08122012-09-16 18:24:46268 launcher_->SetWidgetBounds(
[email protected]ec1930c32012-07-19 23:57:42269 ScreenAsh::ConvertRectToScreen(
270 launcher_widget()->GetNativeView()->parent(),
271 target_bounds.launcher_bounds_in_root));
272 launcher_->SetStatusSize(target_bounds.status_bounds_in_root.size());
[email protected]27f6af62012-03-21 05:34:40273 }
[email protected]88d71122012-10-18 07:11:01274 GetLayer(status_area_widget_)->SetOpacity(target_bounds.opacity);
275 status_area_widget_->SetBounds(
[email protected]ec1930c32012-07-19 23:57:42276 ScreenAsh::ConvertRectToScreen(
[email protected]88d71122012-10-18 07:11:01277 status_area_widget_->GetNativeView()->parent(),
[email protected]ec1930c32012-07-19 23:57:42278 target_bounds.status_bounds_in_root));
[email protected]2e236a52012-06-27 22:21:47279 Shell::GetInstance()->SetDisplayWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50280 Shell::GetPrimaryRootWindow(),
[email protected]ae18b9112011-11-07 16:59:13281 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12282 UpdateHitTestBounds();
[email protected]ae18b9112011-11-07 16:59:13283}
284
[email protected]c758fbf2012-03-25 22:53:59285void ShelfLayoutManager::UpdateVisibilityState() {
286 ShellDelegate* delegate = Shell::GetInstance()->delegate();
287 if (delegate && delegate->IsScreenLocked()) {
288 SetState(VISIBLE);
[email protected]4982ee12012-09-04 22:16:10289 } else if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS) {
[email protected]3c6abbe2012-08-30 23:48:57290 SetState(AUTO_HIDE);
[email protected]c758fbf2012-03-25 22:53:59291 } else {
[email protected]f4bb9fde2012-08-03 19:33:50292 WorkspaceWindowState window_state(workspace_controller_->GetWindowState());
[email protected]c758fbf2012-03-25 22:53:59293 switch (window_state) {
[email protected]f4bb9fde2012-08-03 19:33:50294 case WORKSPACE_WINDOW_STATE_FULL_SCREEN:
[email protected]c758fbf2012-03-25 22:53:59295 SetState(HIDDEN);
296 break;
297
[email protected]f4bb9fde2012-08-03 19:33:50298 case WORKSPACE_WINDOW_STATE_MAXIMIZED:
[email protected]eefd51b22012-09-25 20:26:24299 SetState(auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS ?
300 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59301 break;
302
[email protected]f4bb9fde2012-08-03 19:33:50303 case WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF:
304 case WORKSPACE_WINDOW_STATE_DEFAULT:
[email protected]09f3fc82012-03-26 23:26:56305 SetState(auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS ?
306 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59307 SetWindowOverlapsShelf(window_state ==
[email protected]f4bb9fde2012-08-03 19:33:50308 WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF);
[email protected]e4d9fe92012-09-10 14:04:49309 break;
[email protected]c758fbf2012-03-25 22:53:59310 }
311 }
312}
313
314void ShelfLayoutManager::UpdateAutoHideState() {
[email protected]cadd8c42012-03-27 02:44:31315 AutoHideState auto_hide_state =
316 CalculateAutoHideState(state_.visibility_state);
317 if (auto_hide_state != state_.auto_hide_state) {
318 if (auto_hide_state == AUTO_HIDE_HIDDEN) {
319 // Hides happen immediately.
320 SetState(state_.visibility_state);
[email protected]cbc278f2012-07-10 03:40:21321 FOR_EACH_OBSERVER(Observer, observers_,
322 OnAutoHideStateChanged(auto_hide_state));
[email protected]cadd8c42012-03-27 02:44:31323 } else {
324 auto_hide_timer_.Stop();
[email protected]c758fbf2012-03-25 22:53:59325 auto_hide_timer_.Start(
326 FROM_HERE,
327 base::TimeDelta::FromMilliseconds(kAutoHideDelayMS),
328 this, &ShelfLayoutManager::UpdateAutoHideStateNow);
[email protected]cbc278f2012-07-10 03:40:21329 FOR_EACH_OBSERVER(Observer, observers_, OnAutoHideStateChanged(
330 CalculateAutoHideState(state_.visibility_state)));
[email protected]c758fbf2012-03-25 22:53:59331 }
332 } else {
333 auto_hide_timer_.Stop();
334 }
335}
336
337void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) {
338 window_overlaps_shelf_ = value;
339 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
340}
341
[email protected]cbc278f2012-07-10 03:40:21342void ShelfLayoutManager::AddObserver(Observer* observer) {
343 observers_.AddObserver(observer);
344}
345
346void ShelfLayoutManager::RemoveObserver(Observer* observer) {
347 observers_.RemoveObserver(observer);
348}
349
[email protected]c758fbf2012-03-25 22:53:59350////////////////////////////////////////////////////////////////////////////////
[email protected]3c6abbe2012-08-30 23:48:57351// ShelfLayoutManager, Gesture dragging:
352
353void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) {
354 gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS;
355 gesture_drag_amount_ = 0.f;
[email protected]4982ee12012-09-04 22:16:10356 gesture_drag_auto_hide_state_ = visibility_state() == AUTO_HIDE ?
357 auto_hide_state() : AUTO_HIDE_SHOWN;
[email protected]3c6abbe2012-08-30 23:48:57358 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
359}
360
[email protected]c8e2e832012-09-12 21:48:28361ShelfLayoutManager::DragState ShelfLayoutManager::UpdateGestureDrag(
362 const ui::GestureEvent& gesture) {
[email protected]3c6abbe2012-08-30 23:48:57363 bool horizontal = alignment() == SHELF_ALIGNMENT_BOTTOM;
364 gesture_drag_amount_ += horizontal ? gesture.details().scroll_y() :
365 gesture.details().scroll_x();
366 LayoutShelf();
[email protected]c8e2e832012-09-12 21:48:28367
368 // Start reveling the status menu when:
369 // - dragging up on an already visible shelf
370 // - dragging up on a hidden shelf, but it is currently completely visible.
371 if (horizontal && gesture.details().scroll_y() < 0) {
372 int min_height = 0;
373 if (gesture_drag_auto_hide_state_ == AUTO_HIDE_HIDDEN && launcher_widget())
374 min_height = launcher_widget()->GetContentsView()->
375 GetPreferredSize().height();
376
377 if (min_height < launcher_widget()->GetWindowBoundsInScreen().height() &&
[email protected]88d71122012-10-18 07:11:01378 gesture.root_location().x() >=
379 status_area_widget_->GetWindowBoundsInScreen().x() &&
[email protected]fd422702012-09-25 17:45:14380 IsDraggingTrayEnabled())
[email protected]c8e2e832012-09-12 21:48:28381 return DRAG_TRAY;
382 }
383
384 return DRAG_SHELF;
[email protected]3c6abbe2012-08-30 23:48:57385}
386
[email protected]4982ee12012-09-04 22:16:10387void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) {
[email protected]3c6abbe2012-08-30 23:48:57388 bool horizontal = alignment() == SHELF_ALIGNMENT_BOTTOM;
[email protected]4982ee12012-09-04 22:16:10389 bool should_change = false;
[email protected]3c6abbe2012-08-30 23:48:57390 if (gesture.type() == ui::ET_GESTURE_SCROLL_END) {
391 // If the shelf was dragged X% towards the correct direction, then it is
[email protected]4982ee12012-09-04 22:16:10392 // hidden/shown.
[email protected]3c6abbe2012-08-30 23:48:57393 const float kDragHideThreshold = 0.4f;
394 gfx::Rect bounds = GetIdealBounds();
[email protected]4982ee12012-09-04 22:16:10395 float drag_amount = gesture_drag_auto_hide_state_ == AUTO_HIDE_SHOWN ?
396 gesture_drag_amount_ : -gesture_drag_amount_;
[email protected]3c6abbe2012-08-30 23:48:57397 if (horizontal)
[email protected]4982ee12012-09-04 22:16:10398 should_change = drag_amount > kDragHideThreshold * bounds.height();
[email protected]3c6abbe2012-08-30 23:48:57399 else if (alignment() == SHELF_ALIGNMENT_LEFT)
[email protected]4982ee12012-09-04 22:16:10400 should_change = -drag_amount > kDragHideThreshold * bounds.width();
[email protected]3c6abbe2012-08-30 23:48:57401 else
[email protected]4982ee12012-09-04 22:16:10402 should_change = drag_amount > kDragHideThreshold * bounds.width();
[email protected]3c6abbe2012-08-30 23:48:57403 } else if (gesture.type() == ui::ET_SCROLL_FLING_START) {
404 if (horizontal)
[email protected]4982ee12012-09-04 22:16:10405 should_change = gesture.details().velocity_y() > 0;
[email protected]3c6abbe2012-08-30 23:48:57406 else if (alignment() == SHELF_ALIGNMENT_LEFT)
[email protected]4982ee12012-09-04 22:16:10407 should_change = gesture.details().velocity_x() < 0;
[email protected]3c6abbe2012-08-30 23:48:57408 else
[email protected]4982ee12012-09-04 22:16:10409 should_change = gesture.details().velocity_x() > 0;
410 if (gesture_drag_auto_hide_state_ == AUTO_HIDE_HIDDEN)
411 should_change = !should_change;
[email protected]3c6abbe2012-08-30 23:48:57412 } else {
413 NOTREACHED();
414 }
415
[email protected]4982ee12012-09-04 22:16:10416 if (!should_change) {
[email protected]3c6abbe2012-08-30 23:48:57417 CancelGestureDrag();
418 return;
419 }
420
[email protected]4982ee12012-09-04 22:16:10421 gesture_drag_auto_hide_state_ =
422 gesture_drag_auto_hide_state_ == AUTO_HIDE_SHOWN ? AUTO_HIDE_HIDDEN :
423 AUTO_HIDE_SHOWN;
[email protected]3c6abbe2012-08-30 23:48:57424 if (launcher_widget())
425 launcher_widget()->Deactivate();
[email protected]88d71122012-10-18 07:11:01426 status_area_widget_->Deactivate();
[email protected]e10392c2012-09-11 21:13:08427 if (gesture_drag_auto_hide_state_ == AUTO_HIDE_HIDDEN &&
428 auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
429 gesture_drag_status_ = GESTURE_DRAG_NONE;
[email protected]3c6abbe2012-08-30 23:48:57430 SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
[email protected]e10392c2012-09-11 21:13:08431 } else if (gesture_drag_auto_hide_state_ == AUTO_HIDE_SHOWN &&
432 auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_NEVER) {
433 gesture_drag_status_ = GESTURE_DRAG_NONE;
434 SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
435 } else {
436 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS;
[email protected]3c6abbe2012-08-30 23:48:57437 UpdateVisibilityState();
[email protected]e10392c2012-09-11 21:13:08438 gesture_drag_status_ = GESTURE_DRAG_NONE;
439 }
[email protected]3c6abbe2012-08-30 23:48:57440}
441
442void ShelfLayoutManager::CancelGestureDrag() {
[email protected]e10392c2012-09-11 21:13:08443 gesture_drag_status_ = GESTURE_DRAG_NONE;
[email protected]3c6abbe2012-08-30 23:48:57444 ui::ScopedLayerAnimationSettings
445 launcher_settings(GetLayer(launcher_widget())->GetAnimator()),
[email protected]88d71122012-10-18 07:11:01446 status_settings(GetLayer(status_area_widget_)->GetAnimator());
[email protected]3c6abbe2012-08-30 23:48:57447 LayoutShelf();
448 UpdateVisibilityState();
449 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
450}
451
452////////////////////////////////////////////////////////////////////////////////
[email protected]c758fbf2012-03-25 22:53:59453// ShelfLayoutManager, aura::LayoutManager implementation:
454
455void ShelfLayoutManager::OnWindowResized() {
456 LayoutShelf();
457}
458
459void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
460}
461
462void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
463}
464
[email protected]fa893ab62012-04-20 01:26:51465void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
466}
467
[email protected]c758fbf2012-03-25 22:53:59468void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
469 bool visible) {
470}
471
472void ShelfLayoutManager::SetChildBounds(aura::Window* child,
473 const gfx::Rect& requested_bounds) {
474 SetChildBoundsDirect(child, requested_bounds);
[email protected]9d9b3202012-09-09 22:39:32475 // We may contain other widgets (such as frame maximize bubble) but they don't
476 // effect the layout in anyway.
477 if (!in_layout_ &&
478 ((launcher_widget() && launcher_widget()->GetNativeView() == child) ||
[email protected]88d71122012-10-18 07:11:01479 (status_area_widget_->GetNativeView() == child))) {
[email protected]c758fbf2012-03-25 22:53:59480 LayoutShelf();
[email protected]9d9b3202012-09-09 22:39:32481 }
[email protected]c758fbf2012-03-25 22:53:59482}
483
[email protected]8e43cdf42012-05-11 17:03:31484void ShelfLayoutManager::OnLockStateChanged(bool locked) {
485 UpdateVisibilityState();
486}
487
[email protected]e76310a92012-06-04 19:06:11488void ShelfLayoutManager::OnWindowActivated(aura::Window* active,
489 aura::Window* old_active) {
490 UpdateAutoHideStateNow();
[email protected]8676f0472012-03-29 20:30:12491}
492
[email protected]c758fbf2012-03-25 22:53:59493////////////////////////////////////////////////////////////////////////////////
494// ShelfLayoutManager, private:
495
[email protected]9e52129b92012-08-09 16:14:30496ShelfLayoutManager::TargetBounds::TargetBounds() : opacity(0.0f) {}
497
[email protected]b1c37fc2012-03-22 03:36:13498void ShelfLayoutManager::SetState(VisibilityState visibility_state) {
[email protected]751444a2012-04-03 04:57:14499 ShellDelegate* delegate = Shell::GetInstance()->delegate();
[email protected]27f6af62012-03-21 05:34:40500 State state;
[email protected]c758fbf2012-03-25 22:53:59501 state.visibility_state = visibility_state;
[email protected]b1c37fc2012-03-22 03:36:13502 state.auto_hide_state = CalculateAutoHideState(visibility_state);
[email protected]751444a2012-04-03 04:57:14503 state.is_screen_locked = delegate && delegate->IsScreenLocked();
[email protected]306768162012-02-02 02:04:41504
[email protected]b7d08122012-09-16 18:24:46505 // It's possible for SetState() when a window becomes maximized but the state
506 // won't have changed value. Do the dimming check before the early exit.
507 if (launcher_ && workspace_controller_) {
508 launcher_->SetDimsShelf(
509 (state.visibility_state == VISIBLE) &&
510 workspace_controller_->GetWindowState() ==
511 WORKSPACE_WINDOW_STATE_MAXIMIZED);
512 }
513
[email protected]27f6af62012-03-21 05:34:40514 if (state_.Equals(state))
[email protected]ae18b9112011-11-07 16:59:13515 return; // Nothing changed.
516
[email protected]cbc278f2012-07-10 03:40:21517 FOR_EACH_OBSERVER(Observer, observers_,
518 WillChangeVisibilityState(visibility_state));
519
[email protected]b1c37fc2012-03-22 03:36:13520 if (state.visibility_state == AUTO_HIDE) {
521 // When state is AUTO_HIDE we need to track when the mouse is over the
522 // launcher to unhide the shelf. AutoHideEventFilter does that for us.
523 if (!event_filter_.get())
524 event_filter_.reset(new AutoHideEventFilter(this));
525 } else {
526 event_filter_.reset(NULL);
527 }
528
529 auto_hide_timer_.Stop();
530
[email protected]27f6af62012-03-21 05:34:40531 // Animating the background when transitioning from auto-hide & hidden to
[email protected]e4d9fe92012-09-10 14:04:49532 // visible is janky. Update the background immediately in this case.
[email protected]a160baec2012-03-21 20:52:15533 internal::BackgroundAnimator::ChangeType change_type =
[email protected]27f6af62012-03-21 05:34:40534 (state_.visibility_state == AUTO_HIDE &&
535 state_.auto_hide_state == AUTO_HIDE_HIDDEN &&
536 state.visibility_state == VISIBLE) ?
[email protected]a160baec2012-03-21 20:52:15537 internal::BackgroundAnimator::CHANGE_IMMEDIATE :
538 internal::BackgroundAnimator::CHANGE_ANIMATE;
[email protected]ae18b9112011-11-07 16:59:13539 StopAnimating();
[email protected]e10392c2012-09-11 21:13:08540
541 State old_state = state_;
[email protected]27f6af62012-03-21 05:34:40542 state_ = state;
[email protected]ae18b9112011-11-07 16:59:13543 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40544 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04545 if (launcher_widget()) {
[email protected]27f6af62012-03-21 05:34:40546 ui::ScopedLayerAnimationSettings launcher_animation_setter(
[email protected]d9456cb2012-03-21 16:41:04547 GetLayer(launcher_widget())->GetAnimator());
[email protected]27f6af62012-03-21 05:34:40548 launcher_animation_setter.SetTransitionDuration(
[email protected]c96b9812012-10-17 16:04:04549 base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS));
[email protected]27f6af62012-03-21 05:34:40550 launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]ec1930c32012-07-19 23:57:42551 GetLayer(launcher_widget())->SetBounds(
552 target_bounds.launcher_bounds_in_root);
[email protected]d9456cb2012-03-21 16:41:04553 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]27f6af62012-03-21 05:34:40554 }
[email protected]306768162012-02-02 02:04:41555 ui::ScopedLayerAnimationSettings status_animation_setter(
[email protected]88d71122012-10-18 07:11:01556 GetLayer(status_area_widget_)->GetAnimator());
[email protected]27f6af62012-03-21 05:34:40557 status_animation_setter.SetTransitionDuration(
[email protected]c96b9812012-10-17 16:04:04558 base::TimeDelta::FromMilliseconds(kWorkspaceSwitchTimeMS));
[email protected]27f6af62012-03-21 05:34:40559 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]e10392c2012-09-11 21:13:08560
[email protected]e4d9fe92012-09-10 14:04:49561 // Delay updating the background when going from AUTO_HIDE_SHOWN to
562 // AUTO_HIDE_HIDDEN until the shelf animates out. Otherwise during the
563 // animation you see the background change.
[email protected]e10392c2012-09-11 21:13:08564 // Also delay the animation when the shelf was hidden, and has just been made
565 // visible (e.g. using a gesture-drag).
566 bool delay_shelf_update =
567 state.visibility_state == AUTO_HIDE &&
[email protected]e4d9fe92012-09-10 14:04:49568 state.auto_hide_state == AUTO_HIDE_HIDDEN &&
[email protected]e10392c2012-09-11 21:13:08569 old_state.visibility_state == AUTO_HIDE;
570
571 if (state.visibility_state == VISIBLE &&
572 old_state.visibility_state == AUTO_HIDE &&
573 old_state.auto_hide_state == AUTO_HIDE_HIDDEN)
574 delay_shelf_update = true;
575
[email protected]e4d9fe92012-09-10 14:04:49576 if (delay_shelf_update) {
577 if (update_shelf_observer_)
578 update_shelf_observer_->Detach();
579 // UpdateShelfBackground deletes itself when the animation is done.
580 update_shelf_observer_ = new UpdateShelfObserver(this);
581 status_animation_setter.AddObserver(update_shelf_observer_);
582 }
[email protected]88d71122012-10-18 07:11:01583 ui::Layer* layer = GetLayer(status_area_widget_);
584 layer->SetBounds(target_bounds.status_bounds_in_root);
585 layer->SetOpacity(target_bounds.opacity);
[email protected]2e236a52012-06-27 22:21:47586 Shell::GetInstance()->SetDisplayWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50587 Shell::GetPrimaryRootWindow(),
[email protected]27f6af62012-03-21 05:34:40588 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12589 UpdateHitTestBounds();
[email protected]e4d9fe92012-09-10 14:04:49590 if (!delay_shelf_update)
591 UpdateShelfBackground(change_type);
[email protected]27f6af62012-03-21 05:34:40592}
[email protected]63ef21592012-03-21 01:15:40593
[email protected]4bb16502011-12-06 14:44:58594void ShelfLayoutManager::StopAnimating() {
[email protected]88d71122012-10-18 07:11:01595 ui::Layer* layer = GetLayer(status_area_widget_);
[email protected]d9456cb2012-03-21 16:41:04596 if (launcher_widget())
[email protected]88d71122012-10-18 07:11:01597 layer->GetAnimator()->StopAnimating();
598 layer->GetAnimator()->StopAnimating();
[email protected]ae18b9112011-11-07 16:59:13599}
600
[email protected]55444502012-05-10 15:43:53601void ShelfLayoutManager::GetShelfSize(int* width, int* height) {
602 *width = *height = 0;
[email protected]88d71122012-10-18 07:11:01603 gfx::Size status_size(status_area_widget_->GetWindowBoundsInScreen().size());
[email protected]55444502012-05-10 15:43:53604 gfx::Size launcher_size = launcher_ ?
605 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
[email protected]0ab08e52012-05-19 00:04:21606 if (alignment_ == SHELF_ALIGNMENT_BOTTOM)
[email protected]ec1930c32012-07-19 23:57:42607 *height = std::max(launcher_size.height(), status_size.height());
[email protected]0ab08e52012-05-19 00:04:21608 else
[email protected]ec1930c32012-07-19 23:57:42609 *width = std::max(launcher_size.width(), status_size.width());
[email protected]55444502012-05-10 15:43:53610}
611
612void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset,
613 gfx::Rect* bounds) const {
614 switch (alignment_) {
615 case SHELF_ALIGNMENT_BOTTOM:
616 bounds->Inset(gfx::Insets(0, 0, inset, 0));
617 break;
618 case SHELF_ALIGNMENT_LEFT:
619 bounds->Inset(gfx::Insets(0, inset, 0, 0));
620 break;
621 case SHELF_ALIGNMENT_RIGHT:
622 bounds->Inset(gfx::Insets(0, 0, 0, inset));
623 break;
624 }
625}
626
[email protected]27f6af62012-03-21 05:34:40627void ShelfLayoutManager::CalculateTargetBounds(
628 const State& state,
[email protected]55444502012-05-10 15:43:53629 TargetBounds* target_bounds) {
[email protected]88d71122012-10-18 07:11:01630 const gfx::Rect& available_bounds(root_window_->bounds());
631 gfx::Rect status_size(status_area_widget_->GetWindowBoundsInScreen().size());
[email protected]55444502012-05-10 15:43:53632 gfx::Size launcher_size = launcher_ ?
633 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
634 int shelf_size = 0;
635 int shelf_width = 0, shelf_height = 0;
636 GetShelfSize(&shelf_width, &shelf_height);
[email protected]27f6af62012-03-21 05:34:40637 if (state.visibility_state == VISIBLE ||
638 (state.visibility_state == AUTO_HIDE &&
[email protected]55444502012-05-10 15:43:53639 state.auto_hide_state == AUTO_HIDE_SHOWN)) {
640 shelf_size = std::max(shelf_width, shelf_height);
641 } else if (state.visibility_state == AUTO_HIDE &&
642 state.auto_hide_state == AUTO_HIDE_HIDDEN) {
643 shelf_size = kAutoHideSize;
[email protected]7b675df612012-09-16 18:33:20644 // Keep the launcher to its full height when dragging is in progress.
645 if (gesture_drag_status_ == GESTURE_DRAG_NONE)
646 launcher_size.set_height(kAutoHideSize);
[email protected]27f6af62012-03-21 05:34:40647 }
[email protected]55444502012-05-10 15:43:53648 if (alignment_ == SHELF_ALIGNMENT_BOTTOM) {
649 int y = available_bounds.bottom();
650 y -= shelf_size;
651 // The status widget should extend to the bottom and right edges.
[email protected]ec1930c32012-07-19 23:57:42652 target_bounds->status_bounds_in_root = gfx::Rect(
[email protected]55444502012-05-10 15:43:53653 base::i18n::IsRTL() ? available_bounds.x() :
[email protected]ec1930c32012-07-19 23:57:42654 available_bounds.right() - status_size.width(),
655 y + shelf_height - status_size.height(),
656 status_size.width(), status_size.height());
[email protected]55444502012-05-10 15:43:53657 if (launcher_widget()) {
[email protected]ec1930c32012-07-19 23:57:42658 target_bounds->launcher_bounds_in_root = gfx::Rect(
[email protected]55444502012-05-10 15:43:53659 available_bounds.x(),
[email protected]7b675df612012-09-16 18:33:20660 y,
[email protected]55444502012-05-10 15:43:53661 available_bounds.width(),
662 launcher_size.height());
663 }
664 target_bounds->work_area_insets.Set(
665 0, 0, GetWorkAreaSize(state, shelf_height), 0);
666 } else {
667 int x = (alignment_ == SHELF_ALIGNMENT_LEFT) ?
668 available_bounds.x() + shelf_size - shelf_width :
669 available_bounds.right() - shelf_size;
[email protected]ec1930c32012-07-19 23:57:42670 target_bounds->status_bounds_in_root = gfx::Rect(
671 x, available_bounds.bottom() - status_size.height(),
672 shelf_width, status_size.height());
[email protected]55444502012-05-10 15:43:53673 if (launcher_widget()) {
[email protected]ec1930c32012-07-19 23:57:42674 target_bounds->launcher_bounds_in_root = gfx::Rect(
[email protected]55444502012-05-10 15:43:53675 x,
676 available_bounds.y(),
677 launcher_size.width(),
678 available_bounds.height());
679 }
680 if (alignment_ == SHELF_ALIGNMENT_LEFT) {
681 target_bounds->work_area_insets.Set(
682 0, GetWorkAreaSize(state, shelf_width), 0, 0);
683 } else {
684 target_bounds->work_area_insets.Set(
685 0, 0, 0, GetWorkAreaSize(state, shelf_width));
686 }
687 }
[email protected]27f6af62012-03-21 05:34:40688 target_bounds->opacity =
[email protected]3c6abbe2012-08-30 23:48:57689 (gesture_drag_status_ != GESTURE_DRAG_NONE ||
690 state.visibility_state == VISIBLE ||
[email protected]27f6af62012-03-21 05:34:40691 state.visibility_state == AUTO_HIDE) ? 1.0f : 0.0f;
[email protected]3c6abbe2012-08-30 23:48:57692 if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS)
693 UpdateTargetBoundsForGesture(target_bounds);
694}
695
696void ShelfLayoutManager::UpdateTargetBoundsForGesture(
697 TargetBounds* target_bounds) const {
698 CHECK_EQ(GESTURE_DRAG_IN_PROGRESS, gesture_drag_status_);
699 bool horizontal = alignment() == SHELF_ALIGNMENT_BOTTOM;
[email protected]407ffd32012-09-11 17:47:36700 int resistance_free_region = 0;
[email protected]3c6abbe2012-08-30 23:48:57701
[email protected]c8e2e832012-09-12 21:48:28702 if (gesture_drag_auto_hide_state_ == AUTO_HIDE_HIDDEN &&
703 visibility_state() == AUTO_HIDE && auto_hide_state() != AUTO_HIDE_SHOWN) {
704 // If the shelf was hidden when the drag started (and the state hasn't
705 // changed since then, e.g. because the tray-menu was shown because of the
706 // drag), then allow the drag some resistance-free region at first to make
707 // sure the shelf sticks with the finger until the shelf is visible.
[email protected]91d966a72012-09-06 03:42:27708 resistance_free_region += horizontal ?
[email protected]4982ee12012-09-04 22:16:10709 target_bounds->launcher_bounds_in_root.height() :
710 target_bounds->launcher_bounds_in_root.width();
[email protected]91d966a72012-09-06 03:42:27711 resistance_free_region -= kAutoHideSize;
712 }
713
714 bool resist = false;
715 if (horizontal)
716 resist = gesture_drag_amount_ < -resistance_free_region;
717 else if (alignment() == SHELF_ALIGNMENT_LEFT)
718 resist = gesture_drag_amount_ > resistance_free_region;
719 else
720 resist = gesture_drag_amount_ < -resistance_free_region;
721
722 float translate = 0.f;
723 if (resist) {
724 float diff = fabsf(gesture_drag_amount_) - resistance_free_region;
[email protected]407ffd32012-09-11 17:47:36725 diff = std::min(diff, sqrtf(diff));
[email protected]91d966a72012-09-06 03:42:27726 if (gesture_drag_amount_ < 0)
727 translate = -resistance_free_region - diff;
728 else
729 translate = resistance_free_region + diff;
[email protected]4982ee12012-09-04 22:16:10730 } else {
[email protected]91d966a72012-09-06 03:42:27731 translate = gesture_drag_amount_;
[email protected]4982ee12012-09-04 22:16:10732 }
733
[email protected]3c6abbe2012-08-30 23:48:57734 if (horizontal) {
[email protected]91d966a72012-09-06 03:42:27735 // Move the launcher with the gesture.
[email protected]3c6abbe2012-08-30 23:48:57736 target_bounds->launcher_bounds_in_root.Offset(0, translate);
[email protected]91d966a72012-09-06 03:42:27737
738 if (translate > 0) {
739 // When dragging down, the statusbar should move.
740 target_bounds->status_bounds_in_root.Offset(0, translate);
741 } else {
742 // When dragging up, the launcher height should increase.
[email protected]91d966a72012-09-06 03:42:27743 float move = std::max(translate,
744 -static_cast<float>(resistance_free_region));
745 target_bounds->launcher_bounds_in_root.set_height(
746 target_bounds->launcher_bounds_in_root.height() + move - translate);
747
[email protected]407ffd32012-09-11 17:47:36748 // The statusbar should be in the center.
749 gfx::Rect status_y = target_bounds->launcher_bounds_in_root.Center(
750 target_bounds->status_bounds_in_root.size());
751 target_bounds->status_bounds_in_root.set_y(status_y.y());
[email protected]91d966a72012-09-06 03:42:27752 }
[email protected]3c6abbe2012-08-30 23:48:57753 } else {
[email protected]91d966a72012-09-06 03:42:27754 // Move the launcher with the gesture.
755 if (alignment() == SHELF_ALIGNMENT_RIGHT)
756 target_bounds->launcher_bounds_in_root.Offset(translate, 0);
757
758 if ((translate > 0 && alignment() == SHELF_ALIGNMENT_RIGHT) ||
759 (translate < 0 && alignment() == SHELF_ALIGNMENT_LEFT)) {
760 // When dragging towards the edge, the statusbar should move.
761 target_bounds->status_bounds_in_root.Offset(translate, 0);
762 } else {
763 // When dragging away from the edge, the launcher width should increase.
[email protected]91d966a72012-09-06 03:42:27764 float move = alignment() == SHELF_ALIGNMENT_RIGHT ?
765 std::max(translate, -static_cast<float>(resistance_free_region)) :
766 std::min(translate, static_cast<float>(resistance_free_region));
767
768 if (alignment() == SHELF_ALIGNMENT_RIGHT) {
769 target_bounds->launcher_bounds_in_root.set_width(
770 target_bounds->launcher_bounds_in_root.width() + move - translate);
[email protected]91d966a72012-09-06 03:42:27771 } else {
772 target_bounds->launcher_bounds_in_root.set_width(
773 target_bounds->launcher_bounds_in_root.width() - move + translate);
[email protected]91d966a72012-09-06 03:42:27774 }
775
[email protected]407ffd32012-09-11 17:47:36776 // The statusbar should be in the center.
777 gfx::Rect status_x = target_bounds->launcher_bounds_in_root.Center(
778 target_bounds->status_bounds_in_root.size());
779 target_bounds->status_bounds_in_root.set_x(status_x.x());
[email protected]91d966a72012-09-06 03:42:27780 }
[email protected]3c6abbe2012-08-30 23:48:57781 }
[email protected]ae18b9112011-11-07 16:59:13782}
783
[email protected]a160baec2012-03-21 20:52:15784void ShelfLayoutManager::UpdateShelfBackground(
785 BackgroundAnimator::ChangeType type) {
786 bool launcher_paints = GetLauncherPaintsBackground();
787 if (launcher_)
788 launcher_->SetPaintsBackground(launcher_paints, type);
[email protected]71ac7f092012-08-21 02:31:50789 // The status area normally draws a background, but we don't want it to draw a
[email protected]8fbbf812012-09-17 15:09:18790 // background when the launcher does or when we're at login/lock screen.
[email protected]88d71122012-10-18 07:11:01791 ShellDelegate* delegate = Shell::GetInstance()->delegate();
792 bool delegate_allows_tray_bg = !delegate ||
793 (delegate->IsUserLoggedIn() && !delegate->IsScreenLocked());
794 bool status_area_paints = !launcher_paints && delegate_allows_tray_bg;
795 status_area_widget_->SetPaintsBackground(status_area_paints, type);
[email protected]a160baec2012-03-21 20:52:15796}
797
798bool ShelfLayoutManager::GetLauncherPaintsBackground() const {
[email protected]3c6abbe2012-08-30 23:48:57799 return gesture_drag_status_ != GESTURE_DRAG_NONE ||
800 (!state_.is_screen_locked && window_overlaps_shelf_) ||
[email protected]7b675df612012-09-16 18:33:20801 (state_.visibility_state == AUTO_HIDE) ;
[email protected]ae18b9112011-11-07 16:59:13802}
803
[email protected]b1c37fc2012-03-22 03:36:13804void ShelfLayoutManager::UpdateAutoHideStateNow() {
805 SetState(state_.visibility_state);
806}
807
808ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState(
809 VisibilityState visibility_state) const {
810 if (visibility_state != AUTO_HIDE || !launcher_widget())
811 return AUTO_HIDE_HIDDEN;
812
[email protected]4982ee12012-09-04 22:16:10813 if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS)
814 return gesture_drag_auto_hide_state_;
[email protected]3c6abbe2012-08-30 23:48:57815
[email protected]b1c37fc2012-03-22 03:36:13816 Shell* shell = Shell::GetInstance();
[email protected]7510d1082012-03-30 21:58:34817 if (shell->GetAppListTargetVisibility())
818 return AUTO_HIDE_SHOWN;
819
[email protected]88d71122012-10-18 07:11:01820 if (status_area_widget_ && status_area_widget_->ShouldShowLauncher())
[email protected]d9d5a922012-03-26 04:38:03821 return AUTO_HIDE_SHOWN;
[email protected]b1c37fc2012-03-22 03:36:13822
[email protected]e9992b12012-03-27 00:11:27823 if (launcher_ && launcher_->IsShowingMenu())
824 return AUTO_HIDE_SHOWN;
825
[email protected]3475f5e2012-07-12 22:10:32826 if (launcher_ && launcher_->IsShowingOverflowBubble())
827 return AUTO_HIDE_SHOWN;
828
[email protected]88d71122012-10-18 07:11:01829 if (launcher_widget()->IsActive() || status_area_widget_->IsActive())
[email protected]8676f0472012-03-29 20:30:12830 return AUTO_HIDE_SHOWN;
831
[email protected]5f1d99dc2012-04-12 21:42:37832 // Don't show if the user is dragging the mouse.
833 if (event_filter_.get() && event_filter_->in_mouse_drag())
834 return AUTO_HIDE_HIDDEN;
835
[email protected]2e195f52012-09-22 00:24:46836 gfx::Rect shelf_region = launcher_widget()->GetWindowBoundsInScreen();
[email protected]88d71122012-10-18 07:11:01837 if (status_area_widget_ &&
838 status_area_widget_->IsMessageBubbleShown() &&
[email protected]2e195f52012-09-22 00:24:46839 IsVisible()) {
840 // Increase the the hit test area to prevent the shelf from disappearing
841 // when the mouse is over the bubble gap.
842 shelf_region.Inset(alignment_ == SHELF_ALIGNMENT_RIGHT ?
843 -kNotificationBubbleGapHeight : 0,
844 alignment_ == SHELF_ALIGNMENT_BOTTOM ?
845 -kNotificationBubbleGapHeight : 0,
846 alignment_ == SHELF_ALIGNMENT_LEFT ?
847 -kNotificationBubbleGapHeight : 0,
848 0);
849 }
[email protected]ffabb1e2012-10-12 19:51:17850 return shelf_region.Contains(Shell::GetScreen()->GetCursorScreenPoint()) ?
[email protected]2e195f52012-09-22 00:24:46851 AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN;
[email protected]b1c37fc2012-03-22 03:36:13852}
853
[email protected]128fd3732012-03-27 01:55:12854void ShelfLayoutManager::UpdateHitTestBounds() {
855 gfx::Insets insets;
856 // Only modify the hit test when the shelf is visible, so we don't mess with
857 // hover hit testing in the auto-hide state.
858 if (state_.visibility_state == VISIBLE) {
859 // Let clicks at the very top of the launcher through so windows can be
860 // resized with the bottom-right corner and bottom edge.
[email protected]55444502012-05-10 15:43:53861 switch (alignment_) {
862 case SHELF_ALIGNMENT_BOTTOM:
863 insets.Set(kWorkspaceAreaBottomInset, 0, 0, 0);
864 break;
865 case SHELF_ALIGNMENT_LEFT:
866 insets.Set(0, 0, 0, kWorkspaceAreaBottomInset);
867 break;
868 case SHELF_ALIGNMENT_RIGHT:
869 insets.Set(0, kWorkspaceAreaBottomInset, 0, 0);
870 break;
871 }
[email protected]128fd3732012-03-27 01:55:12872 }
[email protected]a86445b2012-08-09 19:42:39873 if (launcher_widget() && launcher_widget()->GetNativeWindow()) {
874 launcher_widget()->GetNativeWindow()->SetHitTestBoundsOverrideOuter(
875 insets, 1);
876 }
[email protected]88d71122012-10-18 07:11:01877 status_area_widget_->GetNativeWindow()->
878 SetHitTestBoundsOverrideOuter(insets, 1);
[email protected]128fd3732012-03-27 01:55:12879}
880
[email protected]5f1d99dc2012-04-12 21:42:37881bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) {
882 if (!window)
883 return false;
884 return (launcher_widget() &&
885 launcher_widget()->GetNativeWindow()->Contains(window)) ||
[email protected]88d71122012-10-18 07:11:01886 (status_area_widget_->GetNativeWindow()->Contains(window));
[email protected]5f1d99dc2012-04-12 21:42:37887}
888
[email protected]55444502012-05-10 15:43:53889int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const {
890 if (state.visibility_state == VISIBLE)
891 return size;
892 if (state.visibility_state == AUTO_HIDE)
893 return kAutoHideSize;
894 return 0;
895}
896
[email protected]55f593352011-12-24 05:42:46897} // namespace internal
898} // namespace ash