Home | History | Annotate | Download | only in tray
      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/system/tray/tray_background_view.h"
      6 
      7 #include "ash/ash_switches.h"
      8 #include "ash/root_window_controller.h"
      9 #include "ash/screen_ash.h"
     10 #include "ash/shelf/shelf_layout_manager.h"
     11 #include "ash/shelf/shelf_widget.h"
     12 #include "ash/shell.h"
     13 #include "ash/shell_window_ids.h"
     14 #include "ash/system/status_area_widget.h"
     15 #include "ash/system/status_area_widget_delegate.h"
     16 #include "ash/system/tray/system_tray.h"
     17 #include "ash/system/tray/tray_constants.h"
     18 #include "ash/system/tray/tray_event_filter.h"
     19 #include "ash/wm/property_util.h"
     20 #include "ash/wm/window_animations.h"
     21 #include "grit/ash_resources.h"
     22 #include "ui/aura/root_window.h"
     23 #include "ui/aura/window.h"
     24 #include "ui/base/accessibility/accessible_view_state.h"
     25 #include "ui/base/resource/resource_bundle.h"
     26 #include "ui/gfx/canvas.h"
     27 #include "ui/gfx/image/image_skia.h"
     28 #include "ui/gfx/image/image_skia_operations.h"
     29 #include "ui/gfx/rect.h"
     30 #include "ui/gfx/screen.h"
     31 #include "ui/gfx/skia_util.h"
     32 #include "ui/views/background.h"
     33 #include "ui/views/layout/box_layout.h"
     34 
     35 namespace {
     36 
     37 const int kTrayBackgroundAlpha = 100;
     38 const int kTrayBackgroundHoverAlpha = 150;
     39 const SkColor kTrayBackgroundPressedColor = SkColorSetRGB(66, 129, 244);
     40 
     41 // Adjust the size of TrayContainer with additional padding.
     42 const int kTrayContainerVerticalPaddingBottomAlignment  = 1;
     43 const int kTrayContainerHorizontalPaddingBottomAlignment  = 1;
     44 const int kTrayContainerVerticalPaddingVerticalAlignment  = 1;
     45 const int kTrayContainerHorizontalPaddingVerticalAlignment = 1;
     46 
     47 const int kAnimationDurationForPopupMS = 200;
     48 
     49 }  // namespace
     50 
     51 using views::TrayBubbleView;
     52 
     53 namespace ash {
     54 namespace internal {
     55 
     56 // static
     57 const char TrayBackgroundView::kViewClassName[] = "tray/TrayBackgroundView";
     58 
     59 // Used to track when the anchor widget changes position on screen so that the
     60 // bubble position can be updated.
     61 class TrayBackgroundView::TrayWidgetObserver : public views::WidgetObserver {
     62  public:
     63   explicit TrayWidgetObserver(TrayBackgroundView* host)
     64       : host_(host) {
     65   }
     66 
     67   virtual void OnWidgetBoundsChanged(views::Widget* widget,
     68                                      const gfx::Rect& new_bounds) OVERRIDE {
     69     host_->AnchorUpdated();
     70   }
     71 
     72   virtual void OnWidgetVisibilityChanged(views::Widget* widget,
     73                                          bool visible) OVERRIDE {
     74     host_->AnchorUpdated();
     75   }
     76 
     77  private:
     78   TrayBackgroundView* host_;
     79 
     80   DISALLOW_COPY_AND_ASSIGN(TrayWidgetObserver);
     81 };
     82 
     83 class TrayBackground : public views::Background {
     84  public:
     85   const static int kImageTypeDefault = 0;
     86   const static int kImageTypeOnBlack = 1;
     87   const static int kImageTypePressed = 2;
     88   const static int kNumStates = 3;
     89 
     90   const static int kImageHorizontal = 0;
     91   const static int kImageVertical = 1;
     92   const static int kNumOrientations = 2;
     93 
     94   explicit TrayBackground(TrayBackgroundView* tray_background_view) :
     95       tray_background_view_(tray_background_view) {
     96     set_alpha(kTrayBackgroundAlpha);
     97     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
     98     leading_images_[kImageHorizontal][kImageTypeDefault] =
     99         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_LEFT).ToImageSkia();
    100     middle_images_[kImageHorizontal][kImageTypeDefault] =
    101         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_CENTER).ToImageSkia();
    102     trailing_images_[kImageHorizontal][kImageTypeDefault] =
    103         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_RIGHT).ToImageSkia();
    104 
    105     leading_images_[kImageHorizontal][kImageTypeOnBlack] =
    106         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_LEFT_ONBLACK).ToImageSkia();
    107     middle_images_[kImageHorizontal][kImageTypeOnBlack] =
    108         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_CENTER_ONBLACK).ToImageSkia();
    109     trailing_images_[kImageHorizontal][kImageTypeOnBlack] =
    110         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_RIGHT_ONBLACK).ToImageSkia();
    111 
    112     leading_images_[kImageHorizontal][kImageTypePressed] =
    113         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_LEFT_PRESSED).ToImageSkia();
    114     middle_images_[kImageHorizontal][kImageTypePressed] =
    115         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_CENTER_PRESSED).ToImageSkia();
    116     trailing_images_[kImageHorizontal][kImageTypePressed] =
    117         rb.GetImageNamed(IDR_AURA_TRAY_BG_HORIZ_RIGHT_PRESSED).ToImageSkia();
    118 
    119     leading_images_[kImageVertical][kImageTypeDefault] =
    120         rb.GetImageNamed(IDR_AURA_TRAY_BG_VERTICAL_TOP).ToImageSkia();
    121     middle_images_[kImageVertical][kImageTypeDefault] =
    122         rb.GetImageNamed(
    123             IDR_AURA_TRAY_BG_VERTICAL_CENTER).ToImageSkia();
    124     trailing_images_[kImageVertical][kImageTypeDefault] =
    125         rb.GetImageNamed(IDR_AURA_TRAY_BG_VERTICAL_BOTTOM).ToImageSkia();
    126 
    127     leading_images_[kImageVertical][kImageTypeOnBlack] =
    128         rb.GetImageNamed(IDR_AURA_TRAY_BG_VERTICAL_TOP_ONBLACK).ToImageSkia();
    129     middle_images_[kImageVertical][kImageTypeOnBlack] =
    130         rb.GetImageNamed(
    131             IDR_AURA_TRAY_BG_VERTICAL_CENTER_ONBLACK).ToImageSkia();
    132     trailing_images_[kImageVertical][kImageTypeOnBlack] =
    133         rb.GetImageNamed(
    134             IDR_AURA_TRAY_BG_VERTICAL_BOTTOM_ONBLACK).ToImageSkia();
    135 
    136     leading_images_[kImageVertical][kImageTypePressed] =
    137         rb.GetImageNamed(IDR_AURA_TRAY_BG_VERTICAL_TOP_PRESSED).ToImageSkia();
    138     middle_images_[kImageVertical][kImageTypePressed] =
    139         rb.GetImageNamed(
    140             IDR_AURA_TRAY_BG_VERTICAL_CENTER_PRESSED).ToImageSkia();
    141     trailing_images_[kImageVertical][kImageTypePressed] =
    142         rb.GetImageNamed(
    143             IDR_AURA_TRAY_BG_VERTICAL_BOTTOM_PRESSED).ToImageSkia();
    144   }
    145 
    146   virtual ~TrayBackground() {}
    147 
    148   SkColor color() { return color_; }
    149   void set_color(SkColor color) { color_ = color; }
    150   void set_alpha(int alpha) { color_ = SkColorSetARGB(alpha, 0, 0, 0); }
    151 
    152  private:
    153   ShelfWidget* GetShelfWidget() const {
    154     return RootWindowController::ForWindow(tray_background_view_->
    155         status_area_widget()->GetNativeWindow())->shelf();
    156   }
    157 
    158   void PaintForAlternateShelf(gfx::Canvas* canvas, views::View* view) const {
    159     int orientation = kImageHorizontal;
    160     ShelfWidget* shelf_widget = GetShelfWidget();
    161     if (shelf_widget &&
    162         !shelf_widget->shelf_layout_manager()->IsHorizontalAlignment())
    163       orientation = kImageVertical;
    164 
    165     int state = kImageTypeDefault;
    166     if (tray_background_view_->IsPressed())
    167       state = kImageTypePressed;
    168     else if (shelf_widget && shelf_widget->GetDimsShelf())
    169       state = kImageTypeOnBlack;
    170     else
    171       state = kImageTypeDefault;
    172 
    173     const gfx::ImageSkia* leading = leading_images_[orientation][state];
    174     const gfx::ImageSkia* middle = middle_images_[orientation][state];
    175     const gfx::ImageSkia* trailing = trailing_images_[orientation][state];
    176 
    177     gfx::Rect bounds(view->GetLocalBounds());
    178     gfx::Point leading_location, trailing_location;
    179     gfx::Rect middle_bounds;
    180 
    181     if (orientation == kImageHorizontal) {
    182       leading_location = gfx::Point(0, 0);
    183       trailing_location = gfx::Point(bounds.width() - trailing->width(), 0);
    184       middle_bounds = gfx::Rect(
    185           leading->width(),
    186           0,
    187           bounds.width() - (leading->width() + trailing->width()),
    188           bounds.height());
    189     } else {
    190       leading_location = gfx::Point(0, 0);
    191       trailing_location = gfx::Point(0, bounds.height() - trailing->height());
    192       middle_bounds = gfx::Rect(
    193           0,
    194           leading->height(),
    195           bounds.width(),
    196           bounds.height() - (leading->height() + trailing->height()));
    197     }
    198 
    199     canvas->DrawImageInt(*leading,
    200                          leading_location.x(),
    201                          leading_location.y());
    202 
    203     canvas->DrawImageInt(*trailing,
    204                          trailing_location.x(),
    205                          trailing_location.y());
    206 
    207     canvas->TileImageInt(*middle,
    208                          middle_bounds.x(),
    209                          middle_bounds.y(),
    210                          middle_bounds.width(),
    211                          middle_bounds.height());
    212   }
    213 
    214   // Overridden from views::Background.
    215   virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE {
    216     if (ash::switches::UseAlternateShelfLayout()) {
    217       PaintForAlternateShelf(canvas, view);
    218     } else {
    219       SkPaint paint;
    220       paint.setAntiAlias(true);
    221       paint.setStyle(SkPaint::kFill_Style);
    222       paint.setColor(color_);
    223       SkPath path;
    224       gfx::Rect bounds(view->GetLocalBounds());
    225       SkScalar radius = SkIntToScalar(kTrayRoundedBorderRadius);
    226       path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius);
    227       canvas->DrawPath(path, paint);
    228     }
    229   }
    230 
    231   SkColor color_;
    232   // Reference to the TrayBackgroundView for which this is a background.
    233   TrayBackgroundView* tray_background_view_;
    234 
    235   // References to the images used as backgrounds, they are owned by the
    236   // resource bundle class.
    237   const gfx::ImageSkia* leading_images_[kNumOrientations][kNumStates];
    238   const gfx::ImageSkia* middle_images_[kNumOrientations][kNumStates];
    239   const gfx::ImageSkia* trailing_images_[kNumOrientations][kNumStates];
    240 
    241   DISALLOW_COPY_AND_ASSIGN(TrayBackground);
    242 };
    243 
    244 TrayBackgroundView::TrayContainer::TrayContainer(ShelfAlignment alignment)
    245     : alignment_(alignment) {
    246   UpdateLayout();
    247 }
    248 
    249 void TrayBackgroundView::TrayContainer::SetAlignment(ShelfAlignment alignment) {
    250   if (alignment_ == alignment)
    251     return;
    252   alignment_ = alignment;
    253   UpdateLayout();
    254 }
    255 
    256 gfx::Size TrayBackgroundView::TrayContainer::GetPreferredSize() {
    257   if (size_.IsEmpty())
    258     return views::View::GetPreferredSize();
    259   return size_;
    260 }
    261 
    262 void TrayBackgroundView::TrayContainer::ChildPreferredSizeChanged(
    263     views::View* child) {
    264   PreferredSizeChanged();
    265 }
    266 
    267 void TrayBackgroundView::TrayContainer::ChildVisibilityChanged(View* child) {
    268   PreferredSizeChanged();
    269 }
    270 
    271 void TrayBackgroundView::TrayContainer::ViewHierarchyChanged(
    272     const ViewHierarchyChangedDetails& details) {
    273   if (details.parent == this)
    274     PreferredSizeChanged();
    275 }
    276 
    277 void TrayBackgroundView::TrayContainer::UpdateLayout() {
    278   // Adjust the size of status tray dark background by adding additional
    279   // empty border.
    280   if (alignment_ == SHELF_ALIGNMENT_BOTTOM ||
    281       alignment_ == SHELF_ALIGNMENT_TOP) {
    282     int vertical_padding = kTrayContainerVerticalPaddingBottomAlignment;
    283     int horizontal_padding = kTrayContainerHorizontalPaddingBottomAlignment;
    284     if (ash::switches::UseAlternateShelfLayout()) {
    285       vertical_padding = kPaddingFromEdgeOfShelf;
    286       horizontal_padding = kPaddingFromEdgeOfShelf;
    287     }
    288     set_border(views::Border::CreateEmptyBorder(
    289         vertical_padding,
    290         horizontal_padding,
    291         vertical_padding,
    292         horizontal_padding));
    293 
    294     views::BoxLayout* layout =
    295         new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
    296     layout->set_spread_blank_space(true);
    297     views::View::SetLayoutManager(layout);
    298   } else {
    299     int vertical_padding = kTrayContainerVerticalPaddingVerticalAlignment;
    300     int horizontal_padding = kTrayContainerHorizontalPaddingVerticalAlignment;
    301     if (ash::switches::UseAlternateShelfLayout()) {
    302       vertical_padding = kPaddingFromEdgeOfShelf;
    303       horizontal_padding = kPaddingFromEdgeOfShelf;
    304     }
    305     set_border(views::Border::CreateEmptyBorder(
    306         vertical_padding,
    307         horizontal_padding,
    308         vertical_padding,
    309         horizontal_padding));
    310 
    311     views::BoxLayout* layout =
    312         new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
    313     layout->set_spread_blank_space(true);
    314     views::View::SetLayoutManager(layout);
    315   }
    316   PreferredSizeChanged();
    317 }
    318 
    319 ////////////////////////////////////////////////////////////////////////////////
    320 // TrayBackgroundView
    321 
    322 TrayBackgroundView::TrayBackgroundView(
    323     internal::StatusAreaWidget* status_area_widget)
    324     : status_area_widget_(status_area_widget),
    325       tray_container_(NULL),
    326       shelf_alignment_(SHELF_ALIGNMENT_BOTTOM),
    327       background_(NULL),
    328       hide_background_animator_(this, 0, kTrayBackgroundAlpha),
    329       hover_background_animator_(
    330           this, 0, kTrayBackgroundHoverAlpha - kTrayBackgroundAlpha),
    331       hovered_(false),
    332       pressed_(false),
    333       widget_observer_(new TrayWidgetObserver(this)) {
    334   set_notify_enter_exit_on_child(true);
    335 
    336   // Initially we want to paint the background, but without the hover effect.
    337   SetPaintsBackground(true, internal::BackgroundAnimator::CHANGE_IMMEDIATE);
    338   hover_background_animator_.SetPaintsBackground(false,
    339       internal::BackgroundAnimator::CHANGE_IMMEDIATE);
    340 
    341   tray_container_ = new TrayContainer(shelf_alignment_);
    342   SetContents(tray_container_);
    343   tray_event_filter_.reset(new TrayEventFilter);
    344 }
    345 
    346 TrayBackgroundView::~TrayBackgroundView() {
    347   if (GetWidget())
    348     GetWidget()->RemoveObserver(widget_observer_.get());
    349 }
    350 
    351 void TrayBackgroundView::Initialize() {
    352   GetWidget()->AddObserver(widget_observer_.get());
    353   SetBorder();
    354 }
    355 
    356 const char* TrayBackgroundView::GetClassName() const {
    357   return kViewClassName;
    358 }
    359 
    360 void TrayBackgroundView::OnMouseEntered(const ui::MouseEvent& event) {
    361   hovered_ = true;
    362   if (!background_)
    363     return;
    364   if (pressed_)
    365     return;
    366 
    367   hover_background_animator_.SetPaintsBackground(true,
    368       internal::BackgroundAnimator::CHANGE_ANIMATE);
    369 }
    370 
    371 void TrayBackgroundView::OnMouseExited(const ui::MouseEvent& event) {
    372   hovered_ = false;
    373   if (!background_)
    374     return;
    375   if (pressed_)
    376     return;
    377 
    378   hover_background_animator_.SetPaintsBackground(false,
    379       internal::BackgroundAnimator::CHANGE_ANIMATE);
    380 }
    381 
    382 void TrayBackgroundView::ChildPreferredSizeChanged(views::View* child) {
    383   PreferredSizeChanged();
    384 }
    385 
    386 void TrayBackgroundView::OnPaintFocusBorder(gfx::Canvas* canvas) {
    387   // The tray itself expands to the right and bottom edge of the screen to make
    388   // sure clicking on the edges brings up the popup. However, the focus border
    389   // should be only around the container.
    390   if (HasFocus() && (focusable() || IsAccessibilityFocusable()))
    391     DrawBorder(canvas, GetContentsBounds());
    392 }
    393 
    394 void TrayBackgroundView::GetAccessibleState(ui::AccessibleViewState* state) {
    395   state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
    396   state->name = GetAccessibleNameForTray();
    397 }
    398 
    399 void TrayBackgroundView::AboutToRequestFocusFromTabTraversal(bool reverse) {
    400   // Return focus to the login view. See crbug.com/120500.
    401   views::View* v = GetNextFocusableView();
    402   if (v)
    403     v->AboutToRequestFocusFromTabTraversal(reverse);
    404 }
    405 
    406 bool TrayBackgroundView::PerformAction(const ui::Event& event) {
    407   return false;
    408 }
    409 
    410 void TrayBackgroundView::UpdateBackground(int alpha) {
    411   if (!background_)
    412     return;
    413   if (pressed_)
    414     return;
    415 
    416   background_->set_alpha(hide_background_animator_.alpha() +
    417                          hover_background_animator_.alpha());
    418   SchedulePaint();
    419 }
    420 
    421 void TrayBackgroundView::SetContents(views::View* contents) {
    422   SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
    423   AddChildView(contents);
    424 }
    425 
    426 void TrayBackgroundView::SetPaintsBackground(
    427     bool value,
    428     internal::BackgroundAnimator::ChangeType change_type) {
    429   hide_background_animator_.SetPaintsBackground(value, change_type);
    430 }
    431 
    432 void TrayBackgroundView::SetContentsBackground() {
    433   background_ = new internal::TrayBackground(this);
    434   tray_container_->set_background(background_);
    435 }
    436 
    437 ShelfLayoutManager* TrayBackgroundView::GetShelfLayoutManager() {
    438   return ShelfLayoutManager::ForLauncher(GetWidget()->GetNativeView());
    439 }
    440 
    441 void TrayBackgroundView::SetShelfAlignment(ShelfAlignment alignment) {
    442   shelf_alignment_ = alignment;
    443   SetBorder();
    444   tray_container_->SetAlignment(alignment);
    445 }
    446 
    447 void TrayBackgroundView::SetBorder() {
    448   views::View* parent = status_area_widget_->status_area_widget_delegate();
    449 
    450   if (ash::switches::UseAlternateShelfLayout()) {
    451     set_border(views::Border::CreateEmptyBorder(
    452         0,
    453         0,
    454         ShelfLayoutManager::kAutoHideSize,
    455         0));
    456   } else {
    457     // Tray views are laid out right-to-left or bottom-to-top
    458     int on_edge = (this == parent->child_at(0));
    459     // Change the border padding for different shelf alignment.
    460     if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
    461       set_border(views::Border::CreateEmptyBorder(
    462           0, 0,
    463           on_edge ? kPaddingFromBottomOfScreenBottomAlignment :
    464                     kPaddingFromBottomOfScreenBottomAlignment - 1,
    465           on_edge ? kPaddingFromRightEdgeOfScreenBottomAlignment : 0));
    466     } else if (shelf_alignment() == SHELF_ALIGNMENT_TOP) {
    467       set_border(views::Border::CreateEmptyBorder(
    468           on_edge ? kPaddingFromBottomOfScreenBottomAlignment :
    469                     kPaddingFromBottomOfScreenBottomAlignment - 1,
    470           0, 0,
    471           on_edge ? kPaddingFromRightEdgeOfScreenBottomAlignment : 0));
    472     } else if (shelf_alignment() == SHELF_ALIGNMENT_LEFT) {
    473       set_border(views::Border::CreateEmptyBorder(
    474           0, kPaddingFromOuterEdgeOfLauncherVerticalAlignment,
    475           on_edge ? kPaddingFromBottomOfScreenVerticalAlignment : 0,
    476           kPaddingFromInnerEdgeOfLauncherVerticalAlignment));
    477     } else {
    478       set_border(views::Border::CreateEmptyBorder(
    479           0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
    480           on_edge ? kPaddingFromBottomOfScreenVerticalAlignment : 0,
    481           kPaddingFromOuterEdgeOfLauncherVerticalAlignment));
    482     }
    483   }
    484 }
    485 
    486 void TrayBackgroundView::InitializeBubbleAnimations(
    487     views::Widget* bubble_widget) {
    488   views::corewm::SetWindowVisibilityAnimationType(
    489       bubble_widget->GetNativeWindow(),
    490       views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
    491   views::corewm::SetWindowVisibilityAnimationTransition(
    492       bubble_widget->GetNativeWindow(),
    493       views::corewm::ANIMATE_HIDE);
    494   views::corewm::SetWindowVisibilityAnimationDuration(
    495       bubble_widget->GetNativeWindow(),
    496       base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS));
    497 }
    498 
    499 bool TrayBackgroundView::IsPressed() {
    500   return pressed_;
    501 }
    502 
    503 aura::Window* TrayBackgroundView::GetBubbleWindowContainer() const {
    504   return ash::Shell::GetContainer(
    505       tray_container()->GetWidget()->GetNativeWindow()->GetRootWindow(),
    506       ash::internal::kShellWindowId_SettingBubbleContainer);
    507 }
    508 
    509 gfx::Rect TrayBackgroundView::GetBubbleAnchorRect(
    510     views::Widget* anchor_widget,
    511     TrayBubbleView::AnchorType anchor_type,
    512     TrayBubbleView::AnchorAlignment anchor_alignment) const {
    513   gfx::Rect rect;
    514   if (anchor_widget && anchor_widget->IsVisible()) {
    515     rect = anchor_widget->GetWindowBoundsInScreen();
    516     if (anchor_type == TrayBubbleView::ANCHOR_TYPE_TRAY) {
    517       if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) {
    518         bool rtl = base::i18n::IsRTL();
    519         rect.Inset(
    520             rtl ? kPaddingFromRightEdgeOfScreenBottomAlignment : 0,
    521             kTrayBubbleAnchorTopInsetBottomAnchor,
    522             rtl ? 0 : kPaddingFromRightEdgeOfScreenBottomAlignment,
    523             kPaddingFromBottomOfScreenBottomAlignment);
    524       } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) {
    525         rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment + 5,
    526                    kPaddingFromBottomOfScreenVerticalAlignment);
    527       } else {
    528         rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment + 1,
    529                    0, 0, kPaddingFromBottomOfScreenVerticalAlignment);
    530       }
    531     } else if (anchor_type == TrayBubbleView::ANCHOR_TYPE_BUBBLE) {
    532       // Invert the offsets to align with the bubble below.
    533       // Note that with the alternate shelf layout the tips are not shown and
    534       // the offsets for left and right alignment do not need to be applied.
    535       int vertical_alignment = ash::switches::UseAlternateShelfLayout() ?
    536           0 : kPaddingFromInnerEdgeOfLauncherVerticalAlignment;
    537       if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) {
    538         rect.Inset(vertical_alignment,
    539                    0, 0, kPaddingFromBottomOfScreenVerticalAlignment);
    540       } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) {
    541         rect.Inset(0, 0, vertical_alignment,
    542                    kPaddingFromBottomOfScreenVerticalAlignment);
    543       }
    544     }
    545   }
    546 
    547   // TODO(jennyz): May need to add left/right alignment in the following code.
    548   if (rect.IsEmpty()) {
    549     aura::RootWindow* target_root = anchor_widget ?
    550         anchor_widget->GetNativeView()->GetRootWindow() :
    551         Shell::GetPrimaryRootWindow();
    552     rect = target_root->bounds();
    553     rect = gfx::Rect(
    554         base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment :
    555         rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment,
    556         rect.height() - kPaddingFromBottomOfScreenBottomAlignment,
    557         0, 0);
    558     rect = ScreenAsh::ConvertRectToScreen(target_root, rect);
    559   }
    560   return rect;
    561 }
    562 
    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;
    573   }
    574   NOTREACHED();
    575   return TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM;
    576 }
    577 
    578 void TrayBackgroundView::SetBubbleVisible(bool visible) {
    579   pressed_ = visible;
    580   if (!background_)
    581     return;
    582 
    583   // Do not change gradually, changing color between grey and blue is weird.
    584   if (pressed_)
    585     background_->set_color(kTrayBackgroundPressedColor);
    586   else if (hovered_)
    587     background_->set_alpha(kTrayBackgroundHoverAlpha);
    588   else
    589     background_->set_alpha(kTrayBackgroundAlpha);
    590   SchedulePaint();
    591 }
    592 
    593 void TrayBackgroundView::UpdateBubbleViewArrow(
    594     views::TrayBubbleView* bubble_view) {
    595   if (switches::UseAlternateShelfLayout())
    596     return;
    597 
    598   aura::RootWindow* root_window =
    599       bubble_view->GetWidget()->GetNativeView()->GetRootWindow();
    600   ash::internal::ShelfLayoutManager* shelf =
    601       ShelfLayoutManager::ForLauncher(root_window);
    602   bubble_view->SetArrowPaintType(
    603       shelf->IsVisible() ? views::BubbleBorder::PAINT_NORMAL :
    604                            views::BubbleBorder::PAINT_TRANSPARENT);
    605 }
    606 
    607 }  // namespace internal
    608 }  // namespace ash
    609