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