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

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

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

Powered by Google App Engine
This is Rietveld 408576698