Commit 4ee3082c authored by derat@chromium.org's avatar derat@chromium.org

chromeos: Update volume key behavior.

This brings us closer to the most-recent UX request that
I've seen:

- muting displays the previous volume level in a disabled
  state rather than displaying 0%
- volume down while muted drops the level to 0%
- volume up while muted unmutes and raises the level to 25%
  if it was 0% or restores the previous level otherwise

The requested behavior is actually to swell to the louder
volume over three seconds in the volume-up-while-muted case
instead of doing it instantly, but the mixer code doesn't
support that at present, so I'm punting on it for now.

BUG=chromium-os:8473,chromium-os:13618
TEST=manual

Review URL: http://codereview.chromium.org/7566018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95873 0039d316-1c4b-4281-b951-d872f2087c98
parent a7e585a7
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
......@@ -11,9 +11,9 @@ namespace chromeos {
void BrightnessObserver::BrightnessChanged(int level, bool user_initiated) {
if (user_initiated)
BrightnessBubble::GetInstance()->ShowBubble(level);
BrightnessBubble::GetInstance()->ShowBubble(level, true);
else
BrightnessBubble::GetInstance()->UpdateWithoutShowingBubble(level);
BrightnessBubble::GetInstance()->UpdateWithoutShowingBubble(level, true);
VolumeBubble::GetInstance()->HideBubble();
}
......
......@@ -74,12 +74,12 @@ static views::Widget* GetToplevelWidget() {
SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
SkBitmap* decrease_icon,
SkBitmap* zero_icon)
SkBitmap* disabled_icon)
: previous_percent_(-1),
current_percent_(-1),
increase_icon_(increase_icon),
decrease_icon_(decrease_icon),
zero_icon_(zero_icon),
disabled_icon_(disabled_icon),
bubble_(NULL),
view_(NULL),
animation_(this) {
......@@ -89,15 +89,15 @@ SettingLevelBubble::SettingLevelBubble(SkBitmap* increase_icon,
SettingLevelBubble::~SettingLevelBubble() {}
void SettingLevelBubble::ShowBubble(int percent) {
void SettingLevelBubble::ShowBubble(int percent, bool enabled) {
percent = LimitPercent(percent);
if (previous_percent_ == -1)
previous_percent_ = percent;
current_percent_ = percent;
SkBitmap* icon = increase_icon_;
if (current_percent_ == 0)
icon = zero_icon_;
if (!enabled || current_percent_ == 0)
icon = disabled_icon_;
else if (current_percent_ < previous_percent_)
icon = decrease_icon_;
......@@ -109,7 +109,7 @@ void SettingLevelBubble::ShowBubble(int percent) {
}
DCHECK(view_ == NULL);
view_ = new SettingLevelBubbleView;
view_->Init(icon, previous_percent_);
view_->Init(icon, previous_percent_, enabled);
// Calculate the position in screen coordinates that the bubble should
// "point" at (since we use BubbleBorder::FLOAT, this position actually
......@@ -135,10 +135,14 @@ void SettingLevelBubble::ShowBubble(int percent) {
timeout_timer_.Stop();
view_->SetIcon(icon);
}
view_->SetEnabled(enabled);
if (animation_.is_animating())
animation_.End();
animation_.Reset();
animation_.Show();
timeout_timer_.Start(base::TimeDelta::FromSeconds(kBubbleShowTimeoutSec),
this, &SettingLevelBubble::OnTimeout);
}
......@@ -148,7 +152,10 @@ void SettingLevelBubble::HideBubble() {
bubble_->Close();
}
void SettingLevelBubble::UpdateWithoutShowingBubble(int percent) {
void SettingLevelBubble::UpdateWithoutShowingBubble(int percent, bool enabled) {
if (view_)
view_->SetEnabled(enabled);
percent = LimitPercent(percent);
previous_percent_ =
......@@ -191,7 +198,7 @@ void SettingLevelBubble::AnimationEnded(const ui::Animation* animation) {
void SettingLevelBubble::AnimationProgressed(const ui::Animation* animation) {
if (view_) {
view_->Update(
view_->SetLevel(
ui::Tween::ValueBetween(animation->GetCurrentValue(),
previous_percent_,
current_percent_));
......
......@@ -23,7 +23,7 @@ class SettingLevelBubbleView;
class SettingLevelBubble : public BubbleDelegate,
public ui::AnimationDelegate {
public:
void ShowBubble(int percent);
void ShowBubble(int percent, bool enabled);
void HideBubble();
// Update the bubble's current level without showing the bubble onscreen.
......@@ -41,7 +41,7 @@ class SettingLevelBubble : public BubbleDelegate,
// If we didn't update our internal state to 25% after 2), then the animation
// displayed in response to 3) would show the bubble animating from 50% down
// to 30%, rather than from 25% up to 30%.
void UpdateWithoutShowingBubble(int percent);
void UpdateWithoutShowingBubble(int percent, bool enabled);
protected:
SettingLevelBubble(SkBitmap* increase_icon,
......@@ -53,23 +53,23 @@ class SettingLevelBubble : public BubbleDelegate,
void OnTimeout();
// Overridden from BubbleDelegate.
virtual void BubbleClosing(Bubble* bubble, bool closed_by_escape);
virtual bool CloseOnEscape();
virtual bool FadeInOnShow();
virtual void BubbleClosing(Bubble* bubble, bool closed_by_escape) OVERRIDE;
virtual bool CloseOnEscape() OVERRIDE;
virtual bool FadeInOnShow() OVERRIDE;
// Overridden from ui::AnimationDelegate.
virtual void AnimationEnded(const ui::Animation* animation);
virtual void AnimationProgressed(const ui::Animation* animation);
virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
// Previous and current percentages, or -1 if not yet shown.
int previous_percent_;
int current_percent_;
// Icons displayed in the bubble when increasing or decreasing the level or
// setting it to zero. Not owned by us.
// when it's disabled. Not owned by us.
SkBitmap* increase_icon_;
SkBitmap* decrease_icon_;
SkBitmap* zero_icon_;
SkBitmap* disabled_icon_;
// Currently shown bubble or NULL.
Bubble* bubble_;
......
......@@ -32,15 +32,18 @@ SettingLevelBubbleView::SettingLevelBubbleView()
icon_(NULL) {
}
void SettingLevelBubbleView::Init(SkBitmap* icon, int level_percent) {
void SettingLevelBubbleView::Init(SkBitmap* icon,
int level_percent,
bool enabled) {
DCHECK(icon);
DCHECK(level_percent >= 0 && level_percent <= 100);
icon_ = icon;
progress_bar_ = new views::ProgressBar();
AddChildView(progress_bar_);
Update(level_percent);
progress_bar_->EnableCanvasFlippingForRTLUI(true);
EnableCanvasFlippingForRTLUI(true);
SetLevel(level_percent);
SetEnabled(enabled);
}
void SettingLevelBubbleView::SetIcon(SkBitmap* icon) {
......@@ -49,11 +52,15 @@ void SettingLevelBubbleView::SetIcon(SkBitmap* icon) {
SchedulePaint();
}
void SettingLevelBubbleView::Update(int level_percent) {
void SettingLevelBubbleView::SetLevel(int level_percent) {
DCHECK(level_percent >= 0 && level_percent <= 100);
progress_bar_->SetProgress(level_percent);
}
void SettingLevelBubbleView::SetEnabled(bool enabled) {
progress_bar_->SetEnabled(enabled);
}
void SettingLevelBubbleView::OnPaint(gfx::Canvas* canvas) {
views::View::OnPaint(canvas);
canvas->DrawBitmapInt(*icon_, kPadding, (height() - icon_->height()) / 2);
......
......@@ -22,21 +22,24 @@ class SettingLevelBubbleView : public views::View {
public:
SettingLevelBubbleView();
// Initialize the view, setting the progress bar to the specified position.
// Ownership of |icon| remains with the caller (it's probably a shared
// Initialize the view, setting the progress bar to the specified level and
// state. Ownership of |icon| remains with the caller (it's probably a shared
// instance from ResourceBundle).
void Init(SkBitmap* icon, int level_percent);
void Init(SkBitmap* icon, int level_percent, bool enabled);
// Change the icon that we're currently displaying.
void SetIcon(SkBitmap* icon);
// Set the progress bar to the specified position and redraw it.
void Update(int level_percent);
// Set the progress bar to the specified level and redraw it.
void SetLevel(int level_percent);
// Draw the progress bar in an enabled or disabled state.
void SetEnabled(bool enabled);
// views::View implementation:
virtual void OnPaint(gfx::Canvas* canvas);
virtual void Layout();
virtual gfx::Size GetPreferredSize();
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void Layout() OVERRIDE;
virtual gfx::Size GetPreferredSize() OVERRIDE;
private:
views::ProgressBar* progress_bar_;
......
......@@ -26,6 +26,11 @@ namespace {
// Percent by which the volume should be changed when a volume key is pressed.
const double kStepPercentage = 4.0;
// Percent to which the volume should be set when the "volume up" key is pressed
// while we're muted and have the volume set to 0. See
// http://crosbug.com/13618.
const double kVolumePercentOnVolumeUpWhileMuted = 25.0;
} // namespace
// static
......@@ -169,36 +174,32 @@ void SystemKeyEventListener::OnVolumeMute() {
// Always muting (and not toggling) as per final decision on
// http://crosbug.com/3751
audio_handler_->SetMuted(true);
VolumeBubble::GetInstance()->ShowBubble(0);
BrightnessBubble::GetInstance()->HideBubble();
ShowVolumeBubble();
}
void SystemKeyEventListener::OnVolumeDown() {
if (!audio_handler_->IsInitialized())
return;
if (audio_handler_->IsMuted()) {
VolumeBubble::GetInstance()->ShowBubble(0);
} else {
if (audio_handler_->IsMuted())
audio_handler_->SetVolumePercent(0.0);
else
audio_handler_->AdjustVolumeByPercent(-kStepPercentage);
VolumeBubble::GetInstance()->ShowBubble(
audio_handler_->GetVolumePercent());
}
BrightnessBubble::GetInstance()->HideBubble();
ShowVolumeBubble();
}
void SystemKeyEventListener::OnVolumeUp() {
if (!audio_handler_->IsInitialized())
return;
if (audio_handler_->IsMuted())
if (audio_handler_->IsMuted()) {
audio_handler_->SetMuted(false);
else
if (audio_handler_->GetVolumePercent() <= 0.1) // float comparison
audio_handler_->SetVolumePercent(kVolumePercentOnVolumeUpWhileMuted);
} else {
audio_handler_->AdjustVolumeByPercent(kStepPercentage);
VolumeBubble::GetInstance()->ShowBubble(
audio_handler_->GetVolumePercent());
BrightnessBubble::GetInstance()->HideBubble();
}
ShowVolumeBubble();
}
void SystemKeyEventListener::OnCapsLock(bool enabled) {
......@@ -206,6 +207,13 @@ void SystemKeyEventListener::OnCapsLock(bool enabled) {
CapsLockObserver, caps_lock_observers_, OnCapsLockChange(enabled));
}
void SystemKeyEventListener::ShowVolumeBubble() {
VolumeBubble::GetInstance()->ShowBubble(
audio_handler_->GetVolumePercent(),
!audio_handler_->IsMuted());
BrightnessBubble::GetInstance()->HideBubble();
}
bool SystemKeyEventListener::ProcessedXEvent(XEvent* xevent) {
if (xevent->type == xkb_event_base_) {
XkbEvent* xkey_event = reinterpret_cast<XkbEvent*>(xevent);
......
......@@ -76,6 +76,10 @@ class SystemKeyEventListener : public WmMessageListener::Observer,
void OnVolumeUp();
void OnCapsLock(bool enabled);
// Displays the volume bubble for the current volume and muting status.
// Also hides the brightness bubble if it's being shown.
void ShowVolumeBubble();
// Returns true if the event was processed, false otherwise.
virtual bool ProcessedXEvent(XEvent* xevent);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment