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