blob: 1634557314bf62043287a5a62136323f3fbfd6b4 [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]c758fbf2012-03-25 22:53:5916#include "ash/wm/workspace/workspace_manager.h"
[email protected]4bb16502011-12-06 14:44:5817#include "base/auto_reset.h"
[email protected]e24b6092012-04-12 18:58:5118#include "base/i18n/rtl.h"
[email protected]8676f0472012-03-29 20:30:1219#include "ui/aura/client/activation_client.h"
[email protected]b1c37fc2012-03-22 03:36:1320#include "ui/aura/event.h"
21#include "ui/aura/event_filter.h"
[email protected]99f07e02011-12-07 00:02:5922#include "ui/aura/root_window.h"
[email protected]116302fc2012-05-05 21:45:4123#include "ui/compositor/layer.h"
24#include "ui/compositor/layer_animation_observer.h"
25#include "ui/compositor/layer_animator.h"
26#include "ui/compositor/scoped_layer_animation_settings.h"
[email protected]b82c42c42012-04-25 20:03:4127#include "ui/gfx/screen.h"
[email protected]c13be0d2011-11-22 02:09:5828#include "ui/views/widget/widget.h"
[email protected]ae18b9112011-11-07 16:59:1329
[email protected]55f593352011-12-24 05:42:4630namespace ash {
[email protected]ae18b9112011-11-07 16:59:1331namespace internal {
32
33namespace {
34
[email protected]cadd8c42012-03-27 02:44:3135// Delay before showing the launcher. This is after the mouse stops moving.
36const int kAutoHideDelayMS = 200;
[email protected]27f6af62012-03-21 05:34:4037
[email protected]ae18b9112011-11-07 16:59:1338ui::Layer* GetLayer(views::Widget* widget) {
39 return widget->GetNativeView()->layer();
40}
41
42} // namespace
43
[email protected]bbb59f82012-03-14 04:04:3544// static
45const int ShelfLayoutManager::kWorkspaceAreaBottomInset = 2;
46
[email protected]b1c37fc2012-03-22 03:36:1347// static
[email protected]55444502012-05-10 15:43:5348const int ShelfLayoutManager::kAutoHideSize = 2;
[email protected]b1c37fc2012-03-22 03:36:1349
50// Notifies ShelfLayoutManager any time the mouse moves.
51class ShelfLayoutManager::AutoHideEventFilter : public aura::EventFilter {
52 public:
53 explicit AutoHideEventFilter(ShelfLayoutManager* shelf);
54 virtual ~AutoHideEventFilter();
55
[email protected]5f1d99dc2012-04-12 21:42:3756 // Returns true if the last mouse event was a mouse drag.
57 bool in_mouse_drag() const { return in_mouse_drag_; }
58
[email protected]b1c37fc2012-03-22 03:36:1359 // Overridden from aura::EventFilter:
60 virtual bool PreHandleKeyEvent(aura::Window* target,
61 aura::KeyEvent* event) OVERRIDE;
62 virtual bool PreHandleMouseEvent(aura::Window* target,
63 aura::MouseEvent* event) OVERRIDE;
64 virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target,
65 aura::TouchEvent* event) OVERRIDE;
66 virtual ui::GestureStatus PreHandleGestureEvent(
67 aura::Window* target,
68 aura::GestureEvent* event) OVERRIDE;
69
70 private:
71 ShelfLayoutManager* shelf_;
[email protected]5f1d99dc2012-04-12 21:42:3772 bool in_mouse_drag_;
[email protected]b1c37fc2012-03-22 03:36:1373
74 DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter);
75};
76
77ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter(
78 ShelfLayoutManager* shelf)
[email protected]5f1d99dc2012-04-12 21:42:3779 : shelf_(shelf),
80 in_mouse_drag_(false) {
[email protected]b1c37fc2012-03-22 03:36:1381 Shell::GetInstance()->AddRootWindowEventFilter(this);
82}
83
84ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() {
85 Shell::GetInstance()->RemoveRootWindowEventFilter(this);
86}
87
88bool ShelfLayoutManager::AutoHideEventFilter::PreHandleKeyEvent(
89 aura::Window* target,
90 aura::KeyEvent* event) {
91 return false; // Always let the event propagate.
92}
93
94bool ShelfLayoutManager::AutoHideEventFilter::PreHandleMouseEvent(
95 aura::Window* target,
96 aura::MouseEvent* event) {
[email protected]5f1d99dc2012-04-12 21:42:3797 // This also checks IsShelfWindow() to make sure we don't attempt to hide the
98 // shelf if the mouse down occurs on the shelf.
99 in_mouse_drag_ = (event->type() == ui::ET_MOUSE_DRAGGED ||
100 (in_mouse_drag_ && event->type() != ui::ET_MOUSE_RELEASED &&
101 event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)) &&
102 !shelf_->IsShelfWindow(target);
[email protected]b1c37fc2012-03-22 03:36:13103 if (event->type() == ui::ET_MOUSE_MOVED)
104 shelf_->UpdateAutoHideState();
105 return false; // Not handled.
106}
107
108ui::TouchStatus ShelfLayoutManager::AutoHideEventFilter::PreHandleTouchEvent(
109 aura::Window* target,
110 aura::TouchEvent* event) {
111 return ui::TOUCH_STATUS_UNKNOWN; // Not handled.
112}
113
114ui::GestureStatus
115ShelfLayoutManager::AutoHideEventFilter::PreHandleGestureEvent(
116 aura::Window* target,
117 aura::GestureEvent* event) {
118 return ui::GESTURE_STATUS_UNKNOWN; // Not handled.
119}
120
[email protected]4bb16502011-12-06 14:44:58121////////////////////////////////////////////////////////////////////////////////
122// ShelfLayoutManager, public:
123
[email protected]27f6af62012-03-21 05:34:40124ShelfLayoutManager::ShelfLayoutManager(views::Widget* status)
[email protected]42713f72012-05-25 00:41:50125 : root_window_(Shell::GetPrimaryRootWindow()),
[email protected]8676f0472012-03-29 20:30:12126 in_layout_(false),
[email protected]09f3fc82012-03-26 23:26:56127 auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT),
[email protected]55444502012-05-10 15:43:53128 alignment_(SHELF_ALIGNMENT_BOTTOM),
[email protected]27f6af62012-03-21 05:34:40129 launcher_(NULL),
130 status_(status),
[email protected]c758fbf2012-03-25 22:53:59131 workspace_manager_(NULL),
[email protected]b1c37fc2012-03-22 03:36:13132 window_overlaps_shelf_(false) {
[email protected]8e43cdf42012-05-11 17:03:31133 Shell::GetInstance()->AddShellObserver(this);
[email protected]e76310a92012-06-04 19:06:11134 aura::client::GetActivationClient(root_window_)->AddObserver(this);
[email protected]ae18b9112011-11-07 16:59:13135}
136
[email protected]4bb16502011-12-06 14:44:58137ShelfLayoutManager::~ShelfLayoutManager() {
[email protected]8e43cdf42012-05-11 17:03:31138 Shell::GetInstance()->RemoveShellObserver(this);
[email protected]e76310a92012-06-04 19:06:11139 aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
[email protected]ae18b9112011-11-07 16:59:13140}
141
[email protected]09f3fc82012-03-26 23:26:56142void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) {
143 if (auto_hide_behavior_ == behavior)
[email protected]c758fbf2012-03-25 22:53:59144 return;
[email protected]09f3fc82012-03-26 23:26:56145 auto_hide_behavior_ = behavior;
[email protected]c758fbf2012-03-25 22:53:59146 UpdateVisibilityState();
147}
148
[email protected]40429f02012-03-28 20:38:50149bool ShelfLayoutManager::IsVisible() const {
[email protected]dd4b868b2012-04-10 17:20:46150 return status_->IsVisible() && (state_.visibility_state == VISIBLE ||
[email protected]40429f02012-03-28 20:38:50151 (state_.visibility_state == AUTO_HIDE &&
[email protected]dd4b868b2012-04-10 17:20:46152 state_.auto_hide_state == AUTO_HIDE_SHOWN));
[email protected]40429f02012-03-28 20:38:50153}
154
[email protected]27f6af62012-03-21 05:34:40155gfx::Rect ShelfLayoutManager::GetMaximizedWindowBounds(
[email protected]55444502012-05-10 15:43:53156 aura::Window* window) {
[email protected]27f6af62012-03-21 05:34:40157 // TODO: needs to be multi-mon aware.
[email protected]b82c42c42012-04-25 20:03:41158 gfx::Rect bounds(gfx::Screen::GetMonitorNearestWindow(window).bounds());
[email protected]09f3fc82012-03-26 23:26:56159 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT ||
160 auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
[email protected]55444502012-05-10 15:43:53161 AdjustBoundsBasedOnAlignment(kAutoHideSize, &bounds);
[email protected]09f3fc82012-03-26 23:26:56162 return bounds;
163 }
164 // SHELF_AUTO_HIDE_BEHAVIOR_NEVER maximized windows don't get any taller.
165 return GetUnmaximizedWorkAreaBounds(window);
[email protected]27f6af62012-03-21 05:34:40166}
167
168gfx::Rect ShelfLayoutManager::GetUnmaximizedWorkAreaBounds(
[email protected]55444502012-05-10 15:43:53169 aura::Window* window) {
[email protected]27f6af62012-03-21 05:34:40170 // TODO: needs to be multi-mon aware.
[email protected]b82c42c42012-04-25 20:03:41171 gfx::Rect bounds(gfx::Screen::GetMonitorNearestWindow(window).bounds());
[email protected]55444502012-05-10 15:43:53172 int size;
173 if (auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS) {
174 size = kAutoHideSize;
175 } else {
176 int width, height;
177 GetShelfSize(&width, &height);
178 size = std::max(width, height);
179 }
180 AdjustBoundsBasedOnAlignment(size, &bounds);
[email protected]27f6af62012-03-21 05:34:40181 return bounds;
182}
183
[email protected]d9456cb2012-03-21 16:41:04184void ShelfLayoutManager::SetLauncher(Launcher* launcher) {
185 if (launcher == launcher_)
186 return;
187
188 launcher_ = launcher;
[email protected]d9456cb2012-03-21 16:41:04189 LayoutShelf();
190}
191
[email protected]c2d58b42012-05-30 08:11:29192bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) {
[email protected]55444502012-05-10 15:43:53193 if (alignment_ == alignment)
[email protected]c2d58b42012-05-30 08:11:29194 return false;
[email protected]55444502012-05-10 15:43:53195
196 alignment_ = alignment;
197 if (launcher_)
198 launcher_->SetAlignment(alignment);
[email protected]6d6546e2012-05-30 23:12:02199 if (Shell::GetInstance()->status_area_widget())
200 Shell::GetInstance()->status_area_widget()->SetShelfAlignment(alignment);
201 if (Shell::GetInstance()->system_tray())
202 Shell::GetInstance()->system_tray()->SetShelfAlignment(alignment);
[email protected]55444502012-05-10 15:43:53203 LayoutShelf();
[email protected]c2d58b42012-05-30 08:11:29204 return true;
[email protected]55444502012-05-10 15:43:53205}
206
207gfx::Rect ShelfLayoutManager::GetIdealBounds() {
208 // TODO: this is wrong. Figure out what monitor shelf is on and everything
209 // should be based on it.
210 gfx::Rect bounds(
211 gfx::Screen::GetMonitorNearestWindow(status_->GetNativeView()).bounds());
212 int width = 0, height = 0;
213 GetShelfSize(&width, &height);
214 switch (alignment_) {
215 case SHELF_ALIGNMENT_BOTTOM:
216 return gfx::Rect(bounds.x(), bounds.bottom() - height,
217 bounds.width(), height);
218 case SHELF_ALIGNMENT_LEFT:
219 return gfx::Rect(bounds.x(), bounds.y(), width, bounds.height());
220 case SHELF_ALIGNMENT_RIGHT:
[email protected]54a7c5a2012-05-24 19:54:20221 return gfx::Rect(bounds.right() - width, bounds.y(), width,
222 bounds.height());
[email protected]55444502012-05-10 15:43:53223 }
224 NOTREACHED();
225 return gfx::Rect();
226}
227
[email protected]4bb16502011-12-06 14:44:58228void ShelfLayoutManager::LayoutShelf() {
229 AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
[email protected]ae18b9112011-11-07 16:59:13230 StopAnimating();
231 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40232 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04233 if (launcher_widget()) {
234 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]cd9a61c72012-05-08 19:16:59235
[email protected]d9456cb2012-03-21 16:41:04236 launcher_widget()->SetBounds(target_bounds.launcher_bounds);
[email protected]55444502012-05-10 15:43:53237 launcher_->SetStatusSize(target_bounds.status_bounds.size());
[email protected]27f6af62012-03-21 05:34:40238 }
239 GetLayer(status_)->SetOpacity(target_bounds.opacity);
[email protected]ae18b9112011-11-07 16:59:13240 status_->SetBounds(target_bounds.status_bounds);
[email protected]8a45c972012-03-14 18:22:44241 Shell::GetInstance()->SetMonitorWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50242 Shell::GetPrimaryRootWindow(),
[email protected]ae18b9112011-11-07 16:59:13243 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12244 UpdateHitTestBounds();
[email protected]ae18b9112011-11-07 16:59:13245}
246
[email protected]c758fbf2012-03-25 22:53:59247void ShelfLayoutManager::UpdateVisibilityState() {
248 ShellDelegate* delegate = Shell::GetInstance()->delegate();
249 if (delegate && delegate->IsScreenLocked()) {
250 SetState(VISIBLE);
251 } else {
252 WorkspaceManager::WindowState window_state(
253 workspace_manager_->GetWindowState());
254 switch (window_state) {
255 case WorkspaceManager::WINDOW_STATE_FULL_SCREEN:
256 SetState(HIDDEN);
257 break;
258
259 case WorkspaceManager::WINDOW_STATE_MAXIMIZED:
[email protected]09f3fc82012-03-26 23:26:56260 SetState(auto_hide_behavior_ != SHELF_AUTO_HIDE_BEHAVIOR_NEVER ?
261 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59262 break;
263
264 case WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF:
265 case WorkspaceManager::WINDOW_STATE_DEFAULT:
[email protected]09f3fc82012-03-26 23:26:56266 SetState(auto_hide_behavior_ == SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS ?
267 AUTO_HIDE : VISIBLE);
[email protected]c758fbf2012-03-25 22:53:59268 SetWindowOverlapsShelf(window_state ==
269 WorkspaceManager::WINDOW_STATE_WINDOW_OVERLAPS_SHELF);
270 }
271 }
272}
273
274void ShelfLayoutManager::UpdateAutoHideState() {
[email protected]cadd8c42012-03-27 02:44:31275 AutoHideState auto_hide_state =
276 CalculateAutoHideState(state_.visibility_state);
277 if (auto_hide_state != state_.auto_hide_state) {
278 if (auto_hide_state == AUTO_HIDE_HIDDEN) {
279 // Hides happen immediately.
280 SetState(state_.visibility_state);
281 } else {
282 auto_hide_timer_.Stop();
[email protected]c758fbf2012-03-25 22:53:59283 auto_hide_timer_.Start(
284 FROM_HERE,
285 base::TimeDelta::FromMilliseconds(kAutoHideDelayMS),
286 this, &ShelfLayoutManager::UpdateAutoHideStateNow);
287 }
288 } else {
289 auto_hide_timer_.Stop();
290 }
291}
292
293void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) {
294 window_overlaps_shelf_ = value;
295 UpdateShelfBackground(internal::BackgroundAnimator::CHANGE_ANIMATE);
296}
297
298////////////////////////////////////////////////////////////////////////////////
299// ShelfLayoutManager, aura::LayoutManager implementation:
300
301void ShelfLayoutManager::OnWindowResized() {
302 LayoutShelf();
303}
304
305void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
306}
307
308void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
309}
310
[email protected]fa893ab62012-04-20 01:26:51311void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
312}
313
[email protected]c758fbf2012-03-25 22:53:59314void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
315 bool visible) {
316}
317
318void ShelfLayoutManager::SetChildBounds(aura::Window* child,
319 const gfx::Rect& requested_bounds) {
320 SetChildBoundsDirect(child, requested_bounds);
321 if (!in_layout_)
322 LayoutShelf();
323}
324
[email protected]8e43cdf42012-05-11 17:03:31325void ShelfLayoutManager::OnLockStateChanged(bool locked) {
326 UpdateVisibilityState();
327}
328
[email protected]e76310a92012-06-04 19:06:11329void ShelfLayoutManager::OnWindowActivated(aura::Window* active,
330 aura::Window* old_active) {
331 UpdateAutoHideStateNow();
[email protected]8676f0472012-03-29 20:30:12332}
333
[email protected]c758fbf2012-03-25 22:53:59334////////////////////////////////////////////////////////////////////////////////
335// ShelfLayoutManager, private:
336
[email protected]b1c37fc2012-03-22 03:36:13337void ShelfLayoutManager::SetState(VisibilityState visibility_state) {
[email protected]751444a2012-04-03 04:57:14338 ShellDelegate* delegate = Shell::GetInstance()->delegate();
[email protected]27f6af62012-03-21 05:34:40339 State state;
[email protected]c758fbf2012-03-25 22:53:59340 state.visibility_state = visibility_state;
[email protected]b1c37fc2012-03-22 03:36:13341 state.auto_hide_state = CalculateAutoHideState(visibility_state);
[email protected]751444a2012-04-03 04:57:14342 state.is_screen_locked = delegate && delegate->IsScreenLocked();
[email protected]306768162012-02-02 02:04:41343
[email protected]27f6af62012-03-21 05:34:40344 if (state_.Equals(state))
[email protected]ae18b9112011-11-07 16:59:13345 return; // Nothing changed.
346
[email protected]b1c37fc2012-03-22 03:36:13347 if (state.visibility_state == AUTO_HIDE) {
348 // When state is AUTO_HIDE we need to track when the mouse is over the
349 // launcher to unhide the shelf. AutoHideEventFilter does that for us.
350 if (!event_filter_.get())
351 event_filter_.reset(new AutoHideEventFilter(this));
352 } else {
353 event_filter_.reset(NULL);
354 }
355
356 auto_hide_timer_.Stop();
357
[email protected]27f6af62012-03-21 05:34:40358 // Animating the background when transitioning from auto-hide & hidden to
359 // visibile is janking. Update the background immediately in this case.
[email protected]a160baec2012-03-21 20:52:15360 internal::BackgroundAnimator::ChangeType change_type =
[email protected]27f6af62012-03-21 05:34:40361 (state_.visibility_state == AUTO_HIDE &&
362 state_.auto_hide_state == AUTO_HIDE_HIDDEN &&
363 state.visibility_state == VISIBLE) ?
[email protected]a160baec2012-03-21 20:52:15364 internal::BackgroundAnimator::CHANGE_IMMEDIATE :
365 internal::BackgroundAnimator::CHANGE_ANIMATE;
[email protected]ae18b9112011-11-07 16:59:13366 StopAnimating();
[email protected]27f6af62012-03-21 05:34:40367 state_ = state;
[email protected]ae18b9112011-11-07 16:59:13368 TargetBounds target_bounds;
[email protected]27f6af62012-03-21 05:34:40369 CalculateTargetBounds(state_, &target_bounds);
[email protected]d9456cb2012-03-21 16:41:04370 if (launcher_widget()) {
[email protected]27f6af62012-03-21 05:34:40371 ui::ScopedLayerAnimationSettings launcher_animation_setter(
[email protected]d9456cb2012-03-21 16:41:04372 GetLayer(launcher_widget())->GetAnimator());
[email protected]27f6af62012-03-21 05:34:40373 launcher_animation_setter.SetTransitionDuration(
374 base::TimeDelta::FromMilliseconds(130));
375 launcher_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59376 GetLayer(launcher_widget())->SetBounds(target_bounds.launcher_bounds);
[email protected]d9456cb2012-03-21 16:41:04377 GetLayer(launcher_widget())->SetOpacity(target_bounds.opacity);
[email protected]27f6af62012-03-21 05:34:40378 }
[email protected]306768162012-02-02 02:04:41379 ui::ScopedLayerAnimationSettings status_animation_setter(
[email protected]27f6af62012-03-21 05:34:40380 GetLayer(status_)->GetAnimator());
381 status_animation_setter.SetTransitionDuration(
382 base::TimeDelta::FromMilliseconds(130));
383 status_animation_setter.SetTweenType(ui::Tween::EASE_OUT);
[email protected]cd9a61c72012-05-08 19:16:59384 GetLayer(status_)->SetBounds(target_bounds.status_bounds);
[email protected]27f6af62012-03-21 05:34:40385 GetLayer(status_)->SetOpacity(target_bounds.opacity);
386 Shell::GetInstance()->SetMonitorWorkAreaInsets(
[email protected]42713f72012-05-25 00:41:50387 Shell::GetPrimaryRootWindow(),
[email protected]27f6af62012-03-21 05:34:40388 target_bounds.work_area_insets);
[email protected]128fd3732012-03-27 01:55:12389 UpdateHitTestBounds();
[email protected]a160baec2012-03-21 20:52:15390 UpdateShelfBackground(change_type);
[email protected]27f6af62012-03-21 05:34:40391}
[email protected]63ef21592012-03-21 01:15:40392
[email protected]4bb16502011-12-06 14:44:58393void ShelfLayoutManager::StopAnimating() {
[email protected]d9456cb2012-03-21 16:41:04394 if (launcher_widget())
395 GetLayer(launcher_widget())->GetAnimator()->StopAnimating();
[email protected]df5954f2011-12-14 16:19:58396 GetLayer(status_)->GetAnimator()->StopAnimating();
[email protected]ae18b9112011-11-07 16:59:13397}
398
[email protected]55444502012-05-10 15:43:53399void ShelfLayoutManager::GetShelfSize(int* width, int* height) {
400 *width = *height = 0;
401 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
402 gfx::Size launcher_size = launcher_ ?
403 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
[email protected]0ab08e52012-05-19 00:04:21404 if (alignment_ == SHELF_ALIGNMENT_BOTTOM)
[email protected]55444502012-05-10 15:43:53405 *height = std::max(launcher_size.height(), status_bounds.height());
[email protected]0ab08e52012-05-19 00:04:21406 else
407 *width = std::max(launcher_size.width(), status_bounds.width());
[email protected]55444502012-05-10 15:43:53408}
409
410void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset,
411 gfx::Rect* bounds) const {
412 switch (alignment_) {
413 case SHELF_ALIGNMENT_BOTTOM:
414 bounds->Inset(gfx::Insets(0, 0, inset, 0));
415 break;
416 case SHELF_ALIGNMENT_LEFT:
417 bounds->Inset(gfx::Insets(0, inset, 0, 0));
418 break;
419 case SHELF_ALIGNMENT_RIGHT:
420 bounds->Inset(gfx::Insets(0, 0, 0, inset));
421 break;
422 }
423}
424
[email protected]27f6af62012-03-21 05:34:40425void ShelfLayoutManager::CalculateTargetBounds(
426 const State& state,
[email protected]55444502012-05-10 15:43:53427 TargetBounds* target_bounds) {
[email protected]b1c37fc2012-03-22 03:36:13428 const gfx::Rect& available_bounds(
429 status_->GetNativeView()->GetRootWindow()->bounds());
[email protected]55444502012-05-10 15:43:53430 gfx::Rect status_bounds(status_->GetWindowScreenBounds());
431 gfx::Size launcher_size = launcher_ ?
432 launcher_widget()->GetContentsView()->GetPreferredSize() : gfx::Size();
433 int shelf_size = 0;
434 int shelf_width = 0, shelf_height = 0;
435 GetShelfSize(&shelf_width, &shelf_height);
[email protected]27f6af62012-03-21 05:34:40436 if (state.visibility_state == VISIBLE ||
437 (state.visibility_state == AUTO_HIDE &&
[email protected]55444502012-05-10 15:43:53438 state.auto_hide_state == AUTO_HIDE_SHOWN)) {
439 shelf_size = std::max(shelf_width, shelf_height);
440 } else if (state.visibility_state == AUTO_HIDE &&
441 state.auto_hide_state == AUTO_HIDE_HIDDEN) {
442 shelf_size = kAutoHideSize;
[email protected]27f6af62012-03-21 05:34:40443 }
[email protected]55444502012-05-10 15:43:53444 if (alignment_ == SHELF_ALIGNMENT_BOTTOM) {
445 int y = available_bounds.bottom();
446 y -= shelf_size;
447 // The status widget should extend to the bottom and right edges.
448 target_bounds->status_bounds = gfx::Rect(
449 base::i18n::IsRTL() ? available_bounds.x() :
450 available_bounds.right() - status_bounds.width(),
451 y + shelf_height - status_bounds.height(),
452 status_bounds.width(), status_bounds.height());
453 if (launcher_widget()) {
454 target_bounds->launcher_bounds = gfx::Rect(
455 available_bounds.x(),
456 y + (shelf_height - launcher_size.height()) / 2,
457 available_bounds.width(),
458 launcher_size.height());
459 }
460 target_bounds->work_area_insets.Set(
461 0, 0, GetWorkAreaSize(state, shelf_height), 0);
462 } else {
463 int x = (alignment_ == SHELF_ALIGNMENT_LEFT) ?
464 available_bounds.x() + shelf_size - shelf_width :
465 available_bounds.right() - shelf_size;
466 target_bounds->status_bounds = gfx::Rect(
467 x, available_bounds.bottom() - status_bounds.height(),
468 shelf_width, status_bounds.height());
469 if (launcher_widget()) {
470 target_bounds->launcher_bounds = gfx::Rect(
471 x,
472 available_bounds.y(),
473 launcher_size.width(),
474 available_bounds.height());
475 }
476 if (alignment_ == SHELF_ALIGNMENT_LEFT) {
477 target_bounds->work_area_insets.Set(
478 0, GetWorkAreaSize(state, shelf_width), 0, 0);
479 } else {
480 target_bounds->work_area_insets.Set(
481 0, 0, 0, GetWorkAreaSize(state, shelf_width));
482 }
483 }
[email protected]27f6af62012-03-21 05:34:40484 target_bounds->opacity =
485 (state.visibility_state == VISIBLE ||
486 state.visibility_state == AUTO_HIDE) ? 1.0f : 0.0f;
[email protected]ae18b9112011-11-07 16:59:13487}
488
[email protected]a160baec2012-03-21 20:52:15489void ShelfLayoutManager::UpdateShelfBackground(
490 BackgroundAnimator::ChangeType type) {
491 bool launcher_paints = GetLauncherPaintsBackground();
492 if (launcher_)
493 launcher_->SetPaintsBackground(launcher_paints, type);
494 // SystemTray normally draws a background, but we don't want it to draw a
495 // background when the launcher does.
[email protected]6d6546e2012-05-30 23:12:02496 if (Shell::GetInstance()->system_tray()) {
497 Shell::GetInstance()->system_tray()->SetPaintsBackground(
498 !launcher_paints, type);
499 }
[email protected]a160baec2012-03-21 20:52:15500}
501
502bool ShelfLayoutManager::GetLauncherPaintsBackground() const {
[email protected]751444a2012-04-03 04:57:14503 return (!state_.is_screen_locked && window_overlaps_shelf_) ||
504 state_.visibility_state == AUTO_HIDE;
[email protected]ae18b9112011-11-07 16:59:13505}
506
[email protected]b1c37fc2012-03-22 03:36:13507void ShelfLayoutManager::UpdateAutoHideStateNow() {
508 SetState(state_.visibility_state);
509}
510
511ShelfLayoutManager::AutoHideState ShelfLayoutManager::CalculateAutoHideState(
512 VisibilityState visibility_state) const {
513 if (visibility_state != AUTO_HIDE || !launcher_widget())
514 return AUTO_HIDE_HIDDEN;
515
516 Shell* shell = Shell::GetInstance();
[email protected]7510d1082012-03-30 21:58:34517 if (shell->GetAppListTargetVisibility())
518 return AUTO_HIDE_SHOWN;
519
[email protected]6d6546e2012-05-30 23:12:02520 if (shell->system_tray() && shell->system_tray()->should_show_launcher())
[email protected]d9d5a922012-03-26 04:38:03521 return AUTO_HIDE_SHOWN;
[email protected]b1c37fc2012-03-22 03:36:13522
[email protected]e9992b12012-03-27 00:11:27523 if (launcher_ && launcher_->IsShowingMenu())
524 return AUTO_HIDE_SHOWN;
525
[email protected]8676f0472012-03-29 20:30:12526 if (launcher_widget()->IsActive() || status_->IsActive())
527 return AUTO_HIDE_SHOWN;
528
[email protected]5f1d99dc2012-04-12 21:42:37529 // Don't show if the user is dragging the mouse.
530 if (event_filter_.get() && event_filter_->in_mouse_drag())
531 return AUTO_HIDE_HIDDEN;
532
[email protected]b1c37fc2012-03-22 03:36:13533 aura::RootWindow* root = launcher_widget()->GetNativeView()->GetRootWindow();
534 bool mouse_over_launcher =
535 launcher_widget()->GetWindowScreenBounds().Contains(
536 root->last_mouse_location());
537 return mouse_over_launcher ? AUTO_HIDE_SHOWN : AUTO_HIDE_HIDDEN;
538}
539
[email protected]128fd3732012-03-27 01:55:12540void ShelfLayoutManager::UpdateHitTestBounds() {
541 gfx::Insets insets;
542 // Only modify the hit test when the shelf is visible, so we don't mess with
543 // hover hit testing in the auto-hide state.
544 if (state_.visibility_state == VISIBLE) {
545 // Let clicks at the very top of the launcher through so windows can be
546 // resized with the bottom-right corner and bottom edge.
[email protected]55444502012-05-10 15:43:53547 switch (alignment_) {
548 case SHELF_ALIGNMENT_BOTTOM:
549 insets.Set(kWorkspaceAreaBottomInset, 0, 0, 0);
550 break;
551 case SHELF_ALIGNMENT_LEFT:
552 insets.Set(0, 0, 0, kWorkspaceAreaBottomInset);
553 break;
554 case SHELF_ALIGNMENT_RIGHT:
555 insets.Set(0, kWorkspaceAreaBottomInset, 0, 0);
556 break;
557 }
[email protected]128fd3732012-03-27 01:55:12558 }
559 if (launcher_widget() && launcher_widget()->GetNativeWindow())
560 launcher_widget()->GetNativeWindow()->set_hit_test_bounds_override_outer(
561 insets);
562 status_->GetNativeWindow()->set_hit_test_bounds_override_outer(insets);
563}
564
[email protected]5f1d99dc2012-04-12 21:42:37565bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) {
566 if (!window)
567 return false;
568 return (launcher_widget() &&
569 launcher_widget()->GetNativeWindow()->Contains(window)) ||
570 (status_ && status_->GetNativeWindow()->Contains(window));
571}
572
[email protected]55444502012-05-10 15:43:53573int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const {
574 if (state.visibility_state == VISIBLE)
575 return size;
576 if (state.visibility_state == AUTO_HIDE)
577 return kAutoHideSize;
578 return 0;
579}
580
[email protected]55f593352011-12-24 05:42:46581} // namespace internal
582} // namespace ash