Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ash / system / tray / tray_background_view.cc
blob53e116f0000e7a7ed1627140f478b02d62b2e4c2
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/system/tray/tray_background_view.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/screen_util.h"
9 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shelf/shelf_widget.h"
11 #include "ash/shell.h"
12 #include "ash/shell_window_ids.h"
13 #include "ash/system/status_area_widget.h"
14 #include "ash/system/status_area_widget_delegate.h"
15 #include "ash/system/tray/system_tray.h"
16 #include "ash/system/tray/tray_constants.h"
17 #include "ash/system/tray/tray_event_filter.h"
18 #include "ash/wm/window_animations.h"
19 #include "base/command_line.h"
20 #include "grit/ash_resources.h"
21 #include "ui/accessibility/ax_view_state.h"
22 #include "ui/aura/window.h"
23 #include "ui/aura/window_event_dispatcher.h"
24 #include "ui/base/nine_image_painter_factory.h"
25 #include "ui/base/ui_base_switches_util.h"
26 #include "ui/compositor/layer.h"
27 #include "ui/compositor/layer_animation_element.h"
28 #include "ui/compositor/scoped_layer_animation_settings.h"
29 #include "ui/events/event_constants.h"
30 #include "ui/gfx/animation/tween.h"
31 #include "ui/gfx/canvas.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/image/image_skia.h"
34 #include "ui/gfx/image/image_skia_operations.h"
35 #include "ui/gfx/nine_image_painter.h"
36 #include "ui/gfx/screen.h"
37 #include "ui/gfx/skia_util.h"
38 #include "ui/gfx/transform.h"
39 #include "ui/views/background.h"
40 #include "ui/views/layout/box_layout.h"
42 namespace {
44 const int kTrayBackgroundAlpha = 100;
45 const int kTrayBackgroundHoverAlpha = 150;
46 const SkColor kTrayBackgroundPressedColor = SkColorSetRGB(66, 129, 244);
48 const int kAnimationDurationForPopupMs = 200;
50 // Duration of opacity animation for visibility changes.
51 const int kAnimationDurationForVisibilityMs = 250;
53 // When becoming visible delay the animation so that StatusAreaWidgetDelegate
54 // can animate sibling views out of the position to be occuped by the
55 // TrayBackgroundView.
56 const int kShowAnimationDelayMs = 100;
58 } // namespace
60 using views::TrayBubbleView;
62 namespace ash {
64 // static
65 const char TrayBackgroundView::kViewClassName[] = "tray/TrayBackgroundView";
67 // Used to track when the anchor widget changes position on screen so that the
68 // bubble position can be updated.
69 class TrayBackgroundView::TrayWidgetObserver : public views::WidgetObserver {
70 public:
71 explicit TrayWidgetObserver(TrayBackgroundView* host)
72 : host_(host) {
75 void OnWidgetBoundsChanged(views::Widget* widget,
76 const gfx::Rect& new_bounds) override {
77 host_->AnchorUpdated();
80 void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override {
81 host_->AnchorUpdated();
84 private:
85 TrayBackgroundView* host_;
87 DISALLOW_COPY_AND_ASSIGN(TrayWidgetObserver);
90 class TrayBackground : public views::Background {
91 public:
92 const static int kImageTypeDefault = 0;
93 const static int kImageTypeOnBlack = 1;
94 const static int kImageTypePressed = 2;
95 const static int kNumStates = 3;
97 const static int kImageHorizontal = 0;
98 const static int kImageVertical = 1;
99 const static int kNumOrientations = 2;
101 explicit TrayBackground(TrayBackgroundView* tray_background_view) :
102 tray_background_view_(tray_background_view) {
103 set_alpha(kTrayBackgroundAlpha);
106 ~TrayBackground() override {}
108 SkColor color() { return color_; }
109 void set_color(SkColor color) { color_ = color; }
110 void set_alpha(int alpha) { color_ = SkColorSetARGB(alpha, 0, 0, 0); }
112 private:
113 ShelfWidget* GetShelfWidget() const {
114 return RootWindowController::ForWindow(tray_background_view_->
115 status_area_widget()->GetNativeWindow())->shelf();
118 // Overridden from views::Background.
119 void Paint(gfx::Canvas* canvas, views::View* view) const override {
120 const int kGridSizeForPainter = 9;
121 const int kImages[kNumOrientations][kNumStates][kGridSizeForPainter] = {
122 { // Horizontal
123 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ),
124 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ_ONBLACK),
125 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ_PRESSED),
127 { // Vertical
128 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL),
129 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL_ONBLACK),
130 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL_PRESSED),
134 int orientation = kImageHorizontal;
135 ShelfWidget* shelf_widget = GetShelfWidget();
136 if (shelf_widget &&
137 !shelf_widget->shelf_layout_manager()->IsHorizontalAlignment())
138 orientation = kImageVertical;
140 int state = kImageTypeDefault;
141 if (tray_background_view_->draw_background_as_active())
142 state = kImageTypePressed;
143 else if (shelf_widget && shelf_widget->GetDimsShelf())
144 state = kImageTypeOnBlack;
145 else
146 state = kImageTypeDefault;
148 ui::CreateNineImagePainter(kImages[orientation][state])
149 ->Paint(canvas, view->GetLocalBounds());
152 SkColor color_;
153 // Reference to the TrayBackgroundView for which this is a background.
154 TrayBackgroundView* tray_background_view_;
156 DISALLOW_COPY_AND_ASSIGN(TrayBackground);
159 TrayBackgroundView::TrayContainer::TrayContainer(ShelfAlignment alignment)
160 : alignment_(alignment) {
161 UpdateLayout();
164 void TrayBackgroundView::TrayContainer::SetAlignment(ShelfAlignment alignment) {
165 if (alignment_ == alignment)
166 return;
167 alignment_ = alignment;
168 UpdateLayout();
171 gfx::Size TrayBackgroundView::TrayContainer::GetPreferredSize() const {
172 if (size_.IsEmpty())
173 return views::View::GetPreferredSize();
174 return size_;
177 void TrayBackgroundView::TrayContainer::ChildPreferredSizeChanged(
178 views::View* child) {
179 PreferredSizeChanged();
182 void TrayBackgroundView::TrayContainer::ChildVisibilityChanged(View* child) {
183 PreferredSizeChanged();
186 void TrayBackgroundView::TrayContainer::ViewHierarchyChanged(
187 const ViewHierarchyChangedDetails& details) {
188 if (details.parent == this)
189 PreferredSizeChanged();
192 void TrayBackgroundView::TrayContainer::UpdateLayout() {
193 // Adjust the size of status tray dark background by adding additional
194 // empty border.
195 if (alignment_ == SHELF_ALIGNMENT_BOTTOM ||
196 alignment_ == SHELF_ALIGNMENT_TOP) {
197 SetBorder(views::Border::CreateEmptyBorder(
198 kPaddingFromEdgeOfShelf,
199 kPaddingFromEdgeOfShelf,
200 kPaddingFromEdgeOfShelf,
201 kPaddingFromEdgeOfShelf));
203 views::BoxLayout* layout =
204 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
205 layout->SetDefaultFlex(1);
206 views::View::SetLayoutManager(layout);
207 } else {
208 SetBorder(views::Border::CreateEmptyBorder(
209 kPaddingFromEdgeOfShelf,
210 kPaddingFromEdgeOfShelf,
211 kPaddingFromEdgeOfShelf,
212 kPaddingFromEdgeOfShelf));
214 views::BoxLayout* layout =
215 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
216 layout->SetDefaultFlex(1);
217 views::View::SetLayoutManager(layout);
219 PreferredSizeChanged();
222 ////////////////////////////////////////////////////////////////////////////////
223 // TrayBackgroundView
225 TrayBackgroundView::TrayBackgroundView(StatusAreaWidget* status_area_widget)
226 : status_area_widget_(status_area_widget),
227 tray_container_(NULL),
228 shelf_alignment_(SHELF_ALIGNMENT_BOTTOM),
229 background_(NULL),
230 hide_background_animator_(this, 0, kTrayBackgroundAlpha),
231 hover_background_animator_(
232 this,
234 kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha),
235 hovered_(false),
236 draw_background_as_active_(false),
237 widget_observer_(new TrayWidgetObserver(this)) {
238 set_notify_enter_exit_on_child(true);
240 // Initially we want to paint the background, but without the hover effect.
241 hide_background_animator_.SetPaintsBackground(
242 true, BACKGROUND_CHANGE_IMMEDIATE);
243 hover_background_animator_.SetPaintsBackground(
244 false, BACKGROUND_CHANGE_IMMEDIATE);
246 tray_container_ = new TrayContainer(shelf_alignment_);
247 SetContents(tray_container_);
248 tray_event_filter_.reset(new TrayEventFilter);
250 SetPaintToLayer(true);
251 SetFillsBoundsOpaquely(false);
252 // Start the tray items not visible, because visibility changes are animated.
253 views::View::SetVisible(false);
256 TrayBackgroundView::~TrayBackgroundView() {
257 if (GetWidget())
258 GetWidget()->RemoveObserver(widget_observer_.get());
259 StopObservingImplicitAnimations();
262 void TrayBackgroundView::Initialize() {
263 GetWidget()->AddObserver(widget_observer_.get());
264 SetTrayBorder();
267 void TrayBackgroundView::SetVisible(bool visible) {
268 if (visible == layer()->GetTargetVisibility())
269 return;
271 if (visible) {
272 // The alignment of the shelf can change while the TrayBackgroundView is
273 // hidden. Reset the offscreen transform so that the animation to becoming
274 // visible reflects the current layout.
275 HideTransformation();
276 // SetVisible(false) is defered until the animation for hiding is done.
277 // Otherwise the view is immediately hidden and the animation does not
278 // render.
279 views::View::SetVisible(true);
280 // If SetVisible(true) is called while animating to not visible, then
281 // views::View::SetVisible(true) is a no-op. When the previous animation
282 // ends layer->SetVisible(false) is called. To prevent this
283 // layer->SetVisible(true) immediately interrupts the animation of this
284 // property, and keeps the layer visible.
285 layer()->SetVisible(true);
288 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
289 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
290 kAnimationDurationForVisibilityMs));
291 animation.SetPreemptionStrategy(
292 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
294 if (visible) {
295 animation.SetTweenType(gfx::Tween::EASE_OUT);
296 // Show is delayed so as to allow time for other children of
297 // StatusAreaWidget to begin animating to their new positions.
298 layer()->GetAnimator()->SchedulePauseForProperties(
299 base::TimeDelta::FromMilliseconds(kShowAnimationDelayMs),
300 ui::LayerAnimationElement::OPACITY |
301 ui::LayerAnimationElement::TRANSFORM);
302 layer()->SetOpacity(1.0f);
303 gfx::Transform transform;
304 transform.Translate(0.0f, 0.0f);
305 layer()->SetTransform(transform);
306 } else {
307 // Listen only to the hide animation. As we cannot turn off visibility
308 // until the animation is over.
309 animation.AddObserver(this);
310 animation.SetTweenType(gfx::Tween::EASE_IN);
311 layer()->SetOpacity(0.0f);
312 layer()->SetVisible(false);
313 HideTransformation();
317 const char* TrayBackgroundView::GetClassName() const {
318 return kViewClassName;
321 void TrayBackgroundView::OnMouseEntered(const ui::MouseEvent& event) {
322 hovered_ = true;
325 void TrayBackgroundView::OnMouseExited(const ui::MouseEvent& event) {
326 hovered_ = false;
329 void TrayBackgroundView::ChildPreferredSizeChanged(views::View* child) {
330 PreferredSizeChanged();
333 void TrayBackgroundView::GetAccessibleState(ui::AXViewState* state) {
334 state->role = ui::AX_ROLE_BUTTON;
335 state->name = GetAccessibleNameForTray();
338 void TrayBackgroundView::AboutToRequestFocusFromTabTraversal(bool reverse) {
339 // Return focus to the login view. See crbug.com/120500.
340 views::View* v = GetNextFocusableView();
341 if (v)
342 v->AboutToRequestFocusFromTabTraversal(reverse);
345 bool TrayBackgroundView::PerformAction(const ui::Event& event) {
346 return false;
349 gfx::Rect TrayBackgroundView::GetFocusBounds() {
350 // The tray itself expands to the right and bottom edge of the screen to make
351 // sure clicking on the edges brings up the popup. However, the focus border
352 // should be only around the container.
353 return GetContentsBounds();
356 void TrayBackgroundView::OnGestureEvent(ui::GestureEvent* event) {
357 if (switches::IsTouchFeedbackEnabled()) {
358 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
359 SetDrawBackgroundAsActive(true);
360 } else if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
361 event->type() == ui::ET_GESTURE_TAP_CANCEL) {
362 SetDrawBackgroundAsActive(false);
365 ActionableView::OnGestureEvent(event);
368 void TrayBackgroundView::UpdateBackground(int alpha) {
369 // The animator should never fire when the alternate shelf layout is used.
370 if (!background_ || draw_background_as_active_)
371 return;
372 background_->set_alpha(hide_background_animator_.alpha() +
373 hover_background_animator_.alpha());
374 SchedulePaint();
377 void TrayBackgroundView::SetContents(views::View* contents) {
378 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
379 AddChildView(contents);
382 void TrayBackgroundView::SetPaintsBackground(
383 bool value, BackgroundAnimatorChangeType change_type) {
384 hide_background_animator_.SetPaintsBackground(value, change_type);
387 void TrayBackgroundView::SetContentsBackground() {
388 background_ = new TrayBackground(this);
389 tray_container_->set_background(background_);
392 ShelfLayoutManager* TrayBackgroundView::GetShelfLayoutManager() {
393 return ShelfLayoutManager::ForShelf(GetWidget()->GetNativeView());
396 void TrayBackgroundView::SetShelfAlignment(ShelfAlignment alignment) {
397 shelf_alignment_ = alignment;
398 SetTrayBorder();
399 tray_container_->SetAlignment(alignment);
402 void TrayBackgroundView::SetTrayBorder() {
403 views::View* parent = status_area_widget_->status_area_widget_delegate();
404 // Tray views are laid out right-to-left or bottom-to-top
405 bool on_edge = (this == parent->child_at(0));
406 int left_edge, top_edge, right_edge, bottom_edge;
407 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
408 top_edge = ShelfLayoutManager::kShelfItemInset;
409 left_edge = 0;
410 bottom_edge = kShelfSize -
411 ShelfLayoutManager::kShelfItemInset - kShelfItemHeight;
412 right_edge = on_edge ? kPaddingFromEdgeOfShelf : 0;
413 } else if (shelf_alignment() == SHELF_ALIGNMENT_LEFT) {
414 top_edge = 0;
415 left_edge = kShelfSize -
416 ShelfLayoutManager::kShelfItemInset - kShelfItemHeight;
417 bottom_edge = on_edge ? kPaddingFromEdgeOfShelf : 0;
418 right_edge = ShelfLayoutManager::kShelfItemInset;
419 } else { // SHELF_ALIGNMENT_RIGHT
420 top_edge = 0;
421 left_edge = ShelfLayoutManager::kShelfItemInset;
422 bottom_edge = on_edge ? kPaddingFromEdgeOfShelf : 0;
423 right_edge = kShelfSize -
424 ShelfLayoutManager::kShelfItemInset - kShelfItemHeight;
426 SetBorder(views::Border::CreateEmptyBorder(
427 top_edge, left_edge, bottom_edge, right_edge));
430 void TrayBackgroundView::OnImplicitAnimationsCompleted() {
431 // If there is another animation in the queue, the reverse animation was
432 // triggered before the completion of animating to invisible. Do not turn off
433 // the visibility so that the next animation may render. The value of
434 // layer()->GetTargetVisibility() can be incorrect if the hide animation was
435 // aborted to schedule an animation to become visible. As the new animation
436 // is not yet added to the queue. crbug.com/374236
437 if(layer()->GetAnimator()->is_animating() ||
438 layer()->GetTargetVisibility())
439 return;
440 views::View::SetVisible(false);
443 bool TrayBackgroundView::RequiresNotificationWhenAnimatorDestroyed() const {
444 // This is needed so that OnImplicitAnimationsCompleted() is called even upon
445 // destruction of the animator. This can occure when parallel animations
446 // caused by ScreenRotationAnimator end before the animations of
447 // TrayBackgroundView. This allows for a proper update to the visual state of
448 // the view. (crbug.com/476667)
449 return true;
452 void TrayBackgroundView::HideTransformation() {
453 gfx::Transform transform;
454 if (shelf_alignment_ == SHELF_ALIGNMENT_BOTTOM ||
455 shelf_alignment_ == SHELF_ALIGNMENT_TOP)
456 transform.Translate(width(), 0.0f);
457 else
458 transform.Translate(0.0f, height());
459 layer()->SetTransform(transform);
462 void TrayBackgroundView::InitializeBubbleAnimations(
463 views::Widget* bubble_widget) {
464 wm::SetWindowVisibilityAnimationType(
465 bubble_widget->GetNativeWindow(),
466 wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
467 wm::SetWindowVisibilityAnimationTransition(
468 bubble_widget->GetNativeWindow(),
469 wm::ANIMATE_HIDE);
470 wm::SetWindowVisibilityAnimationDuration(
471 bubble_widget->GetNativeWindow(),
472 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMs));
475 aura::Window* TrayBackgroundView::GetBubbleWindowContainer() const {
476 return ash::Shell::GetContainer(
477 tray_container()->GetWidget()->GetNativeWindow()->GetRootWindow(),
478 ash::kShellWindowId_SettingBubbleContainer);
481 gfx::Rect TrayBackgroundView::GetBubbleAnchorRect(
482 views::Widget* anchor_widget,
483 TrayBubbleView::AnchorType anchor_type,
484 TrayBubbleView::AnchorAlignment anchor_alignment) const {
485 gfx::Rect rect;
486 if (anchor_widget && anchor_widget->IsVisible()) {
487 rect = anchor_widget->GetWindowBoundsInScreen();
488 if (anchor_type == TrayBubbleView::ANCHOR_TYPE_TRAY) {
489 if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) {
490 bool rtl = base::i18n::IsRTL();
491 rect.Inset(
492 rtl ? kBubblePaddingHorizontalSide : 0,
493 kBubblePaddingHorizontalBottom,
494 rtl ? 0 : kBubblePaddingHorizontalSide,
496 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) {
497 rect.Inset(0, 0, kBubblePaddingVerticalSide + 4,
498 kBubblePaddingVerticalBottom);
499 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) {
500 rect.Inset(kBubblePaddingVerticalSide, 0, 0,
501 kBubblePaddingVerticalBottom);
502 } else {
503 // TODO(bruthig) May need to handle other ANCHOR_ALIGNMENT_ values.
504 // ie. ANCHOR_ALIGNMENT_TOP
505 DCHECK(false) << "Unhandled anchor alignment.";
507 } else if (anchor_type == TrayBubbleView::ANCHOR_TYPE_BUBBLE) {
508 // Invert the offsets to align with the bubble below.
509 // Note that with the alternate shelf layout the tips are not shown and
510 // the offsets for left and right alignment do not need to be applied.
511 int vertical_alignment = 0;
512 int horizontal_alignment = kBubblePaddingVerticalBottom;
513 if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT)
514 rect.Inset(vertical_alignment, 0, 0, horizontal_alignment);
515 else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT)
516 rect.Inset(0, 0, vertical_alignment, horizontal_alignment);
517 } else {
518 DCHECK(false) << "Unhandled anchor type.";
520 } else {
521 aura::Window* target_root = anchor_widget ?
522 anchor_widget->GetNativeView()->GetRootWindow() :
523 Shell::GetPrimaryRootWindow();
524 rect = target_root->bounds();
525 if (anchor_type == TrayBubbleView::ANCHOR_TYPE_TRAY) {
526 if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) {
527 rect = gfx::Rect(
528 base::i18n::IsRTL() ?
529 kPaddingFromRightEdgeOfScreenBottomAlignment :
530 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment,
531 rect.height() - kPaddingFromBottomOfScreenBottomAlignment,
532 0, 0);
533 rect = ScreenUtil::ConvertRectToScreen(target_root, rect);
534 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) {
535 rect = gfx::Rect(
536 kPaddingFromRightEdgeOfScreenBottomAlignment,
537 rect.height() - kPaddingFromBottomOfScreenBottomAlignment,
538 1, 1);
539 rect = ScreenUtil::ConvertRectToScreen(target_root, rect);
540 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) {
541 rect = gfx::Rect(
542 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment,
543 rect.height() - kPaddingFromBottomOfScreenBottomAlignment,
544 1, 1);
545 rect = ScreenUtil::ConvertRectToScreen(target_root, rect);
546 } else {
547 // TODO(bruthig) May need to handle other ANCHOR_ALIGNMENT_ values.
548 // ie. ANCHOR_ALIGNMENT_TOP
549 DCHECK(false) << "Unhandled anchor alignment.";
551 } else {
552 rect = gfx::Rect(
553 base::i18n::IsRTL() ?
554 kPaddingFromRightEdgeOfScreenBottomAlignment :
555 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment,
556 rect.height() - kPaddingFromBottomOfScreenBottomAlignment,
557 0, 0);
560 return rect;
563 TrayBubbleView::AnchorAlignment TrayBackgroundView::GetAnchorAlignment() const {
564 switch (shelf_alignment_) {
565 case SHELF_ALIGNMENT_BOTTOM:
566 return TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM;
567 case SHELF_ALIGNMENT_LEFT:
568 return TrayBubbleView::ANCHOR_ALIGNMENT_LEFT;
569 case SHELF_ALIGNMENT_RIGHT:
570 return TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT;
571 case SHELF_ALIGNMENT_TOP:
572 return TrayBubbleView::ANCHOR_ALIGNMENT_TOP;
574 NOTREACHED();
575 return TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM;
578 void TrayBackgroundView::SetDrawBackgroundAsActive(bool visible) {
579 if (draw_background_as_active_ == visible)
580 return;
581 draw_background_as_active_ = visible;
582 if (!background_)
583 return;
585 // Do not change gradually, changing color between grey and blue is weird.
586 if (draw_background_as_active_)
587 background_->set_color(kTrayBackgroundPressedColor);
588 else if (hovered_)
589 background_->set_alpha(kTrayBackgroundHoverAlpha);
590 else
591 background_->set_alpha(kTrayBackgroundAlpha);
592 SchedulePaint();
595 void TrayBackgroundView::UpdateBubbleViewArrow(
596 views::TrayBubbleView* bubble_view) {
597 // Nothing to do here.
600 } // namespace ash