• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ash/shelf/shelf_widget.h"
6 
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_delegate.h"
12 #include "ash/shelf/shelf_layout_manager.h"
13 #include "ash/shelf/shelf_model.h"
14 #include "ash/shelf/shelf_navigator.h"
15 #include "ash/shelf/shelf_view.h"
16 #include "ash/shelf/shelf_widget.h"
17 #include "ash/shell.h"
18 #include "ash/shell_window_ids.h"
19 #include "ash/system/tray/system_tray_delegate.h"
20 #include "ash/wm/status_area_layout_manager.h"
21 #include "ash/wm/window_properties.h"
22 #include "ash/wm/workspace_controller.h"
23 #include "grit/ash_resources.h"
24 #include "ui/aura/client/activation_client.h"
25 #include "ui/aura/root_window.h"
26 #include "ui/aura/window.h"
27 #include "ui/aura/window_observer.h"
28 #include "ui/base/resource/resource_bundle.h"
29 #include "ui/compositor/layer.h"
30 #include "ui/compositor/scoped_layer_animation_settings.h"
31 #include "ui/events/event_constants.h"
32 #include "ui/gfx/canvas.h"
33 #include "ui/gfx/image/image.h"
34 #include "ui/gfx/image/image_skia_operations.h"
35 #include "ui/gfx/skbitmap_operations.h"
36 #include "ui/views/accessible_pane_view.h"
37 #include "ui/views/widget/widget.h"
38 #include "ui/views/widget/widget_delegate.h"
39 
40 namespace {
41 // Size of black border at bottom (or side) of launcher.
42 const int kNumBlackPixels = 3;
43 // Alpha to paint dimming image with.
44 const int kDimAlpha = 128;
45 
46 // The time to dim and un-dim.
47 const int kTimeToDimMs = 3000;  // Slow in dimming.
48 const int kTimeToUnDimMs = 200;  // Fast in activating.
49 
50 // Class used to slightly dim shelf items when maximized and visible.
51 class DimmerView : public views::View,
52                    public views::WidgetDelegate,
53                    ash::internal::BackgroundAnimatorDelegate {
54  public:
55   // If |disable_dimming_animations_for_test| is set, all alpha animations will
56   // be performed instantly.
57   DimmerView(ash::ShelfWidget* shelf_widget,
58              bool disable_dimming_animations_for_test);
59   virtual ~DimmerView();
60 
61   // Called by |DimmerEventFilter| when the mouse |hovered| state changes.
62   void SetHovered(bool hovered);
63 
64   // Force the dimmer to be undimmed.
65   void ForceUndimming(bool force);
66 
67   // views::WidgetDelegate overrides:
GetWidget()68   virtual views::Widget* GetWidget() OVERRIDE {
69     return View::GetWidget();
70   }
GetWidget() const71   virtual const views::Widget* GetWidget() const OVERRIDE {
72     return View::GetWidget();
73   }
74 
75   // ash::internal::BackgroundAnimatorDelegate overrides:
UpdateBackground(int alpha)76   virtual void UpdateBackground(int alpha) OVERRIDE {
77     alpha_ = alpha;
78     SchedulePaint();
79   }
80 
81   // views::View overrides:
82   virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE;
83 
84   // A function to test the current alpha used.
get_dimming_alpha_for_test()85   int get_dimming_alpha_for_test() { return alpha_; }
86 
87  private:
88   // This class monitors mouse events to see if it is on top of the launcher.
89   class DimmerEventFilter : public ui::EventHandler {
90    public:
91     explicit DimmerEventFilter(DimmerView* owner);
92     virtual ~DimmerEventFilter();
93 
94     // Overridden from ui::EventHandler:
95     virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
96     virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
97 
98    private:
99     // The owning class.
100     DimmerView* owner_;
101 
102     // TRUE if the mouse is inside the shelf.
103     bool mouse_inside_;
104 
105     // TRUE if a touch event is inside the shelf.
106     bool touch_inside_;
107 
108     DISALLOW_COPY_AND_ASSIGN(DimmerEventFilter);
109   };
110 
111   // The owning shelf.
112   ash::ShelfWidget* shelf_;
113 
114   // The alpha to use for covering the shelf.
115   int alpha_;
116 
117   // True if the event filter claims that we should not be dimmed.
118   bool is_hovered_;
119 
120   // True if someone forces us not to be dimmed (e.g. a menu is open).
121   bool force_hovered_;
122 
123   // True if animations should be suppressed for a test.
124   bool disable_dimming_animations_for_test_;
125 
126   // The animator for the background transitions.
127   ash::internal::BackgroundAnimator background_animator_;
128 
129   // Notification of entering / exiting of the shelf area by mouse.
130   scoped_ptr<DimmerEventFilter> event_filter_;
131 
132   DISALLOW_COPY_AND_ASSIGN(DimmerView);
133 };
134 
DimmerView(ash::ShelfWidget * shelf_widget,bool disable_dimming_animations_for_test)135 DimmerView::DimmerView(ash::ShelfWidget* shelf_widget,
136                        bool disable_dimming_animations_for_test)
137     : shelf_(shelf_widget),
138       alpha_(kDimAlpha),
139       is_hovered_(false),
140       force_hovered_(false),
141       disable_dimming_animations_for_test_(disable_dimming_animations_for_test),
142       background_animator_(this, 0, kDimAlpha) {
143   event_filter_.reset(new DimmerEventFilter(this));
144   // Make sure it is undimmed at the beginning and then fire off the dimming
145   // animation.
146   background_animator_.SetPaintsBackground(false,
147                                            ash::BACKGROUND_CHANGE_IMMEDIATE);
148   SetHovered(false);
149 }
150 
~DimmerView()151 DimmerView::~DimmerView() {
152 }
153 
SetHovered(bool hovered)154 void DimmerView::SetHovered(bool hovered) {
155   // Remember the hovered state so that we can correct the state once a
156   // possible force state has disappeared.
157   is_hovered_ = hovered;
158   // Undimm also if we were forced to by e.g. an open menu.
159   hovered |= force_hovered_;
160   background_animator_.SetDuration(hovered ? kTimeToUnDimMs : kTimeToDimMs);
161   background_animator_.SetPaintsBackground(!hovered,
162       disable_dimming_animations_for_test_ ?
163           ash::BACKGROUND_CHANGE_IMMEDIATE : ash::BACKGROUND_CHANGE_ANIMATE);
164 }
165 
ForceUndimming(bool force)166 void DimmerView::ForceUndimming(bool force) {
167   bool previous = force_hovered_;
168   force_hovered_ = force;
169   // If the forced change does change the result we apply the change.
170   if (is_hovered_ || force_hovered_ != is_hovered_ || previous)
171     SetHovered(is_hovered_);
172 }
173 
OnPaintBackground(gfx::Canvas * canvas)174 void DimmerView::OnPaintBackground(gfx::Canvas* canvas) {
175   SkPaint paint;
176   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
177   gfx::ImageSkia launcher_background =
178       *rb.GetImageNamed(IDR_AURA_LAUNCHER_DIMMING).ToImageSkia();
179 
180   if (shelf_->GetAlignment() != ash::SHELF_ALIGNMENT_BOTTOM) {
181     launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage(
182         launcher_background,
183         shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
184             SkBitmapOperations::ROTATION_90_CW,
185             SkBitmapOperations::ROTATION_90_CW,
186             SkBitmapOperations::ROTATION_270_CW,
187             SkBitmapOperations::ROTATION_180_CW));
188   }
189   paint.setAlpha(alpha_);
190   canvas->DrawImageInt(
191       launcher_background,
192       0, 0, launcher_background.width(), launcher_background.height(),
193       0, 0, width(), height(),
194       false,
195       paint);
196 }
197 
DimmerEventFilter(DimmerView * owner)198 DimmerView::DimmerEventFilter::DimmerEventFilter(DimmerView* owner)
199     : owner_(owner),
200       mouse_inside_(false),
201       touch_inside_(false) {
202   ash::Shell::GetInstance()->AddPreTargetHandler(this);
203 }
204 
~DimmerEventFilter()205 DimmerView::DimmerEventFilter::~DimmerEventFilter() {
206   ash::Shell::GetInstance()->RemovePreTargetHandler(this);
207 }
208 
OnMouseEvent(ui::MouseEvent * event)209 void DimmerView::DimmerEventFilter::OnMouseEvent(ui::MouseEvent* event) {
210   if (event->type() != ui::ET_MOUSE_MOVED &&
211       event->type() != ui::ET_MOUSE_DRAGGED)
212     return;
213   bool inside = owner_->GetBoundsInScreen().Contains(event->root_location());
214   if (mouse_inside_ || touch_inside_ != inside || touch_inside_)
215     owner_->SetHovered(inside || touch_inside_);
216   mouse_inside_ = inside;
217 }
218 
OnTouchEvent(ui::TouchEvent * event)219 void DimmerView::DimmerEventFilter::OnTouchEvent(ui::TouchEvent* event) {
220   bool touch_inside = false;
221   if (event->type() != ui::ET_TOUCH_RELEASED &&
222       event->type() != ui::ET_TOUCH_CANCELLED)
223     touch_inside = owner_->GetBoundsInScreen().Contains(event->root_location());
224 
225   if (mouse_inside_ || touch_inside_ != mouse_inside_ || touch_inside)
226     owner_->SetHovered(mouse_inside_ || touch_inside);
227   touch_inside_ = touch_inside;
228 }
229 
230 }  // namespace
231 
232 namespace ash {
233 
234 // The contents view of the Shelf. This view contains ShelfView and
235 // sizes it to the width of the shelf minus the size of the status area.
236 class ShelfWidget::DelegateView : public views::WidgetDelegate,
237                                   public views::AccessiblePaneView,
238                                   public internal::BackgroundAnimatorDelegate,
239                                   public aura::WindowObserver {
240  public:
241   explicit DelegateView(ShelfWidget* shelf);
242   virtual ~DelegateView();
243 
set_focus_cycler(internal::FocusCycler * focus_cycler)244   void set_focus_cycler(internal::FocusCycler* focus_cycler) {
245     focus_cycler_ = focus_cycler;
246   }
focus_cycler()247   internal::FocusCycler* focus_cycler() {
248     return focus_cycler_;
249   }
250 
opaque_background()251   ui::Layer* opaque_background() { return &opaque_background_; }
252 
253   // Set if the shelf area is dimmed (eg when a window is maximized).
254   void SetDimmed(bool dimmed);
255   bool GetDimmed() const;
256 
257   void SetParentLayer(ui::Layer* layer);
258 
259   // views::View overrides:
260   virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE;
261 
262   // views::WidgetDelegateView overrides:
GetWidget()263   virtual views::Widget* GetWidget() OVERRIDE {
264     return View::GetWidget();
265   }
GetWidget() const266   virtual const views::Widget* GetWidget() const OVERRIDE {
267     return View::GetWidget();
268   }
269 
270   virtual bool CanActivate() const OVERRIDE;
271   virtual void Layout() OVERRIDE;
272   virtual void ReorderChildLayers(ui::Layer* parent_layer) OVERRIDE;
273   // This will be called when the parent local bounds change.
274   virtual void OnBoundsChanged(const gfx::Rect& old_bounds) OVERRIDE;
275 
276   // aura::WindowObserver overrides:
277   // This will be called when the shelf itself changes its absolute position.
278   // Since the |dimmer_| panel needs to be placed in screen coordinates it needs
279   // to be repositioned. The difference to the OnBoundsChanged call above is
280   // that this gets also triggered when the shelf only moves.
281   virtual void OnWindowBoundsChanged(aura::Window* window,
282                                      const gfx::Rect& old_bounds,
283                                      const gfx::Rect& new_bounds) OVERRIDE;
284 
285   // BackgroundAnimatorDelegate overrides:
286   virtual void UpdateBackground(int alpha) OVERRIDE;
287 
288   // Force the shelf to be presented in an undimmed state.
289   void ForceUndimming(bool force);
290 
291   // A function to test the current alpha used by the dimming bar. If there is
292   // no dimmer active, the function will return -1.
293   int GetDimmingAlphaForTest();
294 
295   // A function to test the bounds of the dimming bar. Returns gfx::Rect() if
296   // the dimmer is inactive.
297   gfx::Rect GetDimmerBoundsForTest();
298 
299   // Disable dimming animations for running tests. This needs to be called
300   // prior to the creation of of the |dimmer_|.
disable_dimming_animations_for_test()301   void disable_dimming_animations_for_test() {
302     disable_dimming_animations_for_test_ = true;
303   }
304 
305  private:
306   ShelfWidget* shelf_;
307   scoped_ptr<views::Widget> dimmer_;
308   internal::FocusCycler* focus_cycler_;
309   int alpha_;
310   ui::Layer opaque_background_;
311 
312   // The view which does the dimming.
313   DimmerView* dimmer_view_;
314 
315   // True if dimming animations should be turned off.
316   bool disable_dimming_animations_for_test_;
317 
318   DISALLOW_COPY_AND_ASSIGN(DelegateView);
319 };
320 
DelegateView(ShelfWidget * shelf)321 ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf)
322     : shelf_(shelf),
323       focus_cycler_(NULL),
324       alpha_(0),
325       opaque_background_(ui::LAYER_SOLID_COLOR),
326       dimmer_view_(NULL),
327       disable_dimming_animations_for_test_(false) {
328   set_allow_deactivate_on_esc(true);
329   opaque_background_.SetColor(SK_ColorBLACK);
330   opaque_background_.SetBounds(GetLocalBounds());
331   opaque_background_.SetOpacity(0.0f);
332 }
333 
~DelegateView()334 ShelfWidget::DelegateView::~DelegateView() {
335   // Make sure that the dimmer goes away since it might have set an observer.
336   SetDimmed(false);
337 }
338 
SetDimmed(bool value)339 void ShelfWidget::DelegateView::SetDimmed(bool value) {
340   if (value == (dimmer_.get() != NULL))
341     return;
342 
343   if (value) {
344     dimmer_.reset(new views::Widget);
345     views::Widget::InitParams params(
346         views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
347     params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
348     params.can_activate = false;
349     params.accept_events = false;
350     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
351     params.parent = shelf_->GetNativeView();
352     dimmer_->Init(params);
353     dimmer_->GetNativeWindow()->SetName("ShelfDimmer");
354     dimmer_->SetBounds(shelf_->GetWindowBoundsInScreen());
355     // The launcher should not take focus when it is initially shown.
356     dimmer_->set_focus_on_creation(false);
357     dimmer_view_ = new DimmerView(shelf_, disable_dimming_animations_for_test_);
358     dimmer_->SetContentsView(dimmer_view_);
359     dimmer_->GetNativeView()->SetName("ShelfDimmerView");
360     dimmer_->Show();
361     shelf_->GetNativeView()->AddObserver(this);
362   } else {
363     // Some unit tests will come here with a destroyed window.
364     if (shelf_->GetNativeView())
365       shelf_->GetNativeView()->RemoveObserver(this);
366     dimmer_view_ = NULL;
367     dimmer_.reset(NULL);
368   }
369 }
370 
GetDimmed() const371 bool ShelfWidget::DelegateView::GetDimmed() const {
372   return dimmer_.get() && dimmer_->IsVisible();
373 }
374 
SetParentLayer(ui::Layer * layer)375 void ShelfWidget::DelegateView::SetParentLayer(ui::Layer* layer) {
376   layer->Add(&opaque_background_);
377   ReorderLayers();
378 }
379 
OnPaintBackground(gfx::Canvas * canvas)380 void ShelfWidget::DelegateView::OnPaintBackground(gfx::Canvas* canvas) {
381   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
382   gfx::ImageSkia launcher_background =
383       *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND);
384   if (SHELF_ALIGNMENT_BOTTOM != shelf_->GetAlignment())
385     launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage(
386         launcher_background,
387         shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
388             SkBitmapOperations::ROTATION_90_CW,
389             SkBitmapOperations::ROTATION_90_CW,
390             SkBitmapOperations::ROTATION_270_CW,
391             SkBitmapOperations::ROTATION_180_CW));
392   const gfx::Rect dock_bounds(shelf_->shelf_layout_manager()->dock_bounds());
393   SkPaint paint;
394   paint.setAlpha(alpha_);
395   canvas->DrawImageInt(
396       launcher_background,
397       0, 0, launcher_background.width(), launcher_background.height(),
398       (SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() &&
399        dock_bounds.x() == 0 && dock_bounds.width() > 0) ?
400            dock_bounds.width() : 0, 0,
401       SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() ?
402           width() - dock_bounds.width() : width(), height(),
403       false,
404       paint);
405   if (SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() &&
406       dock_bounds.width() > 0) {
407     // The part of the shelf background that is in the corner below the docked
408     // windows close to the work area is an arched gradient that blends
409     // vertically oriented docked background and horizontal shelf.
410     gfx::ImageSkia launcher_corner =
411         *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_CORNER);
412     if (dock_bounds.x() == 0) {
413       launcher_corner = gfx::ImageSkiaOperations::CreateRotatedImage(
414           launcher_corner, SkBitmapOperations::ROTATION_90_CW);
415     }
416     canvas->DrawImageInt(
417         launcher_corner,
418         0, 0, launcher_corner.width(), launcher_corner.height(),
419         dock_bounds.x() > 0 ? dock_bounds.x() : dock_bounds.width() - height(),
420         0,
421         height(), height(),
422         false,
423         paint);
424     // The part of the shelf background that is just below the docked windows
425     // is drawn using the last (lowest) 1-pixel tall strip of the image asset.
426     // This avoids showing the border 3D shadow between the shelf and the dock.
427     canvas->DrawImageInt(
428         launcher_background,
429         0, launcher_background.height() - 1, launcher_background.width(), 1,
430         dock_bounds.x() > 0 ? dock_bounds.x() + height() : 0, 0,
431         dock_bounds.width() - height(), height(),
432         false,
433         paint);
434   }
435   gfx::Rect black_rect =
436       shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
437           gfx::Rect(0, height() - kNumBlackPixels, width(), kNumBlackPixels),
438           gfx::Rect(0, 0, kNumBlackPixels, height()),
439           gfx::Rect(width() - kNumBlackPixels, 0, kNumBlackPixels, height()),
440           gfx::Rect(0, 0, width(), kNumBlackPixels));
441   canvas->FillRect(black_rect, SK_ColorBLACK);
442 }
443 
CanActivate() const444 bool ShelfWidget::DelegateView::CanActivate() const {
445   // Allow to activate as fallback.
446   if (shelf_->activating_as_fallback_)
447     return true;
448   // Allow to activate from the focus cycler.
449   if (focus_cycler_ && focus_cycler_->widget_activating() == GetWidget())
450     return true;
451   // Disallow activating in other cases, especially when using mouse.
452   return false;
453 }
454 
Layout()455 void ShelfWidget::DelegateView::Layout() {
456   for(int i = 0; i < child_count(); ++i) {
457     if (shelf_->shelf_layout_manager()->IsHorizontalAlignment()) {
458       child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(),
459                              child_at(i)->width(), height());
460     } else {
461       child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(),
462                              width(), child_at(i)->height());
463     }
464   }
465 }
466 
ReorderChildLayers(ui::Layer * parent_layer)467 void ShelfWidget::DelegateView::ReorderChildLayers(ui::Layer* parent_layer) {
468   views::View::ReorderChildLayers(parent_layer);
469   parent_layer->StackAtBottom(&opaque_background_);
470 }
471 
OnBoundsChanged(const gfx::Rect & old_bounds)472 void ShelfWidget::DelegateView::OnBoundsChanged(const gfx::Rect& old_bounds) {
473   opaque_background_.SetBounds(GetLocalBounds());
474   if (dimmer_)
475     dimmer_->SetBounds(GetBoundsInScreen());
476 }
477 
OnWindowBoundsChanged(aura::Window * window,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)478 void ShelfWidget::DelegateView::OnWindowBoundsChanged(
479     aura::Window* window,
480     const gfx::Rect& old_bounds,
481     const gfx::Rect& new_bounds) {
482   // Coming here the shelf got repositioned and since the |dimmer_| is placed
483   // in screen coordinates and not relative to the parent it needs to be
484   // repositioned accordingly.
485   dimmer_->SetBounds(GetBoundsInScreen());
486 }
487 
ForceUndimming(bool force)488 void ShelfWidget::DelegateView::ForceUndimming(bool force) {
489   if (GetDimmed())
490     dimmer_view_->ForceUndimming(force);
491 }
492 
GetDimmingAlphaForTest()493 int ShelfWidget::DelegateView::GetDimmingAlphaForTest() {
494   if (GetDimmed())
495     return dimmer_view_->get_dimming_alpha_for_test();
496   return -1;
497 }
498 
GetDimmerBoundsForTest()499 gfx::Rect ShelfWidget::DelegateView::GetDimmerBoundsForTest() {
500   if (GetDimmed())
501     return dimmer_view_->GetBoundsInScreen();
502   return gfx::Rect();
503 }
504 
UpdateBackground(int alpha)505 void ShelfWidget::DelegateView::UpdateBackground(int alpha) {
506   alpha_ = alpha;
507   SchedulePaint();
508 }
509 
ShelfWidget(aura::Window * shelf_container,aura::Window * status_container,internal::WorkspaceController * workspace_controller)510 ShelfWidget::ShelfWidget(aura::Window* shelf_container,
511                          aura::Window* status_container,
512                          internal::WorkspaceController* workspace_controller)
513     : delegate_view_(new DelegateView(this)),
514       background_animator_(delegate_view_, 0, kLauncherBackgroundAlpha),
515       activating_as_fallback_(false),
516       window_container_(shelf_container) {
517   views::Widget::InitParams params(
518       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
519   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
520   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
521   params.parent = shelf_container;
522   params.delegate = delegate_view_;
523   Init(params);
524 
525   // The shelf should not take focus when initially shown.
526   set_focus_on_creation(false);
527   SetContentsView(delegate_view_);
528   delegate_view_->SetParentLayer(GetLayer());
529 
530   status_area_widget_ = new internal::StatusAreaWidget(status_container);
531   status_area_widget_->CreateTrayViews();
532   if (Shell::GetInstance()->session_state_delegate()->
533           IsActiveUserSessionStarted()) {
534     status_area_widget_->Show();
535   }
536   Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_);
537 
538   shelf_layout_manager_ = new internal::ShelfLayoutManager(this);
539   shelf_layout_manager_->AddObserver(this);
540   shelf_container->SetLayoutManager(shelf_layout_manager_);
541   shelf_layout_manager_->set_workspace_controller(workspace_controller);
542   workspace_controller->SetShelf(shelf_layout_manager_);
543 
544   status_container->SetLayoutManager(
545       new internal::StatusAreaLayoutManager(this));
546 
547   views::Widget::AddObserver(this);
548 }
549 
~ShelfWidget()550 ShelfWidget::~ShelfWidget() {
551   RemoveObserver(this);
552 }
553 
SetPaintsBackground(ShelfBackgroundType background_type,BackgroundAnimatorChangeType change_type)554 void ShelfWidget::SetPaintsBackground(
555     ShelfBackgroundType background_type,
556     BackgroundAnimatorChangeType change_type) {
557   ui::Layer* opaque_background = delegate_view_->opaque_background();
558   float target_opacity =
559       (background_type == SHELF_BACKGROUND_MAXIMIZED) ? 1.0f : 0.0f;
560   scoped_ptr<ui::ScopedLayerAnimationSettings> opaque_background_animation;
561   if (change_type != BACKGROUND_CHANGE_IMMEDIATE) {
562     opaque_background_animation.reset(new ui::ScopedLayerAnimationSettings(
563         opaque_background->GetAnimator()));
564     opaque_background_animation->SetTransitionDuration(
565         base::TimeDelta::FromMilliseconds(kTimeToSwitchBackgroundMs));
566   }
567   opaque_background->SetOpacity(target_opacity);
568 
569   // TODO(mukai): use ui::Layer on both opaque_background and normal background
570   // retire background_animator_ at all. It would be simpler.
571   // See also DockedBackgroundWidget::SetPaintsBackground.
572   background_animator_.SetPaintsBackground(
573       background_type != SHELF_BACKGROUND_DEFAULT,
574       change_type);
575   delegate_view_->SchedulePaint();
576 }
577 
GetBackgroundType() const578 ShelfBackgroundType ShelfWidget::GetBackgroundType() const {
579   if (delegate_view_->opaque_background()->GetTargetOpacity() == 1.0f)
580     return SHELF_BACKGROUND_MAXIMIZED;
581   if (background_animator_.paints_background())
582     return SHELF_BACKGROUND_OVERLAP;
583 
584   return SHELF_BACKGROUND_DEFAULT;
585 }
586 
587 // static
ShelfAlignmentAllowed()588 bool ShelfWidget::ShelfAlignmentAllowed() {
589   if (!ash::switches::ShowShelfAlignmentMenu())
590     return false;
591   user::LoginStatus login_status =
592       Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus();
593 
594   switch (login_status) {
595     case user::LOGGED_IN_USER:
596     case user::LOGGED_IN_OWNER:
597       return true;
598     case user::LOGGED_IN_LOCKED:
599     case user::LOGGED_IN_PUBLIC:
600     case user::LOGGED_IN_LOCALLY_MANAGED:
601     case user::LOGGED_IN_GUEST:
602     case user::LOGGED_IN_RETAIL_MODE:
603     case user::LOGGED_IN_KIOSK_APP:
604     case user::LOGGED_IN_NONE:
605       return false;
606   }
607 
608   DCHECK(false);
609   return false;
610 }
611 
GetAlignment() const612 ShelfAlignment ShelfWidget::GetAlignment() const {
613   return shelf_layout_manager_->GetAlignment();
614 }
615 
SetAlignment(ShelfAlignment alignment)616 void ShelfWidget::SetAlignment(ShelfAlignment alignment) {
617   if (launcher_)
618     launcher_->SetAlignment(alignment);
619   status_area_widget_->SetShelfAlignment(alignment);
620   delegate_view_->SchedulePaint();
621 }
622 
SetDimsShelf(bool dimming)623 void ShelfWidget::SetDimsShelf(bool dimming) {
624   delegate_view_->SetDimmed(dimming);
625   // Repaint all children, allowing updates to reflect dimmed state eg:
626   // status area background, app list button and overflow button.
627   if (launcher_)
628     launcher_->SchedulePaint();
629   status_area_widget_->GetContentsView()->SchedulePaint();
630 }
631 
GetDimsShelf() const632 bool ShelfWidget::GetDimsShelf() const {
633   return delegate_view_->GetDimmed();
634 }
635 
CreateLauncher()636 void ShelfWidget::CreateLauncher() {
637   if (launcher_)
638     return;
639 
640   Shell* shell = Shell::GetInstance();
641   // This needs to be called before shelf_model().
642   ShelfDelegate* shelf_delegate = shell->GetShelfDelegate();
643   if (!shelf_delegate)
644     return;  // Not ready to create Launcher
645 
646   launcher_.reset(new Launcher(shell->shelf_model(),
647                                shell->GetShelfDelegate(),
648                                this));
649   SetFocusCycler(shell->focus_cycler());
650 
651   // Inform the root window controller.
652   internal::RootWindowController::ForWindow(window_container_)->
653       OnLauncherCreated();
654 
655   launcher_->SetVisible(
656       shell->session_state_delegate()->IsActiveUserSessionStarted());
657   shelf_layout_manager_->LayoutShelf();
658   Show();
659 }
660 
IsLauncherVisible() const661 bool ShelfWidget::IsLauncherVisible() const {
662   return launcher_.get() && launcher_->IsVisible();
663 }
664 
SetLauncherVisibility(bool visible)665 void ShelfWidget::SetLauncherVisibility(bool visible) {
666   if (launcher_)
667     launcher_->SetVisible(visible);
668 }
669 
SetFocusCycler(internal::FocusCycler * focus_cycler)670 void ShelfWidget::SetFocusCycler(internal::FocusCycler* focus_cycler) {
671   delegate_view_->set_focus_cycler(focus_cycler);
672   if (focus_cycler)
673     focus_cycler->AddWidget(this);
674 }
675 
GetFocusCycler()676 internal::FocusCycler* ShelfWidget::GetFocusCycler() {
677   return delegate_view_->focus_cycler();
678 }
679 
ShutdownStatusAreaWidget()680 void ShelfWidget::ShutdownStatusAreaWidget() {
681   if (status_area_widget_)
682     status_area_widget_->Shutdown();
683   status_area_widget_ = NULL;
684 }
685 
ForceUndimming(bool force)686 void ShelfWidget::ForceUndimming(bool force) {
687   delegate_view_->ForceUndimming(force);
688 }
689 
OnWidgetActivationChanged(views::Widget * widget,bool active)690 void ShelfWidget::OnWidgetActivationChanged(views::Widget* widget,
691                                             bool active) {
692   activating_as_fallback_ = false;
693   if (active)
694     delegate_view_->SetPaneFocusAndFocusDefault();
695   else
696     delegate_view_->GetFocusManager()->ClearFocus();
697 }
698 
GetDimmingAlphaForTest()699 int ShelfWidget::GetDimmingAlphaForTest() {
700   if (delegate_view_)
701     return delegate_view_->GetDimmingAlphaForTest();
702   return -1;
703 }
704 
GetDimmerBoundsForTest()705 gfx::Rect ShelfWidget::GetDimmerBoundsForTest() {
706   if (delegate_view_)
707     return delegate_view_->GetDimmerBoundsForTest();
708   return gfx::Rect();
709 }
710 
DisableDimmingAnimationsForTest()711 void ShelfWidget::DisableDimmingAnimationsForTest() {
712   DCHECK(delegate_view_);
713   return delegate_view_->disable_dimming_animations_for_test();
714 }
715 
WillDeleteShelf()716 void ShelfWidget::WillDeleteShelf() {
717   shelf_layout_manager_->RemoveObserver(this);
718   shelf_layout_manager_ = NULL;
719 }
720 
721 }  // namespace ash
722