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/focus_cycler.h"
8#include "ash/launcher/launcher_delegate.h"
9#include "ash/launcher/launcher_model.h"
10#include "ash/launcher/launcher_navigator.h"
11#include "ash/launcher/launcher_view.h"
12#include "ash/root_window_controller.h"
13#include "ash/session_state_delegate.h"
14#include "ash/shelf/shelf_layout_manager.h"
15#include "ash/shelf/shelf_widget.h"
16#include "ash/shell.h"
17#include "ash/shell_window_ids.h"
18#include "ash/wm/property_util.h"
19#include "ash/wm/status_area_layout_manager.h"
20#include "ash/wm/window_properties.h"
21#include "ash/wm/workspace_controller.h"
22#include "grit/ash_resources.h"
23#include "ui/aura/client/activation_client.h"
24#include "ui/aura/root_window.h"
25#include "ui/aura/window.h"
26#include "ui/aura/window_observer.h"
27#include "ui/base/events/event_constants.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/gfx/canvas.h"
32#include "ui/gfx/image/image.h"
33#include "ui/gfx/image/image_skia_operations.h"
34#include "ui/gfx/skbitmap_operations.h"
35#include "ui/views/accessible_pane_view.h"
36#include "ui/views/widget/widget.h"
37#include "ui/views/widget/widget_delegate.h"
38
39namespace {
40// Size of black border at bottom (or side) of launcher.
41const int kNumBlackPixels = 3;
42// Alpha to paint dimming image with.
43const int kDimAlpha = 128;
44
45// The time to dim and un-dim.
46const int kTimeToDimMs = 3000;  // Slow in dimming.
47const int kTimeToUnDimMs = 200;  // Fast in activating.
48const int kTimeToSwitchBackgroundMs = 1000;
49
50// Class used to slightly dim shelf items when maximized and visible.
51class 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:
68  virtual views::Widget* GetWidget() OVERRIDE {
69    return View::GetWidget();
70  }
71  virtual const views::Widget* GetWidget() const OVERRIDE {
72    return View::GetWidget();
73  }
74
75  // ash::internal::BackgroundAnimatorDelegate overrides:
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.
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
135DimmerView::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::internal::BackgroundAnimator::CHANGE_IMMEDIATE);
148  SetHovered(false);
149}
150
151DimmerView::~DimmerView() {
152}
153
154void 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::internal::BackgroundAnimator::CHANGE_IMMEDIATE :
164          ash::internal::BackgroundAnimator::CHANGE_ANIMATE);
165}
166
167void DimmerView::ForceUndimming(bool force) {
168  bool previous = force_hovered_;
169  force_hovered_ = force;
170  // If the forced change does change the result we apply the change.
171  if (is_hovered_ || force_hovered_ != is_hovered_ || previous)
172    SetHovered(is_hovered_);
173}
174
175void DimmerView::OnPaintBackground(gfx::Canvas* canvas) {
176  SkPaint paint;
177  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
178  gfx::ImageSkia launcher_background =
179      *rb.GetImageNamed(IDR_AURA_LAUNCHER_DIMMING).ToImageSkia();
180
181  if (shelf_->GetAlignment() != ash::SHELF_ALIGNMENT_BOTTOM) {
182    launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage(
183        launcher_background,
184        shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
185            SkBitmapOperations::ROTATION_90_CW,
186            SkBitmapOperations::ROTATION_90_CW,
187            SkBitmapOperations::ROTATION_270_CW,
188            SkBitmapOperations::ROTATION_180_CW));
189  }
190  paint.setAlpha(alpha_);
191  canvas->DrawImageInt(
192      launcher_background,
193      0, 0, launcher_background.width(), launcher_background.height(),
194      0, 0, width(), height(),
195      false,
196      paint);
197}
198
199DimmerView::DimmerEventFilter::DimmerEventFilter(DimmerView* owner)
200    : owner_(owner),
201      mouse_inside_(false),
202      touch_inside_(false) {
203  ash::Shell::GetInstance()->AddPreTargetHandler(this);
204}
205
206DimmerView::DimmerEventFilter::~DimmerEventFilter() {
207  ash::Shell::GetInstance()->RemovePreTargetHandler(this);
208}
209
210void DimmerView::DimmerEventFilter::OnMouseEvent(ui::MouseEvent* event) {
211  if (event->type() != ui::ET_MOUSE_MOVED &&
212      event->type() != ui::ET_MOUSE_DRAGGED)
213    return;
214  bool inside = owner_->GetBoundsInScreen().Contains(event->root_location());
215  if (mouse_inside_ || touch_inside_ != inside || touch_inside_)
216    owner_->SetHovered(inside || touch_inside_);
217  mouse_inside_ = inside;
218}
219
220void DimmerView::DimmerEventFilter::OnTouchEvent(ui::TouchEvent* event) {
221  bool touch_inside = false;
222  if (event->type() != ui::ET_TOUCH_RELEASED &&
223      event->type() != ui::ET_TOUCH_CANCELLED)
224    touch_inside = owner_->GetBoundsInScreen().Contains(event->root_location());
225
226  if (mouse_inside_ || touch_inside_ != mouse_inside_ || touch_inside)
227    owner_->SetHovered(mouse_inside_ || touch_inside);
228  touch_inside_ = touch_inside;
229}
230
231}  // namespace
232
233namespace ash {
234
235// The contents view of the Shelf. This view contains LauncherView and
236// sizes it to the width of the shelf minus the size of the status area.
237class ShelfWidget::DelegateView : public views::WidgetDelegate,
238                                  public views::AccessiblePaneView,
239                                  public internal::BackgroundAnimatorDelegate {
240 public:
241  explicit DelegateView(ShelfWidget* shelf);
242  virtual ~DelegateView();
243
244  void set_focus_cycler(internal::FocusCycler* focus_cycler) {
245    focus_cycler_ = focus_cycler;
246  }
247  internal::FocusCycler* focus_cycler() {
248    return focus_cycler_;
249  }
250
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  // Set the bounds of the widget.
258  void SetWidgetBounds(const gfx::Rect bounds);
259
260  void SetParentLayer(ui::Layer* layer);
261
262  // views::View overrides:
263  virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE;
264
265  // views::WidgetDelegateView overrides:
266  virtual views::Widget* GetWidget() OVERRIDE {
267    return View::GetWidget();
268  }
269  virtual const views::Widget* GetWidget() const OVERRIDE {
270    return View::GetWidget();
271  }
272
273  virtual bool CanActivate() const OVERRIDE;
274  virtual void Layout() OVERRIDE;
275  virtual void ReorderChildLayers(ui::Layer* parent_layer) OVERRIDE;
276  virtual void OnBoundsChanged(const gfx::Rect& old_bounds) OVERRIDE;
277
278  // BackgroundAnimatorDelegate overrides:
279  virtual void UpdateBackground(int alpha) OVERRIDE;
280
281  // Force the shelf to be presented in an undimmed state.
282  void ForceUndimming(bool force);
283
284  // A function to test the current alpha used by the dimming bar. If there is
285  // no dimmer active, the function will return -1.
286  int GetDimmingAlphaForTest();
287
288  // A function to test the bounds of the dimming bar. Returns gfx::Rect() if
289  // the dimmer is inactive.
290  gfx::Rect GetDimmerBoundsForTest();
291
292  // Disable dimming animations for running tests. This needs to be called
293  // prior to the creation of of the |dimmer_|.
294  void disable_dimming_animations_for_test() {
295    disable_dimming_animations_for_test_ = true;
296  }
297
298 private:
299  ShelfWidget* shelf_;
300  scoped_ptr<views::Widget> dimmer_;
301  internal::FocusCycler* focus_cycler_;
302  int alpha_;
303  ui::Layer opaque_background_;
304
305  // The view which does the dimming.
306  DimmerView* dimmer_view_;
307
308  // True if dimming animations should be turned off.
309  bool disable_dimming_animations_for_test_;
310
311  DISALLOW_COPY_AND_ASSIGN(DelegateView);
312};
313
314ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf)
315    : shelf_(shelf),
316      focus_cycler_(NULL),
317      alpha_(0),
318      opaque_background_(ui::LAYER_SOLID_COLOR),
319      dimmer_view_(NULL),
320      disable_dimming_animations_for_test_(false) {
321  set_allow_deactivate_on_esc(true);
322  opaque_background_.SetColor(SK_ColorBLACK);
323  opaque_background_.SetBounds(GetLocalBounds());
324  opaque_background_.SetOpacity(0.0f);
325}
326
327ShelfWidget::DelegateView::~DelegateView() {
328}
329
330void ShelfWidget::DelegateView::SetDimmed(bool value) {
331  if (value == (dimmer_.get() != NULL))
332    return;
333
334  if (value) {
335    dimmer_.reset(new views::Widget);
336    views::Widget::InitParams params(
337        views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
338    params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
339    params.can_activate = false;
340    params.accept_events = false;
341    params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
342    params.parent = shelf_->GetNativeView();
343    dimmer_->Init(params);
344    dimmer_->GetNativeWindow()->SetName("ShelfDimmer");
345    dimmer_->SetBounds(shelf_->GetWindowBoundsInScreen());
346    // The launcher should not take focus when it is initially shown.
347    dimmer_->set_focus_on_creation(false);
348    dimmer_view_ = new DimmerView(shelf_, disable_dimming_animations_for_test_);
349    dimmer_->SetContentsView(dimmer_view_);
350    dimmer_->GetNativeView()->SetName("ShelfDimmerView");
351    dimmer_->Show();
352  } else {
353    dimmer_view_ = NULL;
354    dimmer_.reset(NULL);
355  }
356}
357
358bool ShelfWidget::DelegateView::GetDimmed() const {
359  return dimmer_.get() && dimmer_->IsVisible();
360}
361
362void ShelfWidget::DelegateView::SetWidgetBounds(const gfx::Rect bounds) {
363  if (dimmer_)
364    dimmer_->SetBounds(bounds);
365}
366
367void ShelfWidget::DelegateView::SetParentLayer(ui::Layer* layer) {
368  layer->Add(&opaque_background_);
369  ReorderLayers();
370}
371
372void ShelfWidget::DelegateView::OnPaintBackground(gfx::Canvas* canvas) {
373  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
374  gfx::ImageSkia launcher_background =
375      *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND);
376  if (SHELF_ALIGNMENT_BOTTOM != shelf_->GetAlignment())
377    launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage(
378        launcher_background,
379        shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
380            SkBitmapOperations::ROTATION_90_CW,
381            SkBitmapOperations::ROTATION_90_CW,
382            SkBitmapOperations::ROTATION_270_CW,
383            SkBitmapOperations::ROTATION_180_CW));
384
385  gfx::Rect black_rect =
386      shelf_->shelf_layout_manager()->SelectValueForShelfAlignment(
387          gfx::Rect(0, height() - kNumBlackPixels, width(), kNumBlackPixels),
388          gfx::Rect(0, 0, kNumBlackPixels, height()),
389          gfx::Rect(width() - kNumBlackPixels, 0, kNumBlackPixels, height()),
390          gfx::Rect(0, 0, width(), kNumBlackPixels));
391
392  SkPaint paint;
393  paint.setAlpha(alpha_);
394  canvas->DrawImageInt(
395      launcher_background,
396      0, 0, launcher_background.width(), launcher_background.height(),
397      0, 0, width(), height(),
398      false,
399      paint);
400  canvas->FillRect(black_rect, SK_ColorBLACK);
401}
402
403bool ShelfWidget::DelegateView::CanActivate() const {
404  // Allow to activate as fallback.
405  if (shelf_->activating_as_fallback_)
406    return true;
407  // Allow to activate from the focus cycler.
408  if (focus_cycler_ && focus_cycler_->widget_activating() == GetWidget())
409    return true;
410  // Disallow activating in other cases, especially when using mouse.
411  return false;
412}
413
414void ShelfWidget::DelegateView::Layout() {
415  for(int i = 0; i < child_count(); ++i) {
416    if (shelf_->shelf_layout_manager()->IsHorizontalAlignment()) {
417      child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(),
418                             child_at(i)->width(), height());
419    } else {
420      child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(),
421                             width(), child_at(i)->height());
422    }
423  }
424}
425
426void ShelfWidget::DelegateView::ReorderChildLayers(ui::Layer* parent_layer) {
427  views::View::ReorderChildLayers(parent_layer);
428  parent_layer->StackAtBottom(&opaque_background_);
429}
430
431void ShelfWidget::DelegateView::OnBoundsChanged(const gfx::Rect& old_bounds) {
432  opaque_background_.SetBounds(GetLocalBounds());
433}
434
435void ShelfWidget::DelegateView::ForceUndimming(bool force) {
436  if (GetDimmed())
437    dimmer_view_->ForceUndimming(force);
438}
439
440int ShelfWidget::DelegateView::GetDimmingAlphaForTest() {
441  if (GetDimmed())
442    return dimmer_view_->get_dimming_alpha_for_test();
443  return -1;
444}
445
446gfx::Rect ShelfWidget::DelegateView::GetDimmerBoundsForTest() {
447  if (GetDimmed())
448    return dimmer_view_->GetBoundsInScreen();
449  return gfx::Rect();
450}
451
452void ShelfWidget::DelegateView::UpdateBackground(int alpha) {
453  alpha_ = alpha;
454  SchedulePaint();
455}
456
457ShelfWidget::ShelfWidget(aura::Window* shelf_container,
458                         aura::Window* status_container,
459                         internal::WorkspaceController* workspace_controller)
460    : delegate_view_(new DelegateView(this)),
461      background_animator_(delegate_view_, 0, kLauncherBackgroundAlpha),
462      activating_as_fallback_(false),
463      window_container_(shelf_container) {
464  views::Widget::InitParams params(
465      views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
466  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
467  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
468  params.parent = shelf_container;
469  params.delegate = delegate_view_;
470  Init(params);
471
472  // The shelf should not take focus when initially shown.
473  set_focus_on_creation(false);
474  SetContentsView(delegate_view_);
475  delegate_view_->SetParentLayer(GetLayer());
476
477  status_area_widget_ = new internal::StatusAreaWidget(status_container);
478  status_area_widget_->CreateTrayViews();
479  if (Shell::GetInstance()->session_state_delegate()->
480          IsActiveUserSessionStarted()) {
481    status_area_widget_->Show();
482  }
483  Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_);
484
485  shelf_layout_manager_ = new internal::ShelfLayoutManager(this);
486  shelf_container->SetLayoutManager(shelf_layout_manager_);
487  shelf_layout_manager_->set_workspace_controller(workspace_controller);
488  workspace_controller->SetShelf(shelf_layout_manager_);
489
490  status_container->SetLayoutManager(
491      new internal::StatusAreaLayoutManager(this));
492
493  views::Widget::AddObserver(this);
494}
495
496ShelfWidget::~ShelfWidget() {
497  RemoveObserver(this);
498}
499
500void ShelfWidget::SetPaintsBackground(
501    ShelfBackgroundType background_type,
502    internal::BackgroundAnimator::ChangeType change_type) {
503  ui::Layer* opaque_background = delegate_view_->opaque_background();
504  float target_opacity =
505      (background_type == SHELF_BACKGROUND_MAXIMIZED) ? 1.0f : 0.0f;
506  scoped_ptr<ui::ScopedLayerAnimationSettings> opaque_background_animation;
507  if (change_type != internal::BackgroundAnimator::CHANGE_IMMEDIATE) {
508    opaque_background_animation.reset(new ui::ScopedLayerAnimationSettings(
509        opaque_background->GetAnimator()));
510    opaque_background_animation->SetTransitionDuration(
511        base::TimeDelta::FromMilliseconds(kTimeToSwitchBackgroundMs));
512  }
513  opaque_background->SetOpacity(target_opacity);
514
515  // TODO(mukai): use ui::Layer on both opaque_background and normal background
516  // retire background_animator_ at all. It would be simpler.
517  background_animator_.SetPaintsBackground(
518      background_type != SHELF_BACKGROUND_DEFAULT,
519      change_type);
520}
521
522ShelfBackgroundType ShelfWidget::GetBackgroundType() const {
523  if (delegate_view_->opaque_background()->GetTargetOpacity() == 1.0f)
524    return SHELF_BACKGROUND_MAXIMIZED;
525  if (background_animator_.paints_background())
526    return SHELF_BACKGROUND_OVERLAP;
527
528  return SHELF_BACKGROUND_DEFAULT;
529}
530
531ShelfAlignment ShelfWidget::GetAlignment() const {
532  return shelf_layout_manager_->GetAlignment();
533}
534
535void ShelfWidget::SetAlignment(ShelfAlignment alignment) {
536  if (launcher_)
537    launcher_->SetAlignment(alignment);
538  status_area_widget_->SetShelfAlignment(alignment);
539  delegate_view_->SchedulePaint();
540}
541
542void ShelfWidget::SetDimsShelf(bool dimming) {
543  delegate_view_->SetDimmed(dimming);
544  // Repaint all children, allowing updates to reflect dimmed state eg:
545  // status area background, app list button and overflow button.
546  if (launcher_)
547    launcher_->SchedulePaint();
548  status_area_widget_->GetContentsView()->SchedulePaint();
549}
550
551bool ShelfWidget::GetDimsShelf() const {
552  return delegate_view_->GetDimmed();
553}
554
555void ShelfWidget::CreateLauncher() {
556  if (launcher_)
557    return;
558
559  Shell* shell = Shell::GetInstance();
560  // This needs to be called before launcher_model().
561  LauncherDelegate* launcher_delegate = shell->GetLauncherDelegate();
562  if (!launcher_delegate)
563    return;  // Not ready to create Launcher
564
565  launcher_.reset(new Launcher(shell->launcher_model(),
566                               shell->GetLauncherDelegate(),
567                               this));
568  SetFocusCycler(shell->focus_cycler());
569
570  // Inform the root window controller.
571  internal::RootWindowController::ForWindow(window_container_)->
572      OnLauncherCreated();
573
574  launcher_->SetVisible(
575      shell->session_state_delegate()->IsActiveUserSessionStarted());
576  shelf_layout_manager_->LayoutShelf();
577  Show();
578}
579
580bool ShelfWidget::IsLauncherVisible() const {
581  return launcher_.get() && launcher_->IsVisible();
582}
583
584void ShelfWidget::SetLauncherVisibility(bool visible) {
585  if (launcher_)
586    launcher_->SetVisible(visible);
587}
588
589void ShelfWidget::SetFocusCycler(internal::FocusCycler* focus_cycler) {
590  delegate_view_->set_focus_cycler(focus_cycler);
591  if (focus_cycler)
592    focus_cycler->AddWidget(this);
593}
594
595internal::FocusCycler* ShelfWidget::GetFocusCycler() {
596  return delegate_view_->focus_cycler();
597}
598
599void ShelfWidget::ShutdownStatusAreaWidget() {
600  if (status_area_widget_)
601    status_area_widget_->Shutdown();
602  status_area_widget_ = NULL;
603}
604
605void ShelfWidget::SetWidgetBounds(const gfx::Rect& rect) {
606  Widget::SetBounds(rect);
607  delegate_view_->SetWidgetBounds(rect);
608}
609
610void ShelfWidget::ForceUndimming(bool force) {
611  delegate_view_->ForceUndimming(force);
612}
613
614void ShelfWidget::OnWidgetActivationChanged(views::Widget* widget,
615                                            bool active) {
616  activating_as_fallback_ = false;
617  if (active)
618    delegate_view_->SetPaneFocusAndFocusDefault();
619  else
620    delegate_view_->GetFocusManager()->ClearFocus();
621}
622
623int ShelfWidget::GetDimmingAlphaForTest() {
624  if (delegate_view_)
625    return delegate_view_->GetDimmingAlphaForTest();
626  return -1;
627}
628
629gfx::Rect ShelfWidget::GetDimmerBoundsForTest() {
630  if (delegate_view_)
631    return delegate_view_->GetDimmerBoundsForTest();
632  return gfx::Rect();
633}
634
635void ShelfWidget::DisableDimmingAnimationsForTest() {
636  DCHECK(delegate_view_);
637  return delegate_view_->disable_dimming_animations_for_test();
638}
639
640}  // namespace ash
641