OLD | NEW |
(Empty) | |
| 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/common/material_design/material_design_controller.h" |
| 8 #include "ash/common/shelf/shelf_constants.h" |
| 9 #include "ash/common/shelf/wm_shelf.h" |
| 10 #include "ash/common/shelf/wm_shelf_util.h" |
| 11 #include "ash/common/shell_window_ids.h" |
| 12 #include "ash/common/system/tray/tray_constants.h" |
| 13 #include "ash/screen_util.h" |
| 14 #include "ash/shell.h" |
| 15 #include "ash/system/status_area_widget.h" |
| 16 #include "ash/system/status_area_widget_delegate.h" |
| 17 #include "ash/system/tray/system_tray.h" |
| 18 #include "ash/system/tray/tray_event_filter.h" |
| 19 #include "ash/wm/window_animations.h" |
| 20 #include "base/command_line.h" |
| 21 #include "grit/ash_resources.h" |
| 22 #include "ui/accessibility/ax_view_state.h" |
| 23 #include "ui/aura/window.h" |
| 24 #include "ui/aura/window_event_dispatcher.h" |
| 25 #include "ui/base/nine_image_painter_factory.h" |
| 26 #include "ui/base/ui_base_switches_util.h" |
| 27 #include "ui/compositor/layer.h" |
| 28 #include "ui/compositor/layer_animation_element.h" |
| 29 #include "ui/compositor/scoped_layer_animation_settings.h" |
| 30 #include "ui/events/event_constants.h" |
| 31 #include "ui/gfx/animation/tween.h" |
| 32 #include "ui/gfx/canvas.h" |
| 33 #include "ui/gfx/geometry/rect.h" |
| 34 #include "ui/gfx/image/image_skia.h" |
| 35 #include "ui/gfx/image/image_skia_operations.h" |
| 36 #include "ui/gfx/nine_image_painter.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" |
| 41 #include "ui/wm/core/window_animations.h" |
| 42 |
| 43 namespace { |
| 44 |
| 45 const int kAnimationDurationForPopupMs = 200; |
| 46 |
| 47 // Duration of opacity animation for visibility changes. |
| 48 const int kAnimationDurationForVisibilityMs = 250; |
| 49 |
| 50 // When becoming visible delay the animation so that StatusAreaWidgetDelegate |
| 51 // can animate sibling views out of the position to be occuped by the |
| 52 // TrayBackgroundView. |
| 53 const int kShowAnimationDelayMs = 100; |
| 54 |
| 55 } // namespace |
| 56 |
| 57 using views::TrayBubbleView; |
| 58 |
| 59 namespace ash { |
| 60 |
| 61 // static |
| 62 const char TrayBackgroundView::kViewClassName[] = "tray/TrayBackgroundView"; |
| 63 |
| 64 // Used to track when the anchor widget changes position on screen so that the |
| 65 // bubble position can be updated. |
| 66 class TrayBackgroundView::TrayWidgetObserver : public views::WidgetObserver { |
| 67 public: |
| 68 explicit TrayWidgetObserver(TrayBackgroundView* host) |
| 69 : host_(host) { |
| 70 } |
| 71 |
| 72 void OnWidgetBoundsChanged(views::Widget* widget, |
| 73 const gfx::Rect& new_bounds) override { |
| 74 host_->AnchorUpdated(); |
| 75 } |
| 76 |
| 77 void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override { |
| 78 host_->AnchorUpdated(); |
| 79 } |
| 80 |
| 81 private: |
| 82 TrayBackgroundView* host_; |
| 83 |
| 84 DISALLOW_COPY_AND_ASSIGN(TrayWidgetObserver); |
| 85 }; |
| 86 |
| 87 class TrayBackground : public views::Background { |
| 88 public: |
| 89 const static int kImageTypeDefault = 0; |
| 90 const static int kImageTypeOnBlack = 1; |
| 91 const static int kImageTypePressed = 2; |
| 92 const static int kNumStates = 3; |
| 93 |
| 94 const static int kImageHorizontal = 0; |
| 95 const static int kImageVertical = 1; |
| 96 const static int kNumOrientations = 2; |
| 97 |
| 98 explicit TrayBackground(TrayBackgroundView* tray_background_view) : |
| 99 tray_background_view_(tray_background_view) { |
| 100 } |
| 101 |
| 102 ~TrayBackground() override {} |
| 103 |
| 104 private: |
| 105 WmShelf* GetShelf() const { |
| 106 return tray_background_view_->GetShelf(); |
| 107 } |
| 108 |
| 109 void PaintMaterial(gfx::Canvas* canvas, views::View* view) const { |
| 110 SkColor background_color = SK_ColorTRANSPARENT; |
| 111 if (GetShelf()->GetBackgroundType() == |
| 112 ShelfBackgroundType::SHELF_BACKGROUND_DEFAULT) { |
| 113 background_color = SkColorSetA(kShelfBaseColor, |
| 114 GetShelfConstant(SHELF_BACKGROUND_ALPHA)); |
| 115 } |
| 116 |
| 117 // TODO(bruthig|tdanderson): The background should be changed using a |
| 118 // fade in/out animation. |
| 119 const int kCornerRadius = 2; |
| 120 |
| 121 SkPaint background_paint; |
| 122 background_paint.setFlags(SkPaint::kAntiAlias_Flag); |
| 123 background_paint.setColor(background_color); |
| 124 canvas->DrawRoundRect(view->GetLocalBounds(), kCornerRadius, |
| 125 background_paint); |
| 126 |
| 127 if (tray_background_view_->draw_background_as_active()) { |
| 128 SkPaint highlight_paint; |
| 129 highlight_paint.setFlags(SkPaint::kAntiAlias_Flag); |
| 130 highlight_paint.setColor(kShelfButtonActivatedHighlightColor); |
| 131 canvas->DrawRoundRect(view->GetLocalBounds(), kCornerRadius, |
| 132 highlight_paint); |
| 133 } |
| 134 } |
| 135 |
| 136 void PaintNonMaterial(gfx::Canvas* canvas, views::View* view) const { |
| 137 const int kGridSizeForPainter = 9; |
| 138 const int kImages[kNumOrientations][kNumStates][kGridSizeForPainter] = { |
| 139 { // Horizontal |
| 140 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ), |
| 141 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ_ONBLACK), |
| 142 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ_PRESSED), |
| 143 }, |
| 144 { // Vertical |
| 145 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL), |
| 146 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL_ONBLACK), |
| 147 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL_PRESSED), |
| 148 } |
| 149 }; |
| 150 |
| 151 WmShelf* shelf = GetShelf(); |
| 152 const int orientation = IsHorizontalAlignment(shelf->GetAlignment()) |
| 153 ? kImageHorizontal |
| 154 : kImageVertical; |
| 155 |
| 156 int state = kImageTypeDefault; |
| 157 if (tray_background_view_->draw_background_as_active()) |
| 158 state = kImageTypePressed; |
| 159 else if (shelf->IsDimmed()) |
| 160 state = kImageTypeOnBlack; |
| 161 else |
| 162 state = kImageTypeDefault; |
| 163 |
| 164 ui::CreateNineImagePainter(kImages[orientation][state]) |
| 165 ->Paint(canvas, view->GetLocalBounds()); |
| 166 } |
| 167 |
| 168 // Overridden from views::Background. |
| 169 void Paint(gfx::Canvas* canvas, views::View* view) const override { |
| 170 if (MaterialDesignController::IsShelfMaterial()) |
| 171 PaintMaterial(canvas, view); |
| 172 else |
| 173 PaintNonMaterial(canvas, view); |
| 174 } |
| 175 |
| 176 // Reference to the TrayBackgroundView for which this is a background. |
| 177 TrayBackgroundView* tray_background_view_; |
| 178 |
| 179 DISALLOW_COPY_AND_ASSIGN(TrayBackground); |
| 180 }; |
| 181 |
| 182 TrayBackgroundView::TrayContainer::TrayContainer(ShelfAlignment alignment) |
| 183 : alignment_(alignment) { |
| 184 UpdateLayout(); |
| 185 } |
| 186 |
| 187 void TrayBackgroundView::TrayContainer::SetAlignment(ShelfAlignment alignment) { |
| 188 if (alignment_ == alignment) |
| 189 return; |
| 190 alignment_ = alignment; |
| 191 UpdateLayout(); |
| 192 } |
| 193 |
| 194 gfx::Size TrayBackgroundView::TrayContainer::GetPreferredSize() const { |
| 195 if (size_.IsEmpty()) |
| 196 return views::View::GetPreferredSize(); |
| 197 return size_; |
| 198 } |
| 199 |
| 200 void TrayBackgroundView::TrayContainer::ChildPreferredSizeChanged( |
| 201 views::View* child) { |
| 202 PreferredSizeChanged(); |
| 203 } |
| 204 |
| 205 void TrayBackgroundView::TrayContainer::ChildVisibilityChanged(View* child) { |
| 206 PreferredSizeChanged(); |
| 207 } |
| 208 |
| 209 void TrayBackgroundView::TrayContainer::ViewHierarchyChanged( |
| 210 const ViewHierarchyChangedDetails& details) { |
| 211 if (details.parent == this) |
| 212 PreferredSizeChanged(); |
| 213 } |
| 214 |
| 215 // TODO(tdanderson): Adjust TrayContainer borders according to the material |
| 216 // design specs. See crbug.com/617295. |
| 217 void TrayBackgroundView::TrayContainer::UpdateLayout() { |
| 218 // Adjust the size of status tray dark background by adding additional |
| 219 // empty border. |
| 220 views::BoxLayout::Orientation orientation = |
| 221 IsHorizontalAlignment(alignment_) ? views::BoxLayout::kHorizontal |
| 222 : views::BoxLayout::kVertical; |
| 223 SetBorder(views::Border::CreateEmptyBorder( |
| 224 kAdjustBackgroundPadding, kAdjustBackgroundPadding, |
| 225 kAdjustBackgroundPadding, kAdjustBackgroundPadding)); |
| 226 |
| 227 views::BoxLayout* layout = new views::BoxLayout(orientation, 0, 0, 0); |
| 228 layout->SetDefaultFlex(1); |
| 229 views::View::SetLayoutManager(layout); |
| 230 PreferredSizeChanged(); |
| 231 } |
| 232 |
| 233 //////////////////////////////////////////////////////////////////////////////// |
| 234 // TrayBackgroundView |
| 235 |
| 236 TrayBackgroundView::TrayBackgroundView(StatusAreaWidget* status_area_widget) |
| 237 : status_area_widget_(status_area_widget), |
| 238 tray_container_(NULL), |
| 239 shelf_alignment_(SHELF_ALIGNMENT_BOTTOM), |
| 240 background_(NULL), |
| 241 draw_background_as_active_(false), |
| 242 widget_observer_(new TrayWidgetObserver(this)) { |
| 243 DCHECK(status_area_widget->wm_shelf()); |
| 244 set_notify_enter_exit_on_child(true); |
| 245 |
| 246 tray_container_ = new TrayContainer(shelf_alignment_); |
| 247 SetContents(tray_container_); |
| 248 tray_event_filter_.reset(new TrayEventFilter); |
| 249 |
| 250 SetPaintToLayer(true); |
| 251 layer()->SetFillsBoundsOpaquely(false); |
| 252 // Start the tray items not visible, because visibility changes are animated. |
| 253 views::View::SetVisible(false); |
| 254 } |
| 255 |
| 256 TrayBackgroundView::~TrayBackgroundView() { |
| 257 if (GetWidget()) |
| 258 GetWidget()->RemoveObserver(widget_observer_.get()); |
| 259 StopObservingImplicitAnimations(); |
| 260 } |
| 261 |
| 262 void TrayBackgroundView::Initialize() { |
| 263 GetWidget()->AddObserver(widget_observer_.get()); |
| 264 } |
| 265 |
| 266 // static |
| 267 void TrayBackgroundView::InitializeBubbleAnimations( |
| 268 views::Widget* bubble_widget) { |
| 269 aura::Window* window = bubble_widget->GetNativeWindow(); |
| 270 ::wm::SetWindowVisibilityAnimationType( |
| 271 window, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); |
| 272 ::wm::SetWindowVisibilityAnimationTransition(window, ::wm::ANIMATE_HIDE); |
| 273 ::wm::SetWindowVisibilityAnimationDuration( |
| 274 window, base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMs)); |
| 275 } |
| 276 |
| 277 void TrayBackgroundView::SetVisible(bool visible) { |
| 278 if (visible == layer()->GetTargetVisibility()) |
| 279 return; |
| 280 |
| 281 if (visible) { |
| 282 // The alignment of the shelf can change while the TrayBackgroundView is |
| 283 // hidden. Reset the offscreen transform so that the animation to becoming |
| 284 // visible reflects the current layout. |
| 285 HideTransformation(); |
| 286 // SetVisible(false) is defered until the animation for hiding is done. |
| 287 // Otherwise the view is immediately hidden and the animation does not |
| 288 // render. |
| 289 views::View::SetVisible(true); |
| 290 // If SetVisible(true) is called while animating to not visible, then |
| 291 // views::View::SetVisible(true) is a no-op. When the previous animation |
| 292 // ends layer->SetVisible(false) is called. To prevent this |
| 293 // layer->SetVisible(true) immediately interrupts the animation of this |
| 294 // property, and keeps the layer visible. |
| 295 layer()->SetVisible(true); |
| 296 } |
| 297 |
| 298 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); |
| 299 animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |
| 300 kAnimationDurationForVisibilityMs)); |
| 301 animation.SetPreemptionStrategy( |
| 302 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 303 |
| 304 if (visible) { |
| 305 animation.SetTweenType(gfx::Tween::EASE_OUT); |
| 306 // Show is delayed so as to allow time for other children of |
| 307 // StatusAreaWidget to begin animating to their new positions. |
| 308 layer()->GetAnimator()->SchedulePauseForProperties( |
| 309 base::TimeDelta::FromMilliseconds(kShowAnimationDelayMs), |
| 310 ui::LayerAnimationElement::OPACITY | |
| 311 ui::LayerAnimationElement::TRANSFORM); |
| 312 layer()->SetOpacity(1.0f); |
| 313 gfx::Transform transform; |
| 314 transform.Translate(0.0f, 0.0f); |
| 315 layer()->SetTransform(transform); |
| 316 } else { |
| 317 // Listen only to the hide animation. As we cannot turn off visibility |
| 318 // until the animation is over. |
| 319 animation.AddObserver(this); |
| 320 animation.SetTweenType(gfx::Tween::EASE_IN); |
| 321 layer()->SetOpacity(0.0f); |
| 322 layer()->SetVisible(false); |
| 323 HideTransformation(); |
| 324 } |
| 325 } |
| 326 |
| 327 const char* TrayBackgroundView::GetClassName() const { |
| 328 return kViewClassName; |
| 329 } |
| 330 |
| 331 void TrayBackgroundView::ChildPreferredSizeChanged(views::View* child) { |
| 332 PreferredSizeChanged(); |
| 333 } |
| 334 |
| 335 void TrayBackgroundView::GetAccessibleState(ui::AXViewState* state) { |
| 336 ActionableView::GetAccessibleState(state); |
| 337 state->name = GetAccessibleNameForTray(); |
| 338 } |
| 339 |
| 340 void TrayBackgroundView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
| 341 // Return focus to the login view. See crbug.com/120500. |
| 342 views::View* v = GetNextFocusableView(); |
| 343 if (v) |
| 344 v->AboutToRequestFocusFromTabTraversal(reverse); |
| 345 } |
| 346 |
| 347 bool TrayBackgroundView::PerformAction(const ui::Event& event) { |
| 348 return false; |
| 349 } |
| 350 |
| 351 gfx::Rect TrayBackgroundView::GetFocusBounds() { |
| 352 // The tray itself expands to the right and bottom edge of the screen to make |
| 353 // sure clicking on the edges brings up the popup. However, the focus border |
| 354 // should be only around the container. |
| 355 return GetContentsBounds(); |
| 356 } |
| 357 |
| 358 void TrayBackgroundView::OnGestureEvent(ui::GestureEvent* event) { |
| 359 if (switches::IsTouchFeedbackEnabled()) { |
| 360 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { |
| 361 SetDrawBackgroundAsActive(true); |
| 362 } else if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || |
| 363 event->type() == ui::ET_GESTURE_TAP_CANCEL) { |
| 364 SetDrawBackgroundAsActive(false); |
| 365 } |
| 366 } |
| 367 ActionableView::OnGestureEvent(event); |
| 368 } |
| 369 |
| 370 void TrayBackgroundView::UpdateBackground(int alpha) { |
| 371 // The animator should never fire when the alternate shelf layout is used. |
| 372 if (!background_ || draw_background_as_active_) |
| 373 return; |
| 374 SchedulePaint(); |
| 375 } |
| 376 |
| 377 void TrayBackgroundView::SetContents(views::View* contents) { |
| 378 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); |
| 379 AddChildView(contents); |
| 380 } |
| 381 void TrayBackgroundView::SetContentsBackground() { |
| 382 background_ = new TrayBackground(this); |
| 383 tray_container_->set_background(background_); |
| 384 } |
| 385 |
| 386 WmShelf* TrayBackgroundView::GetShelf() { |
| 387 return status_area_widget_->wm_shelf(); |
| 388 } |
| 389 |
| 390 void TrayBackgroundView::SetShelfAlignment(ShelfAlignment alignment) { |
| 391 shelf_alignment_ = alignment; |
| 392 tray_container_->SetAlignment(alignment); |
| 393 } |
| 394 |
| 395 void TrayBackgroundView::OnImplicitAnimationsCompleted() { |
| 396 // If there is another animation in the queue, the reverse animation was |
| 397 // triggered before the completion of animating to invisible. Do not turn off |
| 398 // the visibility so that the next animation may render. The value of |
| 399 // layer()->GetTargetVisibility() can be incorrect if the hide animation was |
| 400 // aborted to schedule an animation to become visible. As the new animation |
| 401 // is not yet added to the queue. crbug.com/374236 |
| 402 if(layer()->GetAnimator()->is_animating() || |
| 403 layer()->GetTargetVisibility()) |
| 404 return; |
| 405 views::View::SetVisible(false); |
| 406 } |
| 407 |
| 408 bool TrayBackgroundView::RequiresNotificationWhenAnimatorDestroyed() const { |
| 409 // This is needed so that OnImplicitAnimationsCompleted() is called even upon |
| 410 // destruction of the animator. This can occure when parallel animations |
| 411 // caused by ScreenRotationAnimator end before the animations of |
| 412 // TrayBackgroundView. This allows for a proper update to the visual state of |
| 413 // the view. (crbug.com/476667) |
| 414 return true; |
| 415 } |
| 416 |
| 417 void TrayBackgroundView::HideTransformation() { |
| 418 gfx::Transform transform; |
| 419 if (IsHorizontalAlignment(shelf_alignment_)) |
| 420 transform.Translate(width(), 0.0f); |
| 421 else |
| 422 transform.Translate(0.0f, height()); |
| 423 layer()->SetTransform(transform); |
| 424 } |
| 425 |
| 426 gfx::Rect TrayBackgroundView::GetBubbleAnchorRect( |
| 427 views::Widget* anchor_widget, |
| 428 TrayBubbleView::AnchorType anchor_type, |
| 429 TrayBubbleView::AnchorAlignment anchor_alignment) const { |
| 430 gfx::Rect rect; |
| 431 if (anchor_widget && anchor_widget->IsVisible()) { |
| 432 rect = anchor_widget->GetWindowBoundsInScreen(); |
| 433 if (anchor_type == TrayBubbleView::ANCHOR_TYPE_TRAY) { |
| 434 if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) { |
| 435 bool rtl = base::i18n::IsRTL(); |
| 436 rect.Inset( |
| 437 rtl ? kBubblePaddingHorizontalSide : 0, |
| 438 kBubblePaddingHorizontalBottom, |
| 439 rtl ? 0 : kBubblePaddingHorizontalSide, |
| 440 0); |
| 441 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) { |
| 442 rect.Inset(0, 0, kBubblePaddingVerticalSide + 4, |
| 443 kBubblePaddingVerticalBottom); |
| 444 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) { |
| 445 rect.Inset(kBubblePaddingVerticalSide, 0, 0, |
| 446 kBubblePaddingVerticalBottom); |
| 447 } else { |
| 448 // TODO(bruthig) May need to handle other ANCHOR_ALIGNMENT_ values. |
| 449 // ie. ANCHOR_ALIGNMENT_TOP |
| 450 DCHECK(false) << "Unhandled anchor alignment."; |
| 451 } |
| 452 } else if (anchor_type == TrayBubbleView::ANCHOR_TYPE_BUBBLE) { |
| 453 // Invert the offsets to align with the bubble below. |
| 454 // Note that with the alternate shelf layout the tips are not shown and |
| 455 // the offsets for left and right alignment do not need to be applied. |
| 456 int vertical_alignment = 0; |
| 457 int horizontal_alignment = kBubblePaddingVerticalBottom; |
| 458 if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) |
| 459 rect.Inset(vertical_alignment, 0, 0, horizontal_alignment); |
| 460 else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) |
| 461 rect.Inset(0, 0, vertical_alignment, horizontal_alignment); |
| 462 } else { |
| 463 DCHECK(false) << "Unhandled anchor type."; |
| 464 } |
| 465 } else { |
| 466 aura::Window* target_root = anchor_widget ? |
| 467 anchor_widget->GetNativeView()->GetRootWindow() : |
| 468 Shell::GetPrimaryRootWindow(); |
| 469 rect = target_root->bounds(); |
| 470 if (anchor_type == TrayBubbleView::ANCHOR_TYPE_TRAY) { |
| 471 if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) { |
| 472 rect = gfx::Rect( |
| 473 base::i18n::IsRTL() ? |
| 474 kPaddingFromRightEdgeOfScreenBottomAlignment : |
| 475 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, |
| 476 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, |
| 477 0, 0); |
| 478 rect = ScreenUtil::ConvertRectToScreen(target_root, rect); |
| 479 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) { |
| 480 rect = gfx::Rect( |
| 481 kPaddingFromRightEdgeOfScreenBottomAlignment, |
| 482 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, |
| 483 1, 1); |
| 484 rect = ScreenUtil::ConvertRectToScreen(target_root, rect); |
| 485 } else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) { |
| 486 rect = gfx::Rect( |
| 487 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, |
| 488 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, |
| 489 1, 1); |
| 490 rect = ScreenUtil::ConvertRectToScreen(target_root, rect); |
| 491 } else { |
| 492 // TODO(bruthig) May need to handle other ANCHOR_ALIGNMENT_ values. |
| 493 // ie. ANCHOR_ALIGNMENT_TOP |
| 494 DCHECK(false) << "Unhandled anchor alignment."; |
| 495 } |
| 496 } else { |
| 497 rect = gfx::Rect( |
| 498 base::i18n::IsRTL() ? |
| 499 kPaddingFromRightEdgeOfScreenBottomAlignment : |
| 500 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, |
| 501 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, |
| 502 0, 0); |
| 503 } |
| 504 } |
| 505 return rect; |
| 506 } |
| 507 |
| 508 TrayBubbleView::AnchorAlignment TrayBackgroundView::GetAnchorAlignment() const { |
| 509 if (shelf_alignment_ == SHELF_ALIGNMENT_LEFT) |
| 510 return TrayBubbleView::ANCHOR_ALIGNMENT_LEFT; |
| 511 if (shelf_alignment_ == SHELF_ALIGNMENT_RIGHT) |
| 512 return TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT; |
| 513 return TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM; |
| 514 } |
| 515 |
| 516 void TrayBackgroundView::SetDrawBackgroundAsActive(bool visible) { |
| 517 if (draw_background_as_active_ == visible) |
| 518 return; |
| 519 draw_background_as_active_ = visible; |
| 520 if (!background_) |
| 521 return; |
| 522 SchedulePaint(); |
| 523 } |
| 524 |
| 525 void TrayBackgroundView::UpdateBubbleViewArrow( |
| 526 views::TrayBubbleView* bubble_view) { |
| 527 // Nothing to do here. |
| 528 } |
| 529 |
| 530 } // namespace ash |
OLD | NEW |