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

Side by Side Diff: chrome/browser/ui/views/tabs/media_indicator_button.cc

Issue 591963002: Tab audio mute control (views UI), behind a switch (off by default). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix generated_resources.grd changes for Mac compile. Created 6 years, 2 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 2014 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 "chrome/browser/ui/views/tabs/media_indicator_button.h"
6
7 #include "chrome/browser/ui/views/tabs/tab.h"
8 #include "chrome/browser/ui/views/tabs/tab_controller.h"
9 #include "chrome/browser/ui/views/tabs/tab_renderer_data.h"
10 #include "content/public/browser/user_metrics.h"
11 #include "ui/gfx/animation/animation_delegate.h"
12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/image/image.h"
14
15 using base::UserMetricsAction;
16
17 const char MediaIndicatorButton::kViewClassName[] = "MediaIndicatorButton";
18
19 class MediaIndicatorButton::FadeAnimationDelegate
20 : public gfx::AnimationDelegate {
21 public:
22 explicit FadeAnimationDelegate(MediaIndicatorButton* button)
23 : button_(button) {}
24 virtual ~FadeAnimationDelegate() {}
25
26 private:
27 // gfx::AnimationDelegate
28 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE {
29 button_->SchedulePaint();
30 }
31
32 virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE {
33 button_->showing_media_state_ = button_->media_state_;
34 button_->SchedulePaint();
35 }
36
37 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE {
38 button_->showing_media_state_ = button_->media_state_;
39 button_->SchedulePaint();
40 }
41
42 MediaIndicatorButton* const button_;
43
44 DISALLOW_COPY_AND_ASSIGN(FadeAnimationDelegate);
45 };
46
47 MediaIndicatorButton::MediaIndicatorButton()
48 : views::ImageButton(NULL),
49 media_state_(TAB_MEDIA_STATE_NONE),
50 showing_media_state_(TAB_MEDIA_STATE_NONE) {
51 SetEventTargeter(
52 scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
53 }
54
55 MediaIndicatorButton::~MediaIndicatorButton() {}
56
57 void MediaIndicatorButton::TransitionToMediaState(TabMediaState next_state) {
58 if (next_state == media_state_)
59 return;
60
61 if (next_state != TAB_MEDIA_STATE_NONE) {
62 const gfx::ImageSkia* const indicator_image =
63 chrome::GetTabMediaIndicatorImage(next_state).ToImageSkia();
64 SetImage(views::CustomButton::STATE_NORMAL, indicator_image);
65 SetImage(views::CustomButton::STATE_DISABLED, indicator_image);
66 const gfx::ImageSkia* const affordance_image =
67 chrome::GetTabMediaIndicatorAffordanceImage(next_state).ToImageSkia();
68 SetImage(views::CustomButton::STATE_HOVERED, affordance_image);
69 SetImage(views::CustomButton::STATE_PRESSED, affordance_image);
70 }
71
72 if ((media_state_ == TAB_MEDIA_STATE_AUDIO_PLAYING &&
sky 2014/09/25 19:25:04 It seems like all of this should be moved to non-v
miu 2014/09/25 22:49:36 Acknowledged. Yeah, what I needed is to modify th
73 next_state == TAB_MEDIA_STATE_AUDIO_MUTING) ||
74 (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING &&
75 next_state == TAB_MEDIA_STATE_AUDIO_PLAYING) ||
76 (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING &&
77 next_state == TAB_MEDIA_STATE_NONE)) {
78 // Instant user feedback: No fade animation.
79 showing_media_state_ = next_state;
80 fade_animation_.reset();
81 } else {
82 if (next_state == TAB_MEDIA_STATE_NONE)
83 showing_media_state_ = media_state_; // Fading-out indicator.
84 else
85 showing_media_state_ = next_state; // Fading-in to next indicator.
86 fade_animation_ = chrome::CreateTabMediaIndicatorFadeAnimation(next_state);
87 if (!fade_animation_delegate_)
88 fade_animation_delegate_.reset(new FadeAnimationDelegate(this));
89 fade_animation_->set_delegate(fade_animation_delegate_.get());
90 fade_animation_->Start();
91 }
92
93 SetEnabled(chrome::IsTabAudioMutingFeatureEnabled() &&
94 (next_state == TAB_MEDIA_STATE_AUDIO_PLAYING ||
95 next_state == TAB_MEDIA_STATE_AUDIO_MUTING));
96
97 // An indicator state change should be made visible immediately, instead of
98 // the user being surprised when their mouse leaves the button.
99 if (state() == views::CustomButton::STATE_HOVERED) {
100 SetState(enabled() ? views::CustomButton::STATE_NORMAL :
101 views::CustomButton::STATE_DISABLED);
102 }
103
104 media_state_ = next_state;
105 }
sky 2014/09/25 19:25:05 Do you need a SchedulePaint here? It isn't clear t
miu 2014/09/25 22:49:36 The calls to SetImage(), SetEnabled(), and SetStat
106
107 const char* MediaIndicatorButton::GetClassName() const {
108 return kViewClassName;
109 }
110
111 views::View* MediaIndicatorButton::GetTooltipHandlerForPoint(
112 const gfx::Point& point) {
113 return NULL; // Tab (the parent View) provides the tooltip.
114 }
115
116 bool MediaIndicatorButton::OnMouseDragged(const ui::MouseEvent& event) {
117 const ButtonState previous_state = state();
118 const bool ret = ImageButton::OnMouseDragged(event);
119 if (previous_state != views::CustomButton::STATE_NORMAL &&
120 state() == views::CustomButton::STATE_NORMAL)
121 content::RecordAction(UserMetricsAction("MediaIndicatorButton_Dragged"));
sky 2014/09/25 19:25:04 Why do you care about this? Also, consistently nam
miu 2014/09/25 22:49:36 I want a metric to help determine whether the mute
122 return ret;
123 }
124
125 void MediaIndicatorButton::OnPaint(gfx::Canvas* canvas) {
126 double opaqueness =
127 fade_animation_ ? fade_animation_->GetCurrentValue() : 1.0;
128 if (media_state_ == TAB_MEDIA_STATE_NONE)
129 opaqueness = 1.0 - opaqueness; // Fading out, not in.
sky 2014/09/25 19:25:05 Seems like the lookup for opaquness should move to
miu 2014/09/25 22:49:36 Acknowledged. As above, when I make the changes f
130 if (opaqueness < 1.0)
131 canvas->SaveLayerAlpha(opaqueness * SK_AlphaOPAQUE);
132 ImageButton::OnPaint(canvas);
133 if (opaqueness < 1.0)
134 canvas->Restore();
135 }
136
137 bool MediaIndicatorButton::DoesIntersectRect(const views::View* target,
138 const gfx::Rect& rect) const {
139 // If this button is not enabled, Tab (the parent View) handles all mouse
140 // events.
141 return enabled() &&
142 views::ViewTargeterDelegate::DoesIntersectRect(target, rect);
143 }
144
145 void MediaIndicatorButton::NotifyClick(const ui::Event& event) {
146 if (media_state_ == TAB_MEDIA_STATE_AUDIO_PLAYING)
147 content::RecordAction(UserMetricsAction("MuteTab"));
148 else if (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING)
149 content::RecordAction(UserMetricsAction("UnmuteTab"));
150 else
sky 2014/09/25 19:25:04 I suspect this can be hit. Specifically if the mou
miu 2014/09/25 22:49:36 I think we're good here: CustomButton (superclass)
sky 2014/09/25 23:39:46 You are right, I missed the CustomButton handling.
151 NOTREACHED();
152
153 DCHECK(parent() && !strcmp(parent()->GetClassName(), Tab::kViewClassName));
154 Tab* const tab = static_cast<Tab*>(parent());
155 tab->controller()->ToggleTabAudioMute(tab);
156 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698