1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/shelf/shelf_layout_manager.h"
13 #include "ash/accelerators/accelerator_commands.h"
14 #include "ash/ash_switches.h"
15 #include "ash/root_window_controller.h"
16 #include "ash/screen_util.h"
17 #include "ash/session/session_state_delegate.h"
18 #include "ash/shelf/shelf.h"
19 #include "ash/shelf/shelf_bezel_event_filter.h"
20 #include "ash/shelf/shelf_constants.h"
21 #include "ash/shelf/shelf_layout_manager_observer.h"
22 #include "ash/shelf/shelf_widget.h"
23 #include "ash/shell.h"
24 #include "ash/shell_window_ids.h"
25 #include "ash/system/status_area_widget.h"
26 #include "ash/wm/gestures/shelf_gesture_handler.h"
27 #include "ash/wm/lock_state_controller.h"
28 #include "ash/wm/mru_window_tracker.h"
29 #include "ash/wm/window_animations.h"
30 #include "ash/wm/window_state.h"
31 #include "ash/wm/window_util.h"
32 #include "ash/wm/workspace_controller.h"
33 #include "base/auto_reset.h"
34 #include "base/command_line.h"
35 #include "base/command_line.h"
36 #include "base/i18n/rtl.h"
37 #include "base/strings/string_number_conversions.h"
38 #include "base/strings/string_util.h"
39 #include "ui/aura/client/cursor_client.h"
40 #include "ui/aura/window_event_dispatcher.h"
41 #include "ui/base/ui_base_switches.h"
42 #include "ui/compositor/layer.h"
43 #include "ui/compositor/layer_animation_observer.h"
44 #include "ui/compositor/layer_animator.h"
45 #include "ui/compositor/scoped_layer_animation_settings.h"
46 #include "ui/events/event.h"
47 #include "ui/events/event_handler.h"
48 #include "ui/gfx/screen.h"
49 #include "ui/keyboard/keyboard_util.h"
50 #include "ui/views/widget/widget.h"
51 #include "ui/wm/public/activation_client.h"
56 // Delay before showing the shelf. This is after the mouse stops moving.
57 const int kAutoHideDelayMS = 200;
59 // To avoid hiding the shelf when the mouse transitions from a message bubble
60 // into the shelf, the hit test area is enlarged by this amount of pixels to
61 // keep the shelf from hiding.
62 const int kNotificationBubbleGapHeight = 6;
64 // The maximum size of the region on the display opposing the shelf managed by
65 // this ShelfLayoutManager which can trigger showing the shelf.
67 // - Primary display is left of secondary display.
68 // - Shelf is left aligned
69 // - This ShelfLayoutManager manages the shelf for the secondary display.
70 // |kMaxAutoHideShowShelfRegionSize| refers to the maximum size of the region
71 // from the right edge of the primary display which can trigger showing the
72 // auto hidden shelf. The region is used to make it easier to trigger showing
73 // the auto hidden shelf when the shelf is on the boundary between displays.
74 const int kMaxAutoHideShowShelfRegionSize = 10;
76 ui::Layer* GetLayer(views::Widget* widget) {
77 return widget->GetNativeView()->layer();
80 bool IsDraggingTrayEnabled() {
81 static bool dragging_tray_allowed = CommandLine::ForCurrentProcess()->
82 HasSwitch(ash::switches::kAshEnableTrayDragging);
83 return dragging_tray_allowed;
89 const int ShelfLayoutManager::kWorkspaceAreaVisibleInset = 2;
92 const int ShelfLayoutManager::kWorkspaceAreaAutoHideInset = 5;
95 const int ShelfLayoutManager::kAutoHideSize = 3;
98 const int ShelfLayoutManager::kShelfItemInset = 3;
100 // ShelfLayoutManager::AutoHideEventFilter -------------------------------------
102 // Notifies ShelfLayoutManager any time the mouse moves.
103 class ShelfLayoutManager::AutoHideEventFilter : public ui::EventHandler {
105 explicit AutoHideEventFilter(ShelfLayoutManager* shelf);
106 virtual ~AutoHideEventFilter();
108 // Returns true if the last mouse event was a mouse drag.
109 bool in_mouse_drag() const { return in_mouse_drag_; }
111 // Overridden from ui::EventHandler:
112 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
113 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
116 ShelfLayoutManager* shelf_;
118 ShelfGestureHandler gesture_handler_;
119 DISALLOW_COPY_AND_ASSIGN(AutoHideEventFilter);
122 ShelfLayoutManager::AutoHideEventFilter::AutoHideEventFilter(
123 ShelfLayoutManager* shelf)
125 in_mouse_drag_(false) {
126 Shell::GetInstance()->AddPreTargetHandler(this);
129 ShelfLayoutManager::AutoHideEventFilter::~AutoHideEventFilter() {
130 Shell::GetInstance()->RemovePreTargetHandler(this);
133 void ShelfLayoutManager::AutoHideEventFilter::OnMouseEvent(
134 ui::MouseEvent* event) {
135 // This also checks IsShelfWindow() to make sure we don't attempt to hide the
136 // shelf if the mouse down occurs on the shelf.
137 in_mouse_drag_ = (event->type() == ui::ET_MOUSE_DRAGGED ||
138 (in_mouse_drag_ && event->type() != ui::ET_MOUSE_RELEASED &&
139 event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)) &&
140 !shelf_->IsShelfWindow(static_cast<aura::Window*>(event->target()));
141 if (event->type() == ui::ET_MOUSE_MOVED)
142 shelf_->UpdateAutoHideState();
146 void ShelfLayoutManager::AutoHideEventFilter::OnGestureEvent(
147 ui::GestureEvent* event) {
148 if (shelf_->IsShelfWindow(static_cast<aura::Window*>(event->target()))) {
149 if (gesture_handler_.ProcessGestureEvent(*event))
150 event->StopPropagation();
154 // ShelfLayoutManager:UpdateShelfObserver --------------------------------------
156 // UpdateShelfObserver is used to delay updating the background until the
157 // animation completes.
158 class ShelfLayoutManager::UpdateShelfObserver
159 : public ui::ImplicitAnimationObserver {
161 explicit UpdateShelfObserver(ShelfLayoutManager* shelf) : shelf_(shelf) {
162 shelf_->update_shelf_observer_ = this;
169 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
171 shelf_->UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE);
176 virtual ~UpdateShelfObserver() {
178 shelf_->update_shelf_observer_ = NULL;
181 // Shelf we're in. NULL if deleted before we're deleted.
182 ShelfLayoutManager* shelf_;
184 DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver);
187 // ShelfLayoutManager ----------------------------------------------------------
189 ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf)
190 : root_window_(shelf->GetNativeView()->GetRootWindow()),
191 updating_bounds_(false),
192 force_shelf_always_visibile_(
193 Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled()),
194 auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER),
195 alignment_(SHELF_ALIGNMENT_BOTTOM),
197 workspace_controller_(NULL),
198 window_overlaps_shelf_(false),
199 mouse_over_shelf_when_auto_hide_timer_started_(false),
200 bezel_event_filter_(new ShelfBezelEventFilter(this)),
201 gesture_drag_status_(GESTURE_DRAG_NONE),
202 gesture_drag_amount_(0.f),
203 gesture_drag_auto_hide_state_(SHELF_AUTO_HIDE_SHOWN),
204 update_shelf_observer_(NULL),
205 duration_override_in_ms_(0) {
206 Shell::GetInstance()->AddShellObserver(this);
207 Shell::GetInstance()->lock_state_controller()->AddObserver(this);
208 aura::client::GetActivationClient(root_window_)->AddObserver(this);
209 Shell::GetInstance()->session_state_delegate()->AddSessionStateObserver(this);
212 ShelfLayoutManager::~ShelfLayoutManager() {
213 if (update_shelf_observer_)
214 update_shelf_observer_->Detach();
216 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_, WillDeleteShelf());
217 Shell::GetInstance()->RemoveShellObserver(this);
218 Shell::GetInstance()->lock_state_controller()->RemoveObserver(this);
219 aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
220 Shell::GetInstance()->
221 session_state_delegate()->RemoveSessionStateObserver(this);
224 void ShelfLayoutManager::SetAutoHideBehavior(ShelfAutoHideBehavior behavior) {
225 if (auto_hide_behavior_ == behavior)
227 auto_hide_behavior_ = behavior;
228 UpdateVisibilityState();
229 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_,
230 OnAutoHideBehaviorChanged(root_window_,
231 auto_hide_behavior_));
234 void ShelfLayoutManager::PrepareForShutdown() {
235 // Clear all event filters, otherwise sometimes those filters may catch
236 // synthesized mouse event and cause crashes during the shutdown.
237 set_workspace_controller(NULL);
238 auto_hide_event_filter_.reset();
239 bezel_event_filter_.reset();
242 bool ShelfLayoutManager::IsVisible() const {
243 // status_area_widget() may be NULL during the shutdown.
244 return shelf_->status_area_widget() &&
245 shelf_->status_area_widget()->IsVisible() &&
246 (state_.visibility_state == SHELF_VISIBLE ||
247 (state_.visibility_state == SHELF_AUTO_HIDE &&
248 state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN));
251 bool ShelfLayoutManager::SetAlignment(ShelfAlignment alignment) {
252 if (alignment_ == alignment)
255 // This should not be called during the lock screen transitions.
256 DCHECK(!Shell::GetInstance()->session_state_delegate()->IsScreenLocked());
257 alignment_ = alignment;
258 shelf_->SetAlignment(alignment);
263 ShelfAlignment ShelfLayoutManager::GetAlignment() const {
264 // When the screen is locked, the shelf is forced into bottom alignment.
265 if (Shell::GetInstance()->session_state_delegate()->IsScreenLocked())
266 return SHELF_ALIGNMENT_BOTTOM;
270 gfx::Rect ShelfLayoutManager::GetIdealBounds() {
272 ScreenUtil::GetDisplayBoundsInParent(shelf_->GetNativeView()));
273 int width = 0, height = 0;
274 GetShelfSize(&width, &height);
275 return SelectValueForShelfAlignment(
276 gfx::Rect(bounds.x(), bounds.bottom() - height, bounds.width(), height),
277 gfx::Rect(bounds.x(), bounds.y(), width, bounds.height()),
278 gfx::Rect(bounds.right() - width, bounds.y(), width, bounds.height()),
279 gfx::Rect(bounds.x(), bounds.y(), bounds.width(), height));
282 void ShelfLayoutManager::LayoutShelf() {
283 TargetBounds target_bounds;
284 CalculateTargetBounds(state_, &target_bounds);
285 UpdateBoundsAndOpacity(target_bounds, false, NULL);
287 if (shelf_->shelf()) {
288 // This is not part of UpdateBoundsAndOpacity() because
289 // SetShelfViewBounds() sets the bounds immediately and does not animate.
290 // The height of the ShelfView for a horizontal shelf and the width of
291 // the ShelfView for a vertical shelf are set when |shelf_|'s bounds
292 // are changed via UpdateBoundsAndOpacity(). This sets the origin and the
293 // dimension in the other direction.
294 shelf_->shelf()->SetShelfViewBounds(
295 target_bounds.shelf_bounds_in_shelf);
299 ShelfVisibilityState ShelfLayoutManager::CalculateShelfVisibility() {
300 switch(auto_hide_behavior_) {
301 case SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS:
302 return SHELF_AUTO_HIDE;
303 case SHELF_AUTO_HIDE_BEHAVIOR_NEVER:
304 return SHELF_VISIBLE;
305 case SHELF_AUTO_HIDE_ALWAYS_HIDDEN:
308 return SHELF_VISIBLE;
311 void ShelfLayoutManager::UpdateVisibilityState() {
312 // Bail out early when there is no |workspace_controller_|, which happens
313 // during shutdown after PrepareForShutdown.
314 if (!workspace_controller_)
317 if (Shell::GetInstance()->session_state_delegate()->IsScreenLocked() ||
318 IsShelfForcedToBeVisible()) {
319 SetState(SHELF_VISIBLE);
321 // TODO(zelidrag): Verify shelf drag animation still shows on the device
322 // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN.
323 WorkspaceWindowState window_state(workspace_controller_->GetWindowState());
324 switch (window_state) {
325 case WORKSPACE_WINDOW_STATE_FULL_SCREEN: {
326 const aura::Window* fullscreen_window = GetRootWindowController(
327 root_window_)->GetWindowForFullscreenMode();
328 if (fullscreen_window && wm::GetWindowState(fullscreen_window)->
329 hide_shelf_when_fullscreen()) {
330 SetState(SHELF_HIDDEN);
332 // The shelf is sometimes not hidden when in immersive fullscreen.
333 // Force the shelf to be auto hidden in this case.
334 SetState(SHELF_AUTO_HIDE);
339 case WORKSPACE_WINDOW_STATE_MAXIMIZED:
340 SetState(CalculateShelfVisibility());
343 case WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF:
344 case WORKSPACE_WINDOW_STATE_DEFAULT:
345 SetState(CalculateShelfVisibility());
346 SetWindowOverlapsShelf(window_state ==
347 WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF);
353 void ShelfLayoutManager::UpdateAutoHideState() {
354 ShelfAutoHideState auto_hide_state =
355 CalculateAutoHideState(state_.visibility_state);
356 if (auto_hide_state != state_.auto_hide_state) {
357 if (auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) {
358 // Hides happen immediately.
359 SetState(state_.visibility_state);
361 if (!auto_hide_timer_.IsRunning()) {
362 mouse_over_shelf_when_auto_hide_timer_started_ =
363 shelf_->GetWindowBoundsInScreen().Contains(
364 Shell::GetScreen()->GetCursorScreenPoint());
366 auto_hide_timer_.Start(
368 base::TimeDelta::FromMilliseconds(kAutoHideDelayMS),
369 this, &ShelfLayoutManager::UpdateAutoHideStateNow);
376 void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) {
377 window_overlaps_shelf_ = value;
378 UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE);
381 void ShelfLayoutManager::AddObserver(ShelfLayoutManagerObserver* observer) {
382 observers_.AddObserver(observer);
385 void ShelfLayoutManager::RemoveObserver(ShelfLayoutManagerObserver* observer) {
386 observers_.RemoveObserver(observer);
389 ////////////////////////////////////////////////////////////////////////////////
390 // ShelfLayoutManager, Gesture functions:
392 void ShelfLayoutManager::OnGestureEdgeSwipe(const ui::GestureEvent& gesture) {
393 if (IsShelfForcedToBeVisible())
396 if (visibility_state() == SHELF_AUTO_HIDE) {
397 gesture_drag_auto_hide_state_ = SHELF_AUTO_HIDE_SHOWN;
398 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS;
399 UpdateVisibilityState();
400 gesture_drag_status_ = GESTURE_DRAG_NONE;
404 void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) {
405 if (IsShelfForcedToBeVisible())
407 gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS;
408 gesture_drag_amount_ = 0.f;
409 gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE ?
410 auto_hide_state() : SHELF_AUTO_HIDE_SHOWN;
411 UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE);
414 ShelfLayoutManager::DragState ShelfLayoutManager::UpdateGestureDrag(
415 const ui::GestureEvent& gesture) {
416 if (IsShelfForcedToBeVisible())
418 bool horizontal = IsHorizontalAlignment();
419 gesture_drag_amount_ += horizontal ? gesture.details().scroll_y() :
420 gesture.details().scroll_x();
423 // Start reveling the status menu when:
424 // - dragging up on an already visible shelf
425 // - dragging up on a hidden shelf, but it is currently completely visible.
426 if (horizontal && gesture.details().scroll_y() < 0) {
428 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && shelf_)
429 min_height = shelf_->GetContentsView()->GetPreferredSize().height();
431 if (min_height < shelf_->GetWindowBoundsInScreen().height() &&
432 gesture.root_location().x() >=
433 shelf_->status_area_widget()->GetWindowBoundsInScreen().x() &&
434 IsDraggingTrayEnabled())
441 void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) {
442 if (IsShelfForcedToBeVisible())
444 bool horizontal = IsHorizontalAlignment();
445 bool should_change = false;
446 if (gesture.type() == ui::ET_GESTURE_SCROLL_END) {
447 // The visibility of the shelf changes only if the shelf was dragged X%
448 // along the correct axis. If the shelf was already visible, then the
449 // direction of the drag does not matter.
450 const float kDragHideThreshold = 0.4f;
451 gfx::Rect bounds = GetIdealBounds();
452 float drag_ratio = fabs(gesture_drag_amount_) /
453 (horizontal ? bounds.height() : bounds.width());
454 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) {
455 should_change = drag_ratio > kDragHideThreshold;
457 bool correct_direction = false;
458 switch (GetAlignment()) {
459 case SHELF_ALIGNMENT_BOTTOM:
460 case SHELF_ALIGNMENT_RIGHT:
461 correct_direction = gesture_drag_amount_ < 0;
463 case SHELF_ALIGNMENT_LEFT:
464 case SHELF_ALIGNMENT_TOP:
465 correct_direction = gesture_drag_amount_ > 0;
468 should_change = correct_direction && drag_ratio > kDragHideThreshold;
470 } else if (gesture.type() == ui::ET_SCROLL_FLING_START) {
471 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN) {
472 should_change = horizontal ? fabs(gesture.details().velocity_y()) > 0 :
473 fabs(gesture.details().velocity_x()) > 0;
475 should_change = SelectValueForShelfAlignment(
476 gesture.details().velocity_y() < 0,
477 gesture.details().velocity_x() > 0,
478 gesture.details().velocity_x() < 0,
479 gesture.details().velocity_y() > 0);
485 if (!should_change) {
490 shelf_->Deactivate();
491 shelf_->status_area_widget()->Deactivate();
493 gesture_drag_auto_hide_state_ =
494 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN ?
495 SHELF_AUTO_HIDE_HIDDEN : SHELF_AUTO_HIDE_SHOWN;
496 ShelfAutoHideBehavior new_auto_hide_behavior =
497 gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_SHOWN ?
498 SHELF_AUTO_HIDE_BEHAVIOR_NEVER : SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
500 // When in fullscreen and the shelf is forced to be auto hidden, the auto hide
501 // behavior affects neither the visibility state nor the auto hide state. Set
502 // |gesture_drag_status_| to GESTURE_DRAG_COMPLETE_IN_PROGRESS to set the auto
503 // hide state to |gesture_drag_auto_hide_state_|.
504 gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS;
505 if (auto_hide_behavior_ != new_auto_hide_behavior)
506 SetAutoHideBehavior(new_auto_hide_behavior);
508 UpdateVisibilityState();
509 gesture_drag_status_ = GESTURE_DRAG_NONE;
512 void ShelfLayoutManager::CancelGestureDrag() {
513 gesture_drag_status_ = GESTURE_DRAG_CANCEL_IN_PROGRESS;
514 UpdateVisibilityState();
515 gesture_drag_status_ = GESTURE_DRAG_NONE;
518 void ShelfLayoutManager::SetAnimationDurationOverride(
519 int duration_override_in_ms) {
520 duration_override_in_ms_ = duration_override_in_ms;
523 ////////////////////////////////////////////////////////////////////////////////
524 // ShelfLayoutManager, aura::LayoutManager implementation:
526 void ShelfLayoutManager::OnWindowResized() {
530 void ShelfLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
533 void ShelfLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
536 void ShelfLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
539 void ShelfLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
543 void ShelfLayoutManager::SetChildBounds(aura::Window* child,
544 const gfx::Rect& requested_bounds) {
545 SetChildBoundsDirect(child, requested_bounds);
546 // We may contain other widgets (such as frame maximize bubble) but they don't
547 // effect the layout in anyway.
548 if (!updating_bounds_ &&
549 ((shelf_->GetNativeView() == child) ||
550 (shelf_->status_area_widget()->GetNativeView() == child))) {
555 void ShelfLayoutManager::OnLockStateChanged(bool locked) {
556 // Force the shelf to layout for alignment (bottom if locked, restore
557 // the previous alignment otherwise).
558 state_.is_screen_locked = locked;
559 shelf_->SetAlignment(locked ? SHELF_ALIGNMENT_BOTTOM : alignment_);
560 UpdateVisibilityState();
564 void ShelfLayoutManager::OnMaximizeModeStarted() {
565 DCHECK(!force_shelf_always_visibile_);
566 force_shelf_always_visibile_ = true;
567 UpdateVisibilityState();
570 void ShelfLayoutManager::OnMaximizeModeEnded() {
571 DCHECK(force_shelf_always_visibile_);
572 // Note: At this time Ash::Shell::IsMaximizeModeWindowManagerEnabled() will
573 // report true, even though it is in progress of shut down. To address this
574 // |force_shelf_always_visibile_| will be read.
575 force_shelf_always_visibile_ = false;
576 UpdateVisibilityState();
579 void ShelfLayoutManager::OnWindowActivated(aura::Window* gained_active,
580 aura::Window* lost_active) {
581 UpdateAutoHideStateNow();
584 bool ShelfLayoutManager::IsHorizontalAlignment() const {
585 return GetAlignment() == SHELF_ALIGNMENT_BOTTOM ||
586 GetAlignment() == SHELF_ALIGNMENT_TOP;
590 ShelfLayoutManager* ShelfLayoutManager::ForShelf(aura::Window* window) {
591 ShelfWidget* shelf = RootWindowController::ForShelf(window)->shelf();
592 return shelf ? shelf->shelf_layout_manager() : NULL;
595 ////////////////////////////////////////////////////////////////////////////////
596 // ShelfLayoutManager, private:
598 ShelfLayoutManager::TargetBounds::TargetBounds() : opacity(0.0f) {}
599 ShelfLayoutManager::TargetBounds::~TargetBounds() {}
601 void ShelfLayoutManager::SetState(ShelfVisibilityState visibility_state) {
602 if (!shelf_->GetNativeView())
606 state.visibility_state = visibility_state;
607 state.auto_hide_state = CalculateAutoHideState(visibility_state);
608 state.window_state = workspace_controller_ ?
609 workspace_controller_->GetWindowState() : WORKSPACE_WINDOW_STATE_DEFAULT;
611 // Force an update because gesture drags affect the shelf bounds and we
612 // should animate back to the normal bounds at the end of a gesture.
614 (gesture_drag_status_ == GESTURE_DRAG_CANCEL_IN_PROGRESS ||
615 gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS);
617 if (!force_update && state_.Equals(state))
618 return; // Nothing changed.
620 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_,
621 WillChangeVisibilityState(visibility_state));
623 if (state.visibility_state == SHELF_AUTO_HIDE) {
624 // When state is SHELF_AUTO_HIDE we need to track when the mouse is over the
625 // shelf to unhide it. AutoHideEventFilter does that for us.
626 if (!auto_hide_event_filter_)
627 auto_hide_event_filter_.reset(new AutoHideEventFilter(this));
629 auto_hide_event_filter_.reset(NULL);
634 State old_state = state_;
637 BackgroundAnimatorChangeType change_type = BACKGROUND_CHANGE_ANIMATE;
638 bool delay_background_change = false;
640 // Do not animate the background when:
641 // - Going from a hidden / auto hidden shelf in fullscreen to a visible shelf
642 // in maximized mode.
643 // - Going from an auto hidden shelf in maximized mode to a visible shelf in
645 if (state.visibility_state == SHELF_VISIBLE &&
646 state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED &&
647 old_state.visibility_state != SHELF_VISIBLE) {
648 change_type = BACKGROUND_CHANGE_IMMEDIATE;
650 // Delay the animation when the shelf was hidden, and has just been made
651 // visible (e.g. using a gesture-drag).
652 if (state.visibility_state == SHELF_VISIBLE &&
653 old_state.visibility_state == SHELF_AUTO_HIDE &&
654 old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) {
655 delay_background_change = true;
659 if (delay_background_change) {
660 if (update_shelf_observer_)
661 update_shelf_observer_->Detach();
662 // UpdateShelfBackground deletes itself when the animation is done.
663 update_shelf_observer_ = new UpdateShelfObserver(this);
665 UpdateShelfBackground(change_type);
668 shelf_->SetDimsShelf(
669 state.visibility_state == SHELF_VISIBLE &&
670 state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED);
672 TargetBounds target_bounds;
673 CalculateTargetBounds(state_, &target_bounds);
674 UpdateBoundsAndOpacity(target_bounds, true,
675 delay_background_change ? update_shelf_observer_ : NULL);
677 // OnAutoHideStateChanged Should be emitted when:
678 // - firstly state changed to auto-hide from other state
679 // - or, auto_hide_state has changed
680 if ((old_state.visibility_state != state_.visibility_state &&
681 state_.visibility_state == SHELF_AUTO_HIDE) ||
682 old_state.auto_hide_state != state_.auto_hide_state) {
683 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_,
684 OnAutoHideStateChanged(state_.auto_hide_state));
688 void ShelfLayoutManager::UpdateBoundsAndOpacity(
689 const TargetBounds& target_bounds,
691 ui::ImplicitAnimationObserver* observer) {
692 base::AutoReset<bool> auto_reset_updating_bounds(&updating_bounds_, true);
694 ui::ScopedLayerAnimationSettings shelf_animation_setter(
695 GetLayer(shelf_)->GetAnimator());
696 ui::ScopedLayerAnimationSettings status_animation_setter(
697 GetLayer(shelf_->status_area_widget())->GetAnimator());
699 int duration = duration_override_in_ms_ ? duration_override_in_ms_ :
700 kCrossFadeDurationMS;
701 shelf_animation_setter.SetTransitionDuration(
702 base::TimeDelta::FromMilliseconds(duration));
703 shelf_animation_setter.SetTweenType(gfx::Tween::EASE_OUT);
704 shelf_animation_setter.SetPreemptionStrategy(
705 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
706 status_animation_setter.SetTransitionDuration(
707 base::TimeDelta::FromMilliseconds(duration));
708 status_animation_setter.SetTweenType(gfx::Tween::EASE_OUT);
709 status_animation_setter.SetPreemptionStrategy(
710 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
713 shelf_animation_setter.SetTransitionDuration(base::TimeDelta());
714 status_animation_setter.SetTransitionDuration(base::TimeDelta());
717 status_animation_setter.AddObserver(observer);
719 GetLayer(shelf_)->SetOpacity(target_bounds.opacity);
720 shelf_->SetBounds(ScreenUtil::ConvertRectToScreen(
721 shelf_->GetNativeView()->parent(),
722 target_bounds.shelf_bounds_in_root));
724 GetLayer(shelf_->status_area_widget())->SetOpacity(
725 target_bounds.status_opacity);
726 // TODO(harrym): Once status area widget is a child view of shelf
727 // this can be simplified.
728 gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf;
729 status_bounds.set_x(status_bounds.x() +
730 target_bounds.shelf_bounds_in_root.x());
731 status_bounds.set_y(status_bounds.y() +
732 target_bounds.shelf_bounds_in_root.y());
733 shelf_->status_area_widget()->SetBounds(
734 ScreenUtil::ConvertRectToScreen(
735 shelf_->status_area_widget()->GetNativeView()->parent(),
737 SessionStateDelegate* session_state_delegate =
738 Shell::GetInstance()->session_state_delegate();
739 if (!state_.is_screen_locked) {
741 // If user session is blocked (login to new user session or add user to
742 // the existing session - multi-profile) then give 100% of work area only if
743 // keyboard is not shown.
744 if (!session_state_delegate->IsUserSessionBlocked() ||
745 !keyboard_bounds_.IsEmpty()) {
746 insets = target_bounds.work_area_insets;
748 Shell::GetInstance()->SetDisplayWorkAreaInsets(root_window_, insets);
752 void ShelfLayoutManager::StopAnimating() {
753 GetLayer(shelf_)->GetAnimator()->StopAnimating();
754 GetLayer(shelf_->status_area_widget())->GetAnimator()->StopAnimating();
757 void ShelfLayoutManager::GetShelfSize(int* width, int* height) {
758 *width = *height = 0;
759 gfx::Size status_size(
760 shelf_->status_area_widget()->GetWindowBoundsInScreen().size());
761 if (IsHorizontalAlignment())
762 *height = kShelfSize;
767 void ShelfLayoutManager::AdjustBoundsBasedOnAlignment(int inset,
768 gfx::Rect* bounds) const {
769 bounds->Inset(SelectValueForShelfAlignment(
770 gfx::Insets(0, 0, inset, 0),
771 gfx::Insets(0, inset, 0, 0),
772 gfx::Insets(0, 0, 0, inset),
773 gfx::Insets(inset, 0, 0, 0)));
776 void ShelfLayoutManager::CalculateTargetBounds(
778 TargetBounds* target_bounds) {
779 const gfx::Rect available_bounds(root_window_->bounds());
780 gfx::Rect status_size(
781 shelf_->status_area_widget()->GetWindowBoundsInScreen().size());
782 int shelf_width = 0, shelf_height = 0;
783 GetShelfSize(&shelf_width, &shelf_height);
784 if (IsHorizontalAlignment())
785 shelf_width = available_bounds.width();
787 shelf_height = available_bounds.height();
789 if (state.visibility_state == SHELF_AUTO_HIDE &&
790 state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) {
791 // Auto-hidden shelf always starts with the default size. If a gesture-drag
792 // is in progress, then the call to UpdateTargetBoundsForGesture() below
793 // takes care of setting the height properly.
794 if (IsHorizontalAlignment())
795 shelf_height = kAutoHideSize;
797 shelf_width = kAutoHideSize;
798 } else if (state.visibility_state == SHELF_HIDDEN ||
799 (!keyboard_bounds_.IsEmpty() && !keyboard::IsKeyboardOverscrollEnabled()))
801 if (IsHorizontalAlignment())
807 int bottom_shelf_vertical_offset = available_bounds.bottom();
808 if (keyboard_bounds_.IsEmpty())
809 bottom_shelf_vertical_offset -= shelf_height;
811 bottom_shelf_vertical_offset -= keyboard_bounds_.height();
813 target_bounds->shelf_bounds_in_root = SelectValueForShelfAlignment(
814 gfx::Rect(available_bounds.x(), bottom_shelf_vertical_offset,
815 available_bounds.width(), shelf_height),
816 gfx::Rect(available_bounds.x(), available_bounds.y(),
817 shelf_width, available_bounds.height()),
818 gfx::Rect(available_bounds.right() - shelf_width, available_bounds.y(),
819 shelf_width, available_bounds.height()),
820 gfx::Rect(available_bounds.x(), available_bounds.y(),
821 available_bounds.width(), shelf_height));
823 if (IsHorizontalAlignment())
824 status_size.set_height(kShelfSize);
826 status_size.set_width(kShelfSize);
828 target_bounds->status_bounds_in_shelf = SelectValueForShelfAlignment(
829 gfx::Rect(base::i18n::IsRTL() ? 0 : shelf_width - status_size.width(),
830 0, status_size.width(), status_size.height()),
831 gfx::Rect(shelf_width - status_size.width(),
832 shelf_height - status_size.height(), status_size.width(),
833 status_size.height()),
834 gfx::Rect(0, shelf_height - status_size.height(),
835 status_size.width(), status_size.height()),
836 gfx::Rect(base::i18n::IsRTL() ? 0 : shelf_width - status_size.width(),
837 shelf_height - status_size.height(),
838 status_size.width(), status_size.height()));
840 target_bounds->work_area_insets = SelectValueForShelfAlignment(
841 gfx::Insets(0, 0, GetWorkAreaSize(state, shelf_height), 0),
842 gfx::Insets(0, GetWorkAreaSize(state, shelf_width), 0, 0),
843 gfx::Insets(0, 0, 0, GetWorkAreaSize(state, shelf_width)),
844 gfx::Insets(GetWorkAreaSize(state, shelf_height), 0, 0, 0));
846 // TODO(varkha): The functionality of managing insets for display areas
847 // should probably be pushed to a separate component. This would simplify or
848 // remove entirely the dependency on keyboard and dock.
850 if (!keyboard_bounds_.IsEmpty() && !keyboard::IsKeyboardOverscrollEnabled()) {
851 // Also push in the work area inset for the keyboard if it is visible.
852 gfx::Insets keyboard_insets(0, 0, keyboard_bounds_.height(), 0);
853 target_bounds->work_area_insets += keyboard_insets;
856 // Also push in the work area inset for the dock if it is visible.
857 if (!dock_bounds_.IsEmpty()) {
858 gfx::Insets dock_insets(
859 0, (dock_bounds_.x() > 0 ? 0 : dock_bounds_.width()),
860 0, (dock_bounds_.x() > 0 ? dock_bounds_.width() : 0));
861 target_bounds->work_area_insets += dock_insets;
864 target_bounds->opacity =
865 (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS ||
866 state.visibility_state == SHELF_VISIBLE ||
867 state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f;
868 target_bounds->status_opacity =
869 (state.visibility_state == SHELF_AUTO_HIDE &&
870 state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN &&
871 gesture_drag_status_ != GESTURE_DRAG_IN_PROGRESS) ?
872 0.0f : target_bounds->opacity;
874 if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS)
875 UpdateTargetBoundsForGesture(target_bounds);
877 // This needs to happen after calling UpdateTargetBoundsForGesture(), because
878 // that can change the size of the shelf.
879 target_bounds->shelf_bounds_in_shelf = SelectValueForShelfAlignment(
881 shelf_width - status_size.width(),
882 target_bounds->shelf_bounds_in_root.height()),
883 gfx::Rect(0, 0, target_bounds->shelf_bounds_in_root.width(),
884 shelf_height - status_size.height()),
885 gfx::Rect(0, 0, target_bounds->shelf_bounds_in_root.width(),
886 shelf_height - status_size.height()),
888 shelf_width - status_size.width(),
889 target_bounds->shelf_bounds_in_root.height()));
892 void ShelfLayoutManager::UpdateTargetBoundsForGesture(
893 TargetBounds* target_bounds) const {
894 CHECK_EQ(GESTURE_DRAG_IN_PROGRESS, gesture_drag_status_);
895 bool horizontal = IsHorizontalAlignment();
896 const gfx::Rect& available_bounds(root_window_->bounds());
897 int resistance_free_region = 0;
899 if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN &&
900 visibility_state() == SHELF_AUTO_HIDE &&
901 auto_hide_state() != SHELF_AUTO_HIDE_SHOWN) {
902 // If the shelf was hidden when the drag started (and the state hasn't
903 // changed since then, e.g. because the tray-menu was shown because of the
904 // drag), then allow the drag some resistance-free region at first to make
905 // sure the shelf sticks with the finger until the shelf is visible.
906 resistance_free_region = kShelfSize - kAutoHideSize;
909 bool resist = SelectValueForShelfAlignment(
910 gesture_drag_amount_ < -resistance_free_region,
911 gesture_drag_amount_ > resistance_free_region,
912 gesture_drag_amount_ < -resistance_free_region,
913 gesture_drag_amount_ > resistance_free_region);
915 float translate = 0.f;
917 float diff = fabsf(gesture_drag_amount_) - resistance_free_region;
918 diff = std::min(diff, sqrtf(diff));
919 if (gesture_drag_amount_ < 0)
920 translate = -resistance_free_region - diff;
922 translate = resistance_free_region + diff;
924 translate = gesture_drag_amount_;
928 // Move and size the shelf with the gesture.
929 int shelf_height = target_bounds->shelf_bounds_in_root.height() - translate;
930 shelf_height = std::max(shelf_height, kAutoHideSize);
931 target_bounds->shelf_bounds_in_root.set_height(shelf_height);
932 if (GetAlignment() == SHELF_ALIGNMENT_BOTTOM) {
933 target_bounds->shelf_bounds_in_root.set_y(
934 available_bounds.bottom() - shelf_height);
937 target_bounds->status_bounds_in_shelf.set_y(0);
939 // Move and size the shelf with the gesture.
940 int shelf_width = target_bounds->shelf_bounds_in_root.width();
941 bool right_aligned = GetAlignment() == SHELF_ALIGNMENT_RIGHT;
943 shelf_width -= translate;
945 shelf_width += translate;
946 shelf_width = std::max(shelf_width, kAutoHideSize);
947 target_bounds->shelf_bounds_in_root.set_width(shelf_width);
949 target_bounds->shelf_bounds_in_root.set_x(
950 available_bounds.right() - shelf_width);
954 target_bounds->status_bounds_in_shelf.set_x(0);
956 target_bounds->status_bounds_in_shelf.set_x(
957 target_bounds->shelf_bounds_in_root.width() -
962 void ShelfLayoutManager::UpdateShelfBackground(
963 BackgroundAnimatorChangeType type) {
964 const ShelfBackgroundType background_type(GetShelfBackgroundType());
965 shelf_->SetPaintsBackground(background_type, type);
966 FOR_EACH_OBSERVER(ShelfLayoutManagerObserver, observers_,
967 OnBackgroundUpdated(background_type, type));
970 ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const {
971 if (state_.visibility_state != SHELF_AUTO_HIDE &&
972 state_.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED) {
973 return SHELF_BACKGROUND_MAXIMIZED;
976 if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS ||
977 (!state_.is_screen_locked && window_overlaps_shelf_) ||
978 (state_.visibility_state == SHELF_AUTO_HIDE)) {
979 return SHELF_BACKGROUND_OVERLAP;
982 return SHELF_BACKGROUND_DEFAULT;
985 void ShelfLayoutManager::UpdateAutoHideStateNow() {
986 SetState(state_.visibility_state);
988 // If the state did not change, the auto hide timer may still be running.
992 void ShelfLayoutManager::StopAutoHideTimer() {
993 auto_hide_timer_.Stop();
994 mouse_over_shelf_when_auto_hide_timer_started_ = false;
997 gfx::Rect ShelfLayoutManager::GetAutoHideShowShelfRegionInScreen() const {
998 gfx::Rect shelf_bounds_in_screen = shelf_->GetWindowBoundsInScreen();
999 gfx::Vector2d offset = SelectValueForShelfAlignment(
1000 gfx::Vector2d(0, shelf_bounds_in_screen.height()),
1001 gfx::Vector2d(-kMaxAutoHideShowShelfRegionSize, 0),
1002 gfx::Vector2d(shelf_bounds_in_screen.width(), 0),
1003 gfx::Vector2d(0, -kMaxAutoHideShowShelfRegionSize));
1005 gfx::Rect show_shelf_region_in_screen = shelf_bounds_in_screen;
1006 show_shelf_region_in_screen += offset;
1007 if (IsHorizontalAlignment())
1008 show_shelf_region_in_screen.set_height(kMaxAutoHideShowShelfRegionSize);
1010 show_shelf_region_in_screen.set_width(kMaxAutoHideShowShelfRegionSize);
1012 // TODO: Figure out if we need any special handling when the keyboard is
1014 return show_shelf_region_in_screen;
1017 ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState(
1018 ShelfVisibilityState visibility_state) const {
1019 if (IsShelfForcedToBeVisible())
1020 return SHELF_AUTO_HIDE_SHOWN;
1022 if (visibility_state != SHELF_AUTO_HIDE || !shelf_)
1023 return SHELF_AUTO_HIDE_HIDDEN;
1025 Shell* shell = Shell::GetInstance();
1026 if (shell->GetAppListTargetVisibility())
1027 return SHELF_AUTO_HIDE_SHOWN;
1029 if (shelf_->status_area_widget() &&
1030 shelf_->status_area_widget()->ShouldShowShelf())
1031 return SHELF_AUTO_HIDE_SHOWN;
1033 if (shelf_->shelf() && shelf_->shelf()->IsShowingMenu())
1034 return SHELF_AUTO_HIDE_SHOWN;
1036 if (shelf_->shelf() && shelf_->shelf()->IsShowingOverflowBubble())
1037 return SHELF_AUTO_HIDE_SHOWN;
1039 if (shelf_->IsActive() ||
1040 (shelf_->status_area_widget() &&
1041 shelf_->status_area_widget()->IsActive()))
1042 return SHELF_AUTO_HIDE_SHOWN;
1044 const std::vector<aura::Window*> windows =
1045 ash::MruWindowTracker::BuildWindowList(false);
1047 // Process the window list and check if there are any visible windows.
1048 bool visible_window = false;
1049 for (size_t i = 0; i < windows.size(); ++i) {
1050 if (windows[i] && windows[i]->IsVisible() &&
1051 !wm::GetWindowState(windows[i])->IsMinimized() &&
1052 root_window_ == windows[i]->GetRootWindow()) {
1053 visible_window = true;
1057 // If there are no visible windows do not hide the shelf.
1058 if (!visible_window)
1059 return SHELF_AUTO_HIDE_SHOWN;
1061 if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS)
1062 return gesture_drag_auto_hide_state_;
1064 // Don't show if the user is dragging the mouse.
1065 if (auto_hide_event_filter_.get() && auto_hide_event_filter_->in_mouse_drag())
1066 return SHELF_AUTO_HIDE_HIDDEN;
1068 // Ignore the mouse position if mouse events are disabled.
1069 aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
1070 shelf_->GetNativeWindow()->GetRootWindow());
1071 if (!cursor_client->IsMouseEventsEnabled())
1072 return SHELF_AUTO_HIDE_HIDDEN;
1074 gfx::Rect shelf_region = shelf_->GetWindowBoundsInScreen();
1075 if (shelf_->status_area_widget() &&
1076 shelf_->status_area_widget()->IsMessageBubbleShown() &&
1078 // Increase the the hit test area to prevent the shelf from disappearing
1079 // when the mouse is over the bubble gap.
1080 ShelfAlignment alignment = GetAlignment();
1081 shelf_region.Inset(alignment == SHELF_ALIGNMENT_RIGHT ?
1082 -kNotificationBubbleGapHeight : 0,
1083 alignment == SHELF_ALIGNMENT_BOTTOM ?
1084 -kNotificationBubbleGapHeight : 0,
1085 alignment == SHELF_ALIGNMENT_LEFT ?
1086 -kNotificationBubbleGapHeight : 0,
1087 alignment == SHELF_ALIGNMENT_TOP ?
1088 -kNotificationBubbleGapHeight : 0);
1091 gfx::Point cursor_position_in_screen =
1092 Shell::GetScreen()->GetCursorScreenPoint();
1093 if (shelf_region.Contains(cursor_position_in_screen))
1094 return SHELF_AUTO_HIDE_SHOWN;
1096 // When the shelf is auto hidden and the shelf is on the boundary between two
1097 // displays, it is hard to trigger showing the shelf. For instance, if a
1098 // user's primary display is left of their secondary display, it is hard to
1099 // unautohide a left aligned shelf on the secondary display.
1100 // It is hard because:
1101 // - It is hard to stop the cursor in the shelf "light bar" and not overshoot.
1102 // - The cursor is warped to the other display if the cursor gets to the edge
1104 // Show the shelf if the cursor started on the shelf and the user overshot the
1105 // shelf slightly to make it easier to show the shelf in this situation. We
1106 // do not check |auto_hide_timer_|.IsRunning() because it returns false when
1107 // the timer's task is running.
1108 if ((state_.auto_hide_state == SHELF_AUTO_HIDE_SHOWN ||
1109 mouse_over_shelf_when_auto_hide_timer_started_) &&
1110 GetAutoHideShowShelfRegionInScreen().Contains(
1111 cursor_position_in_screen)) {
1112 return SHELF_AUTO_HIDE_SHOWN;
1115 return SHELF_AUTO_HIDE_HIDDEN;
1118 bool ShelfLayoutManager::IsShelfWindow(aura::Window* window) {
1121 return (shelf_ && shelf_->GetNativeWindow()->Contains(window)) ||
1122 (shelf_->status_area_widget() &&
1123 shelf_->status_area_widget()->GetNativeWindow()->Contains(window));
1126 int ShelfLayoutManager::GetWorkAreaSize(const State& state, int size) const {
1127 if (state.visibility_state == SHELF_VISIBLE)
1129 if (state.visibility_state == SHELF_AUTO_HIDE)
1130 return kAutoHideSize;
1134 bool ShelfLayoutManager::IsShelfForcedToBeVisible() const {
1135 // Bail out early when there is no |workspace_controller_|, which happens
1136 // during shutdown after PrepareForShutdown.
1137 if (!workspace_controller_)
1138 return force_shelf_always_visibile_;
1140 return force_shelf_always_visibile_ &&
1141 workspace_controller_->GetWindowState() !=
1142 WORKSPACE_WINDOW_STATE_FULL_SCREEN;
1145 void ShelfLayoutManager::OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) {
1146 bool keyboard_is_about_to_hide = false;
1147 if (new_bounds.IsEmpty() && !keyboard_bounds_.IsEmpty())
1148 keyboard_is_about_to_hide = true;
1150 keyboard_bounds_ = new_bounds;
1153 SessionStateDelegate* session_state_delegate =
1154 Shell::GetInstance()->session_state_delegate();
1156 // On login screen if keyboard has been just hidden, update bounds just once
1157 // but ignore target_bounds.work_area_insets since shelf overlaps with login
1159 if (session_state_delegate->IsUserSessionBlocked() &&
1160 keyboard_is_about_to_hide) {
1161 Shell::GetInstance()->SetDisplayWorkAreaInsets(root_window_, gfx::Insets());
1165 void ShelfLayoutManager::OnDockBoundsChanging(
1166 const gfx::Rect& dock_bounds,
1167 DockedWindowLayoutManagerObserver::Reason reason) {
1168 // Skip shelf layout in case docked notification originates from this class.
1169 if (reason == DISPLAY_INSETS_CHANGED)
1171 if (dock_bounds_ != dock_bounds) {
1172 dock_bounds_ = dock_bounds;
1174 UpdateVisibilityState();
1175 UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE);
1179 void ShelfLayoutManager::OnLockStateEvent(LockStateObserver::EventType event) {
1180 if (event == EVENT_LOCK_ANIMATION_STARTED) {
1181 // Enter the screen locked state as the animation starts to prevent
1182 // layout changes as the screen locks.
1183 state_.is_screen_locked = true;
1184 // Hide the status area widget (using auto hide animation).
1185 base::AutoReset<ShelfVisibilityState> state(&state_.visibility_state,
1187 TargetBounds target_bounds;
1188 CalculateTargetBounds(state_, &target_bounds);
1189 UpdateBoundsAndOpacity(target_bounds, true, NULL);
1190 UpdateVisibilityState();
1194 void ShelfLayoutManager::SessionStateChanged(
1195 SessionStateDelegate::SessionState state) {
1196 TargetBounds target_bounds;
1197 CalculateTargetBounds(state_, &target_bounds);
1198 UpdateBoundsAndOpacity(target_bounds, true, NULL);
1199 UpdateVisibilityState();