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

Side by Side Diff: ui/arc/notification/arc_custom_notification_view.cc

Issue 2906323002: Rename ArcCustomNotificationView to ArcNotificationContentView (Closed)
Patch Set: Created 3 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 2016 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 "ui/arc/notification/arc_custom_notification_view.h"
6
7 #include "ash/wm/window_util.h"
8 #include "base/auto_reset.h"
9 #include "base/memory/ptr_util.h"
10 #include "components/exo/notification_surface.h"
11 #include "components/exo/surface.h"
12 #include "ui/accessibility/ax_action_data.h"
13 #include "ui/arc/notification/arc_notification_view.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/compositor/layer_animation_observer.h"
17 #include "ui/events/event_handler.h"
18 #include "ui/gfx/animation/linear_animation.h"
19 #include "ui/gfx/animation/tween.h"
20 #include "ui/gfx/canvas.h"
21 #include "ui/gfx/transform.h"
22 #include "ui/message_center/message_center_style.h"
23 #include "ui/message_center/views/toast_contents_view.h"
24 #include "ui/strings/grit/ui_strings.h"
25 #include "ui/views/background.h"
26 #include "ui/views/focus/focus_manager.h"
27 #include "ui/views/layout/box_layout.h"
28 #include "ui/views/painter.h"
29 #include "ui/views/widget/root_view.h"
30 #include "ui/views/widget/widget.h"
31 #include "ui/wm/core/window_util.h"
32
33 namespace arc {
34
35 namespace {
36
37 // This value should be the same as the duration of reveal animation of
38 // the settings view of an Android notification.
39 constexpr int kBackgroundColorChangeDuration = 360;
40
41 SkColor GetControlButtonBackgroundColor(
42 const mojom::ArcNotificationShownContents& shown_contents) {
43 if (shown_contents == mojom::ArcNotificationShownContents::CONTENTS_SHOWN)
44 return message_center::kControlButtonBackgroundColor;
45 else
46 return SK_ColorTRANSPARENT;
47 }
48
49 } // namespace
50
51 class ArcCustomNotificationView::EventForwarder : public ui::EventHandler {
52 public:
53 explicit EventForwarder(ArcCustomNotificationView* owner) : owner_(owner) {}
54 ~EventForwarder() override = default;
55
56 private:
57 // ui::EventHandler
58 void OnEvent(ui::Event* event) override {
59 // Do not forward event targeted to the floating close button so that
60 // keyboard press and tap are handled properly.
61 if (owner_->floating_control_buttons_widget_ && event->target() &&
62 owner_->floating_control_buttons_widget_->GetNativeWindow() ==
63 event->target()) {
64 return;
65 }
66
67 // TODO(yoshiki): Use a better tigger (eg. focusing EditText on
68 // notification) than clicking (crbug.com/697379).
69 if (event->type() == ui::ET_MOUSE_PRESSED)
70 owner_->ActivateToast();
71
72 views::Widget* widget = owner_->GetWidget();
73 if (!widget)
74 return;
75
76 // Forward the events to the containing widget, except for:
77 // 1. Touches, because View should no longer receive touch events.
78 // See View::OnTouchEvent.
79 // 2. Tap gestures are handled on the Android side, so ignore them.
80 // See crbug.com/709911.
81 // 3. Key events. These are already forwarded by NotificationSurface's
82 // WindowDelegate.
83 if (event->IsLocatedEvent()) {
84 ui::LocatedEvent* located_event = event->AsLocatedEvent();
85 located_event->target()->ConvertEventToTarget(widget->GetNativeWindow(),
86 located_event);
87 if (located_event->type() == ui::ET_MOUSE_MOVED ||
88 located_event->IsMouseWheelEvent()) {
89 widget->OnMouseEvent(located_event->AsMouseEvent());
90 } else if (located_event->IsScrollEvent()) {
91 widget->OnScrollEvent(located_event->AsScrollEvent());
92 } else if (located_event->IsGestureEvent() &&
93 event->type() != ui::ET_GESTURE_TAP) {
94 widget->OnGestureEvent(located_event->AsGestureEvent());
95 }
96 }
97 }
98
99 ArcCustomNotificationView* const owner_;
100
101 DISALLOW_COPY_AND_ASSIGN(EventForwarder);
102 };
103
104 class ArcCustomNotificationView::SlideHelper
105 : public ui::LayerAnimationObserver {
106 public:
107 explicit SlideHelper(ArcCustomNotificationView* owner) : owner_(owner) {
108 GetSlideOutLayer()->GetAnimator()->AddObserver(this);
109
110 // Reset opacity to 1 to handle to case when the surface is sliding before
111 // getting managed by this class, e.g. sliding in a popup before showing
112 // in a message center view.
113 if (owner_->surface_ && owner_->surface_->window())
114 owner_->surface_->window()->layer()->SetOpacity(1.0f);
115 }
116 ~SlideHelper() override {
117 if (GetSlideOutLayer())
118 GetSlideOutLayer()->GetAnimator()->RemoveObserver(this);
119 }
120
121 void Update() {
122 const bool has_animation =
123 GetSlideOutLayer()->GetAnimator()->is_animating();
124 const bool has_transform = !GetSlideOutLayer()->transform().IsIdentity();
125 const bool sliding = has_transform || has_animation;
126 if (sliding_ == sliding)
127 return;
128
129 sliding_ = sliding;
130
131 if (sliding_)
132 OnSlideStart();
133 else
134 OnSlideEnd();
135 }
136
137 private:
138 // This is a temporary hack to address crbug.com/718965
139 ui::Layer* GetSlideOutLayer() {
140 ui::Layer* layer = owner_->parent()->layer();
141 return layer ? layer : owner_->GetWidget()->GetLayer();
142 }
143
144 void OnSlideStart() {
145 if (!owner_->surface_ || !owner_->surface_->window())
146 return;
147 surface_copy_ = ::wm::RecreateLayers(owner_->surface_->window());
148 // |surface_copy_| is at (0, 0) in owner_->layer().
149 surface_copy_->root()->SetBounds(gfx::Rect(surface_copy_->root()->size()));
150 owner_->layer()->Add(surface_copy_->root());
151 owner_->surface_->window()->layer()->SetOpacity(0.0f);
152 }
153
154 void OnSlideEnd() {
155 if (!owner_->surface_ || !owner_->surface_->window())
156 return;
157 owner_->surface_->window()->layer()->SetOpacity(1.0f);
158 owner_->Layout();
159 surface_copy_.reset();
160 }
161
162 // ui::LayerAnimationObserver
163 void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq) override {
164 Update();
165 }
166 void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq) override {
167 Update();
168 }
169 void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {}
170
171 ArcCustomNotificationView* const owner_;
172 bool sliding_ = false;
173 std::unique_ptr<ui::LayerTreeOwner> surface_copy_;
174
175 DISALLOW_COPY_AND_ASSIGN(SlideHelper);
176 };
177
178 class ArcCustomNotificationView::ContentViewDelegate
179 : public ArcNotificationContentViewDelegate {
180 public:
181 explicit ContentViewDelegate(ArcCustomNotificationView* owner)
182 : owner_(owner) {}
183
184 bool IsCloseButtonFocused() const override {
185 if (!owner_->close_button_)
186 return false;
187 return owner_->close_button_->HasFocus();
188 }
189
190 void RequestFocusOnCloseButton() override {
191 if (owner_->close_button_)
192 owner_->close_button_->RequestFocus();
193 owner_->UpdateControlButtonsVisibility();
194 }
195
196 void UpdateControlButtonsVisibility() override {
197 owner_->UpdateControlButtonsVisibility();
198 }
199
200 void OnSlideChanged() override {
201 if (owner_->slide_helper_)
202 owner_->slide_helper_->Update();
203 }
204
205 private:
206 ArcCustomNotificationView* const owner_;
207
208 DISALLOW_COPY_AND_ASSIGN(ContentViewDelegate);
209 };
210
211 ArcCustomNotificationView::ControlButton::ControlButton(
212 ArcCustomNotificationView* owner)
213 : message_center::PaddedButton(owner), owner_(owner) {
214 if (owner_->item_) {
215 set_background(views::Background::CreateSolidBackground(
216 GetControlButtonBackgroundColor(owner_->item_->GetShownContents())));
217 } else {
218 set_background(views::Background::CreateSolidBackground(
219 message_center::kControlButtonBackgroundColor));
220 }
221 }
222
223 void ArcCustomNotificationView::ControlButton::OnFocus() {
224 message_center::PaddedButton::OnFocus();
225 owner_->UpdateControlButtonsVisibility();
226 }
227
228 void ArcCustomNotificationView::ControlButton::OnBlur() {
229 message_center::PaddedButton::OnBlur();
230 owner_->UpdateControlButtonsVisibility();
231 }
232
233 ArcCustomNotificationView::ArcCustomNotificationView(ArcNotificationItem* item)
234 : item_(item),
235 notification_key_(item->GetNotificationKey()),
236 event_forwarder_(new EventForwarder(this)) {
237 SetFocusBehavior(FocusBehavior::ALWAYS);
238
239 item_->IncrementWindowRefCount();
240 item_->AddObserver(this);
241
242 auto* surface_manager = ArcNotificationSurfaceManager::Get();
243 if (surface_manager) {
244 surface_manager->AddObserver(this);
245 exo::NotificationSurface* surface =
246 surface_manager->GetSurface(notification_key_);
247 if (surface)
248 OnNotificationSurfaceAdded(surface);
249 }
250
251 // Create a layer as an anchor to insert surface copy during a slide.
252 SetPaintToLayer();
253 UpdatePreferredSize();
254 }
255
256 ArcCustomNotificationView::~ArcCustomNotificationView() {
257 SetSurface(nullptr);
258
259 auto* surface_manager = ArcNotificationSurfaceManager::Get();
260 if (surface_manager)
261 surface_manager->RemoveObserver(this);
262 if (item_) {
263 item_->RemoveObserver(this);
264 item_->DecrementWindowRefCount();
265 }
266 }
267
268 std::unique_ptr<ArcNotificationContentViewDelegate>
269 ArcCustomNotificationView::CreateContentViewDelegate() {
270 return base::MakeUnique<ArcCustomNotificationView::ContentViewDelegate>(this);
271 }
272
273 void ArcCustomNotificationView::CreateCloseButton() {
274 DCHECK(control_buttons_view_);
275 DCHECK(item_);
276
277 close_button_ = base::MakeUnique<ControlButton>(this);
278 close_button_->SetImage(views::CustomButton::STATE_NORMAL,
279 message_center::GetCloseIcon());
280 close_button_->SetAccessibleName(l10n_util::GetStringUTF16(
281 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
282 close_button_->SetTooltipText(l10n_util::GetStringUTF16(
283 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_TOOLTIP));
284 close_button_->set_owned_by_client();
285 control_buttons_view_->AddChildView(close_button_.get());
286 }
287
288 void ArcCustomNotificationView::CreateSettingsButton() {
289 DCHECK(control_buttons_view_);
290 DCHECK(item_);
291
292 settings_button_ = new ControlButton(this);
293 settings_button_->SetImage(views::CustomButton::STATE_NORMAL,
294 message_center::GetSettingsIcon());
295 settings_button_->SetAccessibleName(l10n_util::GetStringUTF16(
296 IDS_MESSAGE_NOTIFICATION_SETTINGS_BUTTON_ACCESSIBLE_NAME));
297 settings_button_->SetTooltipText(l10n_util::GetStringUTF16(
298 IDS_MESSAGE_NOTIFICATION_SETTINGS_BUTTON_ACCESSIBLE_NAME));
299 control_buttons_view_->AddChildView(settings_button_);
300 }
301
302 void ArcCustomNotificationView::MaybeCreateFloatingControlButtons() {
303 // Floating close button is a transient child of |surface_| and also part
304 // of the hosting widget's focus chain. It could only be created when both
305 // are present. Further, if we are being destroyed (|item_| is null), don't
306 // create the control buttons.
307 if (!surface_ || !GetWidget() || !item_)
308 return;
309
310 // Creates the control_buttons_view_, which collects all control buttons into
311 // a horizontal box.
312 control_buttons_view_ = new views::View();
313 control_buttons_view_->SetLayoutManager(
314 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
315
316 if (item_->IsOpeningSettingsSupported())
317 CreateSettingsButton();
318 if (!item_->GetPinned())
319 CreateCloseButton();
320
321 views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
322 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
323 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
324 params.parent = surface_->window();
325
326 floating_control_buttons_widget_.reset(new views::Widget);
327 floating_control_buttons_widget_->Init(params);
328 floating_control_buttons_widget_->SetContentsView(control_buttons_view_);
329
330 // Put the close button into the focus chain.
331 floating_control_buttons_widget_->SetFocusTraversableParent(
332 GetWidget()->GetFocusTraversable());
333 floating_control_buttons_widget_->SetFocusTraversableParentView(this);
334
335 Layout();
336 }
337
338 void ArcCustomNotificationView::SetSurface(exo::NotificationSurface* surface) {
339 if (surface_ == surface)
340 return;
341
342 // Reset |floating_control_buttons_widget_| when |surface_| is changed.
343 floating_control_buttons_widget_.reset();
344 control_buttons_view_ = nullptr;
345 settings_button_ = nullptr;
346 close_button_.reset();
347
348 if (surface_ && surface_->window()) {
349 surface_->window()->RemoveObserver(this);
350 surface_->window()->RemovePreTargetHandler(event_forwarder_.get());
351 }
352
353 surface_ = surface;
354
355 if (surface_ && surface_->window()) {
356 surface_->window()->AddObserver(this);
357 surface_->window()->AddPreTargetHandler(event_forwarder_.get());
358
359 MaybeCreateFloatingControlButtons();
360
361 if (GetWidget())
362 AttachSurface();
363 }
364 }
365
366 void ArcCustomNotificationView::UpdatePreferredSize() {
367 gfx::Size preferred_size;
368 if (surface_)
369 preferred_size = surface_->GetSize();
370 else if (item_)
371 preferred_size = item_->GetSnapshot().size();
372
373 if (preferred_size.IsEmpty())
374 return;
375
376 if (preferred_size.width() != message_center::kNotificationWidth) {
377 const float scale = static_cast<float>(message_center::kNotificationWidth) /
378 preferred_size.width();
379 preferred_size.SetSize(message_center::kNotificationWidth,
380 preferred_size.height() * scale);
381 }
382
383 SetPreferredSize(preferred_size);
384 }
385
386 void ArcCustomNotificationView::UpdateControlButtonsVisibility() {
387 if (!surface_)
388 return;
389
390 // TODO(edcourtney, yhanada): Creating the floating control widget here is not
391 // correct. This function may be called during the destruction of
392 // |floating_control_buttons_widget_|. This can lead to memory corruption.
393 // Rather than creating it here, we should fix the behaviour of OnMouseExited
394 // and OnMouseEntered for ARC notifications in MessageCenterView. See
395 // crbug.com/714587 and crbug.com/709862.
396 if (!floating_control_buttons_widget_) {
397 // This may update |floating_control_buttons_widget_|.
398 MaybeCreateFloatingControlButtons();
399 if (!floating_control_buttons_widget_)
400 return;
401 }
402
403 const bool target_visiblity =
404 IsMouseHovered() || (close_button_ && close_button_->HasFocus()) ||
405 (settings_button_ && settings_button_->HasFocus());
406 if (target_visiblity == floating_control_buttons_widget_->IsVisible())
407 return;
408
409 if (target_visiblity)
410 floating_control_buttons_widget_->Show();
411 else
412 floating_control_buttons_widget_->Hide();
413 }
414
415 void ArcCustomNotificationView::UpdatePinnedState() {
416 if (!item_)
417 return;
418
419 if (item_->GetPinned() && close_button_) {
420 control_buttons_view_->RemoveChildView(close_button_.get());
421 close_button_.reset();
422 Layout();
423 } else if (!item_->GetPinned() && !close_button_) {
424 CreateCloseButton();
425 Layout();
426 }
427 }
428
429 void ArcCustomNotificationView::UpdateSnapshot() {
430 // Bail if we have a |surface_| because it controls the sizes and paints UI.
431 if (surface_)
432 return;
433
434 UpdatePreferredSize();
435 SchedulePaint();
436 }
437
438 void ArcCustomNotificationView::AttachSurface() {
439 if (!GetWidget())
440 return;
441
442 UpdatePreferredSize();
443 Attach(surface_->window());
444
445 // The texture for this window can be placed at subpixel position
446 // with fractional scale factor. Force to align it at the pixel
447 // boundary here, and when layout is updated in Layout().
448 ash::wm::SnapWindowToPixelBoundary(surface_->window());
449
450 // Creates slide helper after this view is added to its parent.
451 slide_helper_.reset(new SlideHelper(this));
452
453 // Invokes Update() in case surface is attached during a slide.
454 slide_helper_->Update();
455
456 // Updates pinned state to create or destroy the floating close button
457 // after |surface_| is attached to a widget.
458 if (item_)
459 UpdatePinnedState();
460 }
461
462 void ArcCustomNotificationView::StartControlButtonsColorAnimation() {
463 if (control_button_color_animation_)
464 control_button_color_animation_->End();
465 control_button_color_animation_.reset(new gfx::LinearAnimation(this));
466 control_button_color_animation_->SetDuration(kBackgroundColorChangeDuration);
467 control_button_color_animation_->Start();
468 }
469
470 bool ArcCustomNotificationView::ShouldUpdateControlButtonsColor() const {
471 // Don't update the control button color when we are about to be destroyed.
472 if (!item_)
473 return false;
474
475 if (settings_button_ &&
476 settings_button_->background()->get_color() !=
477 GetControlButtonBackgroundColor(item_->GetShownContents()))
478 return true;
479 if (close_button_ &&
480 close_button_->background()->get_color() !=
481 GetControlButtonBackgroundColor(item_->GetShownContents()))
482 return true;
483 return false;
484 }
485
486 void ArcCustomNotificationView::ViewHierarchyChanged(
487 const views::View::ViewHierarchyChangedDetails& details) {
488 views::Widget* widget = GetWidget();
489
490 if (!details.is_add) {
491 // Resets slide helper when this view is removed from its parent.
492 slide_helper_.reset();
493
494 // Bail if this view is no longer attached to a widget or native_view() has
495 // attached to a different widget.
496 if (!widget || (native_view() &&
497 views::Widget::GetTopLevelWidgetForNativeView(
498 native_view()) != widget)) {
499 return;
500 }
501 }
502
503 views::NativeViewHost::ViewHierarchyChanged(details);
504
505 if (!widget || !surface_ || !details.is_add)
506 return;
507
508 AttachSurface();
509 }
510
511 void ArcCustomNotificationView::Layout() {
512 base::AutoReset<bool> auto_reset_in_layout(&in_layout_, true);
513
514 views::NativeViewHost::Layout();
515
516 if (!surface_ || !GetWidget())
517 return;
518
519 const gfx::Rect contents_bounds = GetContentsBounds();
520
521 // Scale notification surface if necessary.
522 gfx::Transform transform;
523 const gfx::Size surface_size = surface_->GetSize();
524 const gfx::Size contents_size = contents_bounds.size();
525 if (!surface_size.IsEmpty() && !contents_size.IsEmpty()) {
526 transform.Scale(
527 static_cast<float>(contents_size.width()) / surface_size.width(),
528 static_cast<float>(contents_size.height()) / surface_size.height());
529 }
530
531 // Apply the transform to the surface content so that close button can
532 // be positioned without the need to consider the transform.
533 surface_->window()->children()[0]->SetTransform(transform);
534
535 if (!floating_control_buttons_widget_)
536 return;
537
538 gfx::Rect control_buttons_bounds(contents_bounds);
539 int buttons_width = 0;
540 int buttons_height = 0;
541 if (close_button_) {
542 buttons_width += close_button_->GetPreferredSize().width();
543 buttons_height = close_button_->GetPreferredSize().height();
544 }
545 if (settings_button_) {
546 buttons_width += settings_button_->GetPreferredSize().width();
547 buttons_height = settings_button_->GetPreferredSize().height();
548 }
549 control_buttons_bounds.set_x(control_buttons_bounds.right() - buttons_width -
550 message_center::kControlButtonPadding);
551 control_buttons_bounds.set_y(control_buttons_bounds.y() +
552 message_center::kControlButtonPadding);
553 control_buttons_bounds.set_width(buttons_width);
554 control_buttons_bounds.set_height(buttons_height);
555 floating_control_buttons_widget_->SetBounds(control_buttons_bounds);
556
557 UpdateControlButtonsVisibility();
558
559 ash::wm::SnapWindowToPixelBoundary(surface_->window());
560 }
561
562 void ArcCustomNotificationView::OnPaint(gfx::Canvas* canvas) {
563 views::NativeViewHost::OnPaint(canvas);
564
565 // Bail if there is a |surface_| or no item or no snapshot image.
566 if (surface_ || !item_ || item_->GetSnapshot().isNull())
567 return;
568 const gfx::Rect contents_bounds = GetContentsBounds();
569 canvas->DrawImageInt(item_->GetSnapshot(), 0, 0, item_->GetSnapshot().width(),
570 item_->GetSnapshot().height(), contents_bounds.x(),
571 contents_bounds.y(), contents_bounds.width(),
572 contents_bounds.height(), false);
573 }
574
575 void ArcCustomNotificationView::OnMouseEntered(const ui::MouseEvent&) {
576 UpdateControlButtonsVisibility();
577 }
578
579 void ArcCustomNotificationView::OnMouseExited(const ui::MouseEvent&) {
580 UpdateControlButtonsVisibility();
581 }
582
583 void ArcCustomNotificationView::OnFocus() {
584 CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName());
585
586 NativeViewHost::OnFocus();
587 static_cast<ArcNotificationView*>(parent())->OnContentFocused();
588 }
589
590 void ArcCustomNotificationView::OnBlur() {
591 if (!parent()) {
592 // OnBlur may be called when this view is being removed.
593 return;
594 }
595
596 CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName());
597
598 NativeViewHost::OnBlur();
599 static_cast<ArcNotificationView*>(parent())->OnContentBlured();
600 }
601
602 void ArcCustomNotificationView::ActivateToast() {
603 if (message_center::ToastContentsView::kViewClassName ==
604 parent()->parent()->GetClassName()) {
605 static_cast<message_center::ToastContentsView*>(parent()->parent())
606 ->ActivateToast();
607 }
608 }
609
610 views::FocusTraversable* ArcCustomNotificationView::GetFocusTraversable() {
611 if (floating_control_buttons_widget_)
612 return static_cast<views::internal::RootView*>(
613 floating_control_buttons_widget_->GetRootView());
614 return nullptr;
615 }
616
617 bool ArcCustomNotificationView::HandleAccessibleAction(
618 const ui::AXActionData& action_data) {
619 if (item_ && action_data.action == ui::AX_ACTION_DO_DEFAULT) {
620 item_->ToggleExpansion();
621 return true;
622 }
623 return false;
624 }
625
626 void ArcCustomNotificationView::ButtonPressed(views::Button* sender,
627 const ui::Event& event) {
628 if (item_ && !item_->GetPinned() && sender == close_button_.get()) {
629 CHECK_EQ(ArcNotificationView::kViewClassName, parent()->GetClassName());
630 static_cast<ArcNotificationView*>(parent())->OnCloseButtonPressed();
631 }
632 if (item_ && settings_button_ && sender == settings_button_) {
633 item_->OpenSettings();
634 }
635 }
636
637 void ArcCustomNotificationView::OnWindowBoundsChanged(
638 aura::Window* window,
639 const gfx::Rect& old_bounds,
640 const gfx::Rect& new_bounds) {
641 if (in_layout_)
642 return;
643
644 UpdatePreferredSize();
645 Layout();
646 }
647
648 void ArcCustomNotificationView::OnWindowDestroying(aura::Window* window) {
649 SetSurface(nullptr);
650 }
651
652 void ArcCustomNotificationView::OnItemDestroying() {
653 item_->RemoveObserver(this);
654 item_ = nullptr;
655
656 // Reset |surface_| with |item_| since no one is observing the |surface_|
657 // after |item_| is gone and this view should be removed soon.
658 SetSurface(nullptr);
659 }
660
661 void ArcCustomNotificationView::OnItemUpdated() {
662 UpdatePinnedState();
663 UpdateSnapshot();
664 if (ShouldUpdateControlButtonsColor())
665 StartControlButtonsColorAnimation();
666 }
667
668 void ArcCustomNotificationView::OnNotificationSurfaceAdded(
669 exo::NotificationSurface* surface) {
670 if (surface->notification_id() != notification_key_)
671 return;
672
673 SetSurface(surface);
674 }
675
676 void ArcCustomNotificationView::OnNotificationSurfaceRemoved(
677 exo::NotificationSurface* surface) {
678 if (surface->notification_id() != notification_key_)
679 return;
680
681 SetSurface(nullptr);
682 }
683
684 void ArcCustomNotificationView::AnimationEnded(
685 const gfx::Animation* animation) {
686 DCHECK_EQ(animation, control_button_color_animation_.get());
687 control_button_color_animation_.reset();
688 }
689
690 void ArcCustomNotificationView::AnimationProgressed(
691 const gfx::Animation* animation) {
692 DCHECK_EQ(animation, control_button_color_animation_.get());
693
694 if (item_) {
695 const SkColor target =
696 GetControlButtonBackgroundColor(item_->GetShownContents());
697 const SkColor start =
698 target == message_center::kControlButtonBackgroundColor
699 ? SK_ColorTRANSPARENT
700 : message_center::kControlButtonBackgroundColor;
701 const SkColor current_color = gfx::Tween::ColorValueBetween(
702 animation->GetCurrentValue(), start, target);
703 if (settings_button_) {
704 settings_button_->set_background(
705 views::Background::CreateSolidBackground(current_color));
706 settings_button_->SchedulePaint();
707 }
708 if (close_button_) {
709 close_button_->set_background(
710 views::Background::CreateSolidBackground(current_color));
711 close_button_->SchedulePaint();
712 }
713 }
714 }
715
716 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698