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

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: rebase + add about:flags experiment 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 &&
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
106 // Note: The calls to SetImage(), SetEnabled(), and SetState() above will call
107 // SchedulePaint() if necessary.
108 }
109
110 const char* MediaIndicatorButton::GetClassName() const {
111 return kViewClassName;
112 }
113
114 views::View* MediaIndicatorButton::GetTooltipHandlerForPoint(
115 const gfx::Point& point) {
116 return NULL; // Tab (the parent View) provides the tooltip.
117 }
118
119 bool MediaIndicatorButton::OnMouseDragged(const ui::MouseEvent& event) {
120 const ButtonState previous_state = state();
121 const bool ret = ImageButton::OnMouseDragged(event);
122 if (previous_state != views::CustomButton::STATE_NORMAL &&
123 state() == views::CustomButton::STATE_NORMAL)
124 content::RecordAction(UserMetricsAction("MediaIndicatorButton_Dragged"));
125 return ret;
126 }
127
128 void MediaIndicatorButton::OnPaint(gfx::Canvas* canvas) {
129 double opaqueness =
130 fade_animation_ ? fade_animation_->GetCurrentValue() : 1.0;
131 if (media_state_ == TAB_MEDIA_STATE_NONE)
132 opaqueness = 1.0 - opaqueness; // Fading out, not in.
133 if (opaqueness < 1.0)
134 canvas->SaveLayerAlpha(opaqueness * SK_AlphaOPAQUE);
135 ImageButton::OnPaint(canvas);
136 if (opaqueness < 1.0)
137 canvas->Restore();
138 }
139
140 bool MediaIndicatorButton::DoesIntersectRect(const views::View* target,
141 const gfx::Rect& rect) const {
142 // If this button is not enabled, Tab (the parent View) handles all mouse
143 // events.
144 return enabled() &&
145 views::ViewTargeterDelegate::DoesIntersectRect(target, rect);
146 }
147
148 void MediaIndicatorButton::NotifyClick(const ui::Event& event) {
149 if (media_state_ == TAB_MEDIA_STATE_AUDIO_PLAYING)
150 content::RecordAction(UserMetricsAction("MediaIndicatorButton_Mute"));
151 else if (media_state_ == TAB_MEDIA_STATE_AUDIO_MUTING)
152 content::RecordAction(UserMetricsAction("MediaIndicatorButton_Unmute"));
153 else
154 NOTREACHED();
155
156 DCHECK(parent() && !strcmp(parent()->GetClassName(), Tab::kViewClassName));
157 Tab* const tab = static_cast<Tab*>(parent());
158 tab->controller()->ToggleTabAudioMute(tab);
159 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/media_indicator_button.h ('k') | chrome/browser/ui/views/tabs/tab.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698