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_widget.h"
7 #include "ash/ash_switches.h"
8 #include "ash/focus_cycler.h"
9 #include "ash/root_window_controller.h"
10 #include "ash/session_state_delegate.h"
11 #include "ash/shelf/shelf_constants.h"
12 #include "ash/shelf/shelf_delegate.h"
13 #include "ash/shelf/shelf_layout_manager.h"
14 #include "ash/shelf/shelf_model.h"
15 #include "ash/shelf/shelf_navigator.h"
16 #include "ash/shelf/shelf_view.h"
17 #include "ash/shelf/shelf_widget.h"
18 #include "ash/shell.h"
19 #include "ash/shell_window_ids.h"
20 #include "ash/system/tray/system_tray_delegate.h"
21 #include "ash/wm/status_area_layout_manager.h"
22 #include "ash/wm/window_properties.h"
23 #include "ash/wm/workspace_controller.h"
24 #include "grit/ash_resources.h"
25 #include "ui/aura/client/activation_client.h"
26 #include "ui/aura/window.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/compositor/layer.h"
31 #include "ui/compositor/scoped_layer_animation_settings.h"
32 #include "ui/events/event_constants.h"
33 #include "ui/gfx/canvas.h"
34 #include "ui/gfx/image/image.h"
35 #include "ui/gfx/image/image_skia_operations.h"
36 #include "ui/gfx/skbitmap_operations.h"
37 #include "ui/views/accessible_pane_view.h"
38 #include "ui/views/widget/widget.h"
39 #include "ui/views/widget/widget_delegate.h"
40 #include "ui/wm/core/easy_resize_window_targeter.h"
43 // Size of black border at bottom (or side) of shelf.
44 const int kNumBlackPixels
= 3;
45 // Alpha to paint dimming image with.
46 const int kDimAlpha
= 128;
48 // The time to dim and un-dim.
49 const int kTimeToDimMs
= 3000; // Slow in dimming.
50 const int kTimeToUnDimMs
= 200; // Fast in activating.
52 // Class used to slightly dim shelf items when maximized and visible.
53 class DimmerView
: public views::View
,
54 public views::WidgetDelegate
,
55 ash::internal::BackgroundAnimatorDelegate
{
57 // If |disable_dimming_animations_for_test| is set, all alpha animations will
58 // be performed instantly.
59 DimmerView(ash::ShelfWidget
* shelf_widget
,
60 bool disable_dimming_animations_for_test
);
61 virtual ~DimmerView();
63 // Called by |DimmerEventFilter| when the mouse |hovered| state changes.
64 void SetHovered(bool hovered
);
66 // Force the dimmer to be undimmed.
67 void ForceUndimming(bool force
);
69 // views::WidgetDelegate overrides:
70 virtual views::Widget
* GetWidget() OVERRIDE
{
71 return View::GetWidget();
73 virtual const views::Widget
* GetWidget() const OVERRIDE
{
74 return View::GetWidget();
77 // ash::internal::BackgroundAnimatorDelegate overrides:
78 virtual void UpdateBackground(int alpha
) OVERRIDE
{
83 // views::View overrides:
84 virtual void OnPaintBackground(gfx::Canvas
* canvas
) OVERRIDE
;
86 // A function to test the current alpha used.
87 int get_dimming_alpha_for_test() { return alpha_
; }
90 // This class monitors mouse events to see if it is on top of the shelf.
91 class DimmerEventFilter
: public ui::EventHandler
{
93 explicit DimmerEventFilter(DimmerView
* owner
);
94 virtual ~DimmerEventFilter();
96 // Overridden from ui::EventHandler:
97 virtual void OnMouseEvent(ui::MouseEvent
* event
) OVERRIDE
;
98 virtual void OnTouchEvent(ui::TouchEvent
* event
) OVERRIDE
;
104 // TRUE if the mouse is inside the shelf.
107 // TRUE if a touch event is inside the shelf.
110 DISALLOW_COPY_AND_ASSIGN(DimmerEventFilter
);
114 ash::ShelfWidget
* shelf_
;
116 // The alpha to use for covering the shelf.
119 // True if the event filter claims that we should not be dimmed.
122 // True if someone forces us not to be dimmed (e.g. a menu is open).
125 // True if animations should be suppressed for a test.
126 bool disable_dimming_animations_for_test_
;
128 // The animator for the background transitions.
129 ash::internal::BackgroundAnimator background_animator_
;
131 // Notification of entering / exiting of the shelf area by mouse.
132 scoped_ptr
<DimmerEventFilter
> event_filter_
;
134 DISALLOW_COPY_AND_ASSIGN(DimmerView
);
137 DimmerView::DimmerView(ash::ShelfWidget
* shelf_widget
,
138 bool disable_dimming_animations_for_test
)
139 : shelf_(shelf_widget
),
142 force_hovered_(false),
143 disable_dimming_animations_for_test_(disable_dimming_animations_for_test
),
144 background_animator_(this, 0, kDimAlpha
) {
145 event_filter_
.reset(new DimmerEventFilter(this));
146 // Make sure it is undimmed at the beginning and then fire off the dimming
148 background_animator_
.SetPaintsBackground(false,
149 ash::BACKGROUND_CHANGE_IMMEDIATE
);
153 DimmerView::~DimmerView() {
156 void DimmerView::SetHovered(bool hovered
) {
157 // Remember the hovered state so that we can correct the state once a
158 // possible force state has disappeared.
159 is_hovered_
= hovered
;
160 // Undimm also if we were forced to by e.g. an open menu.
161 hovered
|= force_hovered_
;
162 background_animator_
.SetDuration(hovered
? kTimeToUnDimMs
: kTimeToDimMs
);
163 background_animator_
.SetPaintsBackground(!hovered
,
164 disable_dimming_animations_for_test_
?
165 ash::BACKGROUND_CHANGE_IMMEDIATE
: ash::BACKGROUND_CHANGE_ANIMATE
);
168 void DimmerView::ForceUndimming(bool force
) {
169 bool previous
= force_hovered_
;
170 force_hovered_
= force
;
171 // If the forced change does change the result we apply the change.
172 if (is_hovered_
|| force_hovered_
!= is_hovered_
|| previous
)
173 SetHovered(is_hovered_
);
176 void DimmerView::OnPaintBackground(gfx::Canvas
* canvas
) {
178 ResourceBundle
& rb
= ResourceBundle::GetSharedInstance();
179 gfx::ImageSkia shelf_background
=
180 *rb
.GetImageNamed(IDR_AURA_LAUNCHER_DIMMING
).ToImageSkia();
182 if (shelf_
->GetAlignment() != ash::SHELF_ALIGNMENT_BOTTOM
) {
183 shelf_background
= gfx::ImageSkiaOperations::CreateRotatedImage(
185 shelf_
->shelf_layout_manager()->SelectValueForShelfAlignment(
186 SkBitmapOperations::ROTATION_90_CW
,
187 SkBitmapOperations::ROTATION_90_CW
,
188 SkBitmapOperations::ROTATION_270_CW
,
189 SkBitmapOperations::ROTATION_180_CW
));
191 paint
.setAlpha(alpha_
);
192 canvas
->DrawImageInt(shelf_background
,
195 shelf_background
.width(),
196 shelf_background
.height(),
205 DimmerView::DimmerEventFilter::DimmerEventFilter(DimmerView
* owner
)
207 mouse_inside_(false),
208 touch_inside_(false) {
209 ash::Shell::GetInstance()->AddPreTargetHandler(this);
212 DimmerView::DimmerEventFilter::~DimmerEventFilter() {
213 ash::Shell::GetInstance()->RemovePreTargetHandler(this);
216 void DimmerView::DimmerEventFilter::OnMouseEvent(ui::MouseEvent
* event
) {
217 if (event
->type() != ui::ET_MOUSE_MOVED
&&
218 event
->type() != ui::ET_MOUSE_DRAGGED
)
220 bool inside
= owner_
->GetBoundsInScreen().Contains(event
->root_location());
221 if (mouse_inside_
|| touch_inside_
!= inside
|| touch_inside_
)
222 owner_
->SetHovered(inside
|| touch_inside_
);
223 mouse_inside_
= inside
;
226 void DimmerView::DimmerEventFilter::OnTouchEvent(ui::TouchEvent
* event
) {
227 bool touch_inside
= false;
228 if (event
->type() != ui::ET_TOUCH_RELEASED
&&
229 event
->type() != ui::ET_TOUCH_CANCELLED
)
230 touch_inside
= owner_
->GetBoundsInScreen().Contains(event
->root_location());
232 if (mouse_inside_
|| touch_inside_
!= mouse_inside_
|| touch_inside
)
233 owner_
->SetHovered(mouse_inside_
|| touch_inside
);
234 touch_inside_
= touch_inside
;
237 using ash::internal::ShelfLayoutManager
;
239 // ShelfWindowTargeter makes it easier to resize windows with the mouse when the
240 // window-edge slightly overlaps with the shelf edge. The targeter also makes it
241 // easier to drag the shelf out with touch while it is hidden.
242 class ShelfWindowTargeter
: public wm::EasyResizeWindowTargeter
,
243 public ash::ShelfLayoutManagerObserver
{
245 ShelfWindowTargeter(aura::Window
* container
,
246 ShelfLayoutManager
* shelf
)
247 : wm::EasyResizeWindowTargeter(container
, gfx::Insets(), gfx::Insets()),
249 WillChangeVisibilityState(shelf_
->visibility_state());
250 shelf_
->AddObserver(this);
253 virtual ~ShelfWindowTargeter() {
254 // |shelf_| may have been destroyed by this time.
256 shelf_
->RemoveObserver(this);
260 gfx::Insets
GetInsetsForAlignment(int distance
,
261 ash::ShelfAlignment alignment
) {
263 case ash::SHELF_ALIGNMENT_BOTTOM
:
264 return gfx::Insets(distance
, 0, 0, 0);
265 case ash::SHELF_ALIGNMENT_LEFT
:
266 return gfx::Insets(0, 0, 0, distance
);
267 case ash::SHELF_ALIGNMENT_RIGHT
:
268 return gfx::Insets(0, distance
, 0, 0);
269 case ash::SHELF_ALIGNMENT_TOP
:
270 return gfx::Insets(0, 0, distance
, 0);
273 return gfx::Insets();
276 // ash::ShelfLayoutManagerObserver:
277 virtual void WillDeleteShelf() OVERRIDE
{
281 virtual void WillChangeVisibilityState(
282 ash::ShelfVisibilityState new_state
) OVERRIDE
{
283 gfx::Insets mouse_insets
;
284 gfx::Insets touch_insets
;
285 if (new_state
== ash::SHELF_VISIBLE
) {
286 // Let clicks at the very top of the shelf through so windows can be
287 // resized with the bottom-right corner and bottom edge.
288 mouse_insets
= GetInsetsForAlignment(
289 ShelfLayoutManager::kWorkspaceAreaVisibleInset
,
290 shelf_
->GetAlignment());
291 } else if (new_state
== ash::SHELF_AUTO_HIDE
) {
292 // Extend the touch hit target out a bit to allow users to drag shelf out
294 touch_insets
= GetInsetsForAlignment(
295 -ShelfLayoutManager::kWorkspaceAreaAutoHideInset
,
296 shelf_
->GetAlignment());
299 set_mouse_extend(mouse_insets
);
300 set_touch_extend(touch_insets
);
303 ShelfLayoutManager
* shelf_
;
305 DISALLOW_COPY_AND_ASSIGN(ShelfWindowTargeter
);
312 // The contents view of the Shelf. This view contains ShelfView and
313 // sizes it to the width of the shelf minus the size of the status area.
314 class ShelfWidget::DelegateView
: public views::WidgetDelegate
,
315 public views::AccessiblePaneView
,
316 public internal::BackgroundAnimatorDelegate
,
317 public aura::WindowObserver
{
319 explicit DelegateView(ShelfWidget
* shelf
);
320 virtual ~DelegateView();
322 void set_focus_cycler(internal::FocusCycler
* focus_cycler
) {
323 focus_cycler_
= focus_cycler
;
325 internal::FocusCycler
* focus_cycler() {
326 return focus_cycler_
;
329 ui::Layer
* opaque_background() { return &opaque_background_
; }
331 // Set if the shelf area is dimmed (eg when a window is maximized).
332 void SetDimmed(bool dimmed
);
333 bool GetDimmed() const;
335 void SetParentLayer(ui::Layer
* layer
);
337 // views::View overrides:
338 virtual void OnPaintBackground(gfx::Canvas
* canvas
) OVERRIDE
;
340 // views::WidgetDelegateView overrides:
341 virtual views::Widget
* GetWidget() OVERRIDE
{
342 return View::GetWidget();
344 virtual const views::Widget
* GetWidget() const OVERRIDE
{
345 return View::GetWidget();
348 virtual bool CanActivate() const OVERRIDE
;
349 virtual void Layout() OVERRIDE
;
350 virtual void ReorderChildLayers(ui::Layer
* parent_layer
) OVERRIDE
;
351 // This will be called when the parent local bounds change.
352 virtual void OnBoundsChanged(const gfx::Rect
& old_bounds
) OVERRIDE
;
354 // aura::WindowObserver overrides:
355 // This will be called when the shelf itself changes its absolute position.
356 // Since the |dimmer_| panel needs to be placed in screen coordinates it needs
357 // to be repositioned. The difference to the OnBoundsChanged call above is
358 // that this gets also triggered when the shelf only moves.
359 virtual void OnWindowBoundsChanged(aura::Window
* window
,
360 const gfx::Rect
& old_bounds
,
361 const gfx::Rect
& new_bounds
) OVERRIDE
;
363 // BackgroundAnimatorDelegate overrides:
364 virtual void UpdateBackground(int alpha
) OVERRIDE
;
366 // Force the shelf to be presented in an undimmed state.
367 void ForceUndimming(bool force
);
369 // A function to test the current alpha used by the dimming bar. If there is
370 // no dimmer active, the function will return -1.
371 int GetDimmingAlphaForTest();
373 // A function to test the bounds of the dimming bar. Returns gfx::Rect() if
374 // the dimmer is inactive.
375 gfx::Rect
GetDimmerBoundsForTest();
377 // Disable dimming animations for running tests. This needs to be called
378 // prior to the creation of of the |dimmer_|.
379 void disable_dimming_animations_for_test() {
380 disable_dimming_animations_for_test_
= true;
385 scoped_ptr
<views::Widget
> dimmer_
;
386 internal::FocusCycler
* focus_cycler_
;
388 ui::Layer opaque_background_
;
390 // The view which does the dimming.
391 DimmerView
* dimmer_view_
;
393 // True if dimming animations should be turned off.
394 bool disable_dimming_animations_for_test_
;
396 DISALLOW_COPY_AND_ASSIGN(DelegateView
);
399 ShelfWidget::DelegateView::DelegateView(ShelfWidget
* shelf
)
403 opaque_background_(ui::LAYER_SOLID_COLOR
),
405 disable_dimming_animations_for_test_(false) {
406 set_allow_deactivate_on_esc(true);
407 opaque_background_
.SetColor(SK_ColorBLACK
);
408 opaque_background_
.SetBounds(GetLocalBounds());
409 opaque_background_
.SetOpacity(0.0f
);
412 ShelfWidget::DelegateView::~DelegateView() {
413 // Make sure that the dimmer goes away since it might have set an observer.
417 void ShelfWidget::DelegateView::SetDimmed(bool value
) {
418 if (value
== (dimmer_
.get() != NULL
))
422 dimmer_
.reset(new views::Widget
);
423 views::Widget::InitParams
params(
424 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
425 params
.opacity
= views::Widget::InitParams::TRANSLUCENT_WINDOW
;
426 params
.can_activate
= false;
427 params
.accept_events
= false;
428 params
.ownership
= views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
429 params
.parent
= shelf_
->GetNativeView();
430 dimmer_
->Init(params
);
431 dimmer_
->GetNativeWindow()->SetName("ShelfDimmer");
432 dimmer_
->SetBounds(shelf_
->GetWindowBoundsInScreen());
433 // The shelf should not take focus when it is initially shown.
434 dimmer_
->set_focus_on_creation(false);
435 dimmer_view_
= new DimmerView(shelf_
, disable_dimming_animations_for_test_
);
436 dimmer_
->SetContentsView(dimmer_view_
);
437 dimmer_
->GetNativeView()->SetName("ShelfDimmerView");
439 shelf_
->GetNativeView()->AddObserver(this);
441 // Some unit tests will come here with a destroyed window.
442 if (shelf_
->GetNativeView())
443 shelf_
->GetNativeView()->RemoveObserver(this);
449 bool ShelfWidget::DelegateView::GetDimmed() const {
450 return dimmer_
.get() && dimmer_
->IsVisible();
453 void ShelfWidget::DelegateView::SetParentLayer(ui::Layer
* layer
) {
454 layer
->Add(&opaque_background_
);
458 void ShelfWidget::DelegateView::OnPaintBackground(gfx::Canvas
* canvas
) {
459 ResourceBundle
& rb
= ResourceBundle::GetSharedInstance();
460 gfx::ImageSkia shelf_background
=
461 *rb
.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND
);
462 if (SHELF_ALIGNMENT_BOTTOM
!= shelf_
->GetAlignment())
463 shelf_background
= gfx::ImageSkiaOperations::CreateRotatedImage(
465 shelf_
->shelf_layout_manager()->SelectValueForShelfAlignment(
466 SkBitmapOperations::ROTATION_90_CW
,
467 SkBitmapOperations::ROTATION_90_CW
,
468 SkBitmapOperations::ROTATION_270_CW
,
469 SkBitmapOperations::ROTATION_180_CW
));
470 const gfx::Rect
dock_bounds(shelf_
->shelf_layout_manager()->dock_bounds());
472 paint
.setAlpha(alpha_
);
473 canvas
->DrawImageInt(shelf_background
,
476 shelf_background
.width(),
477 shelf_background
.height(),
478 (SHELF_ALIGNMENT_BOTTOM
== shelf_
->GetAlignment() &&
479 dock_bounds
.x() == 0 && dock_bounds
.width() > 0)
480 ? dock_bounds
.width()
483 SHELF_ALIGNMENT_BOTTOM
== shelf_
->GetAlignment()
484 ? width() - dock_bounds
.width()
489 if (SHELF_ALIGNMENT_BOTTOM
== shelf_
->GetAlignment() &&
490 dock_bounds
.width() > 0) {
491 // The part of the shelf background that is in the corner below the docked
492 // windows close to the work area is an arched gradient that blends
493 // vertically oriented docked background and horizontal shelf.
494 gfx::ImageSkia shelf_corner
=
495 *rb
.GetImageSkiaNamed(IDR_AURA_LAUNCHER_CORNER
);
496 if (dock_bounds
.x() == 0) {
497 shelf_corner
= gfx::ImageSkiaOperations::CreateRotatedImage(
498 shelf_corner
, SkBitmapOperations::ROTATION_90_CW
);
500 canvas
->DrawImageInt(
504 shelf_corner
.width(),
505 shelf_corner
.height(),
506 dock_bounds
.x() > 0 ? dock_bounds
.x() : dock_bounds
.width() - height(),
512 // The part of the shelf background that is just below the docked windows
513 // is drawn using the last (lowest) 1-pixel tall strip of the image asset.
514 // This avoids showing the border 3D shadow between the shelf and the dock.
515 canvas
->DrawImageInt(shelf_background
,
517 shelf_background
.height() - 1,
518 shelf_background
.width(),
520 dock_bounds
.x() > 0 ? dock_bounds
.x() + height() : 0,
522 dock_bounds
.width() - height(),
527 gfx::Rect black_rect
=
528 shelf_
->shelf_layout_manager()->SelectValueForShelfAlignment(
529 gfx::Rect(0, height() - kNumBlackPixels
, width(), kNumBlackPixels
),
530 gfx::Rect(0, 0, kNumBlackPixels
, height()),
531 gfx::Rect(width() - kNumBlackPixels
, 0, kNumBlackPixels
, height()),
532 gfx::Rect(0, 0, width(), kNumBlackPixels
));
533 canvas
->FillRect(black_rect
, SK_ColorBLACK
);
536 bool ShelfWidget::DelegateView::CanActivate() const {
537 // Allow to activate as fallback.
538 if (shelf_
->activating_as_fallback_
)
540 // Allow to activate from the focus cycler.
541 if (focus_cycler_
&& focus_cycler_
->widget_activating() == GetWidget())
543 // Disallow activating in other cases, especially when using mouse.
547 void ShelfWidget::DelegateView::Layout() {
548 for(int i
= 0; i
< child_count(); ++i
) {
549 if (shelf_
->shelf_layout_manager()->IsHorizontalAlignment()) {
550 child_at(i
)->SetBounds(child_at(i
)->x(), child_at(i
)->y(),
551 child_at(i
)->width(), height());
553 child_at(i
)->SetBounds(child_at(i
)->x(), child_at(i
)->y(),
554 width(), child_at(i
)->height());
559 void ShelfWidget::DelegateView::ReorderChildLayers(ui::Layer
* parent_layer
) {
560 views::View::ReorderChildLayers(parent_layer
);
561 parent_layer
->StackAtBottom(&opaque_background_
);
564 void ShelfWidget::DelegateView::OnBoundsChanged(const gfx::Rect
& old_bounds
) {
565 opaque_background_
.SetBounds(GetLocalBounds());
567 dimmer_
->SetBounds(GetBoundsInScreen());
570 void ShelfWidget::DelegateView::OnWindowBoundsChanged(
571 aura::Window
* window
,
572 const gfx::Rect
& old_bounds
,
573 const gfx::Rect
& new_bounds
) {
574 // Coming here the shelf got repositioned and since the |dimmer_| is placed
575 // in screen coordinates and not relative to the parent it needs to be
576 // repositioned accordingly.
577 dimmer_
->SetBounds(GetBoundsInScreen());
580 void ShelfWidget::DelegateView::ForceUndimming(bool force
) {
582 dimmer_view_
->ForceUndimming(force
);
585 int ShelfWidget::DelegateView::GetDimmingAlphaForTest() {
587 return dimmer_view_
->get_dimming_alpha_for_test();
591 gfx::Rect
ShelfWidget::DelegateView::GetDimmerBoundsForTest() {
593 return dimmer_view_
->GetBoundsInScreen();
597 void ShelfWidget::DelegateView::UpdateBackground(int alpha
) {
602 ShelfWidget::ShelfWidget(aura::Window
* shelf_container
,
603 aura::Window
* status_container
,
604 internal::WorkspaceController
* workspace_controller
)
605 : delegate_view_(new DelegateView(this)),
606 background_animator_(delegate_view_
, 0, kShelfBackgroundAlpha
),
607 activating_as_fallback_(false),
608 window_container_(shelf_container
) {
609 views::Widget::InitParams
params(
610 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
611 params
.opacity
= views::Widget::InitParams::TRANSLUCENT_WINDOW
;
612 params
.ownership
= views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
613 params
.parent
= shelf_container
;
614 params
.delegate
= delegate_view_
;
617 // The shelf should not take focus when initially shown.
618 set_focus_on_creation(false);
619 SetContentsView(delegate_view_
);
620 delegate_view_
->SetParentLayer(GetLayer());
622 status_area_widget_
= new internal::StatusAreaWidget(status_container
);
623 status_area_widget_
->CreateTrayViews();
624 if (Shell::GetInstance()->session_state_delegate()->
625 IsActiveUserSessionStarted()) {
626 status_area_widget_
->Show();
628 Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_
);
630 shelf_layout_manager_
= new internal::ShelfLayoutManager(this);
631 shelf_layout_manager_
->AddObserver(this);
632 shelf_container
->SetLayoutManager(shelf_layout_manager_
);
633 shelf_layout_manager_
->set_workspace_controller(workspace_controller
);
634 workspace_controller
->SetShelf(shelf_layout_manager_
);
636 status_container
->SetLayoutManager(
637 new internal::StatusAreaLayoutManager(this));
639 shelf_container
->SetEventTargeter(scoped_ptr
<ui::EventTargeter
>(new
640 ShelfWindowTargeter(shelf_container
, shelf_layout_manager_
)));
641 status_container
->SetEventTargeter(scoped_ptr
<ui::EventTargeter
>(new
642 ShelfWindowTargeter(status_container
, shelf_layout_manager_
)));
644 views::Widget::AddObserver(this);
647 ShelfWidget::~ShelfWidget() {
648 RemoveObserver(this);
651 void ShelfWidget::SetPaintsBackground(
652 ShelfBackgroundType background_type
,
653 BackgroundAnimatorChangeType change_type
) {
654 ui::Layer
* opaque_background
= delegate_view_
->opaque_background();
655 float target_opacity
=
656 (background_type
== SHELF_BACKGROUND_MAXIMIZED
) ? 1.0f
: 0.0f
;
657 scoped_ptr
<ui::ScopedLayerAnimationSettings
> opaque_background_animation
;
658 if (change_type
!= BACKGROUND_CHANGE_IMMEDIATE
) {
659 opaque_background_animation
.reset(new ui::ScopedLayerAnimationSettings(
660 opaque_background
->GetAnimator()));
661 opaque_background_animation
->SetTransitionDuration(
662 base::TimeDelta::FromMilliseconds(kTimeToSwitchBackgroundMs
));
664 opaque_background
->SetOpacity(target_opacity
);
666 // TODO(mukai): use ui::Layer on both opaque_background and normal background
667 // retire background_animator_ at all. It would be simpler.
668 // See also DockedBackgroundWidget::SetPaintsBackground.
669 background_animator_
.SetPaintsBackground(
670 background_type
!= SHELF_BACKGROUND_DEFAULT
,
672 delegate_view_
->SchedulePaint();
675 ShelfBackgroundType
ShelfWidget::GetBackgroundType() const {
676 if (delegate_view_
->opaque_background()->GetTargetOpacity() == 1.0f
)
677 return SHELF_BACKGROUND_MAXIMIZED
;
678 if (background_animator_
.paints_background())
679 return SHELF_BACKGROUND_OVERLAP
;
681 return SHELF_BACKGROUND_DEFAULT
;
685 bool ShelfWidget::ShelfAlignmentAllowed() {
686 user::LoginStatus login_status
=
687 Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus();
689 switch (login_status
) {
690 case user::LOGGED_IN_USER
:
691 case user::LOGGED_IN_OWNER
:
693 case user::LOGGED_IN_LOCKED
:
694 case user::LOGGED_IN_PUBLIC
:
695 case user::LOGGED_IN_LOCALLY_MANAGED
:
696 case user::LOGGED_IN_GUEST
:
697 case user::LOGGED_IN_RETAIL_MODE
:
698 case user::LOGGED_IN_KIOSK_APP
:
699 case user::LOGGED_IN_NONE
:
707 ShelfAlignment
ShelfWidget::GetAlignment() const {
708 return shelf_layout_manager_
->GetAlignment();
711 void ShelfWidget::SetAlignment(ShelfAlignment alignment
) {
713 shelf_
->SetAlignment(alignment
);
714 status_area_widget_
->SetShelfAlignment(alignment
);
715 delegate_view_
->SchedulePaint();
718 void ShelfWidget::SetDimsShelf(bool dimming
) {
719 delegate_view_
->SetDimmed(dimming
);
720 // Repaint all children, allowing updates to reflect dimmed state eg:
721 // status area background, app list button and overflow button.
723 shelf_
->SchedulePaint();
724 status_area_widget_
->GetContentsView()->SchedulePaint();
727 bool ShelfWidget::GetDimsShelf() const {
728 return delegate_view_
->GetDimmed();
731 void ShelfWidget::CreateShelf() {
735 Shell
* shell
= Shell::GetInstance();
736 // This needs to be called before shelf_model().
737 ShelfDelegate
* shelf_delegate
= shell
->GetShelfDelegate();
739 return; // Not ready to create Shelf.
742 new Shelf(shell
->shelf_model(), shell
->GetShelfDelegate(), this));
743 SetFocusCycler(shell
->focus_cycler());
745 // Inform the root window controller.
746 internal::RootWindowController::ForWindow(window_container_
)
750 shell
->session_state_delegate()->IsActiveUserSessionStarted());
751 shelf_layout_manager_
->LayoutShelf();
755 bool ShelfWidget::IsShelfVisible() const {
756 return shelf_
.get() && shelf_
->IsVisible();
759 void ShelfWidget::SetShelfVisibility(bool visible
) {
761 shelf_
->SetVisible(visible
);
764 void ShelfWidget::SetFocusCycler(internal::FocusCycler
* focus_cycler
) {
765 delegate_view_
->set_focus_cycler(focus_cycler
);
767 focus_cycler
->AddWidget(this);
770 internal::FocusCycler
* ShelfWidget::GetFocusCycler() {
771 return delegate_view_
->focus_cycler();
774 void ShelfWidget::ShutdownStatusAreaWidget() {
775 if (status_area_widget_
)
776 status_area_widget_
->Shutdown();
777 status_area_widget_
= NULL
;
780 void ShelfWidget::ForceUndimming(bool force
) {
781 delegate_view_
->ForceUndimming(force
);
784 void ShelfWidget::OnWidgetActivationChanged(views::Widget
* widget
,
786 activating_as_fallback_
= false;
788 delegate_view_
->SetPaneFocusAndFocusDefault();
790 delegate_view_
->GetFocusManager()->ClearFocus();
793 int ShelfWidget::GetDimmingAlphaForTest() {
795 return delegate_view_
->GetDimmingAlphaForTest();
799 gfx::Rect
ShelfWidget::GetDimmerBoundsForTest() {
801 return delegate_view_
->GetDimmerBoundsForTest();
805 void ShelfWidget::DisableDimmingAnimationsForTest() {
806 DCHECK(delegate_view_
);
807 return delegate_view_
->disable_dimming_animations_for_test();
810 void ShelfWidget::WillDeleteShelf() {
811 shelf_layout_manager_
->RemoveObserver(this);
812 shelf_layout_manager_
= NULL
;