Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(560)

Side by Side Diff: ash/common/system/tray/tray_background_view.cc

Issue 2095663004: Revert of mash: Convert TrayBackgroundView to wm common types (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW
« no previous file with comments | « ash/common/system/tray/tray_background_view.h ('k') | ash/common/system/tray/tray_bubble_wrapper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698