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