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