volume_bubble.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2010 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/chromeos/volume_bubble.h" 6 7#include <gdk/gdk.h> 8 9#include "base/timer.h" 10#include "chrome/browser/browser_list.h" 11#include "chrome/browser/browser_window.h" 12#include "chrome/browser/profile_manager.h" 13#include "chrome/browser/chromeos/volume_bubble_view.h" 14#include "chrome/browser/ui/browser.h" 15#include "chrome/browser/views/info_bubble.h" 16#include "views/widget/root_view.h" 17 18namespace { 19 20const int kBubbleShowTimeoutSec = 2; 21const int kAnimationDurationMs = 200; 22 23// Horizontal relative position: 0 - leftmost, 0.5 - center, 1 - rightmost. 24const double kVolumeBubbleXRatio = 0.5; 25 26// Vertical gap from the bottom of the screen in pixels. 27const int kVolumeBubbleBottomGap = 30; 28 29} // namespace 30 31namespace chromeos { 32 33// Temporary helper routine. Returns the widget from the most-recently-focused 34// normal browser window or NULL. 35// TODO(glotov): remove this in favor of enabling InfoBubble class act 36// without |parent| specified. crosbug.com/4025 37static views::Widget* GetToplevelWidget() { 38 // We just use the default profile here -- this gets overridden as needed 39 // in Chrome OS depending on whether the user is logged in or not. 40 Browser* browser = 41 BrowserList::FindBrowserWithType( 42 ProfileManager::GetDefaultProfile(), 43 Browser::TYPE_NORMAL, 44 true); // match_incognito 45 if (!browser) 46 return NULL; 47 48 views::RootView* root = 49 views::Widget::FindRootView( 50 GTK_WINDOW(browser->window()->GetNativeHandle())); 51 DCHECK(root); 52 if (!root) 53 return NULL; 54 55 return root->GetWidget(); 56} 57 58VolumeBubble::VolumeBubble() 59 : previous_percent_(-1), 60 current_percent_(-1), 61 bubble_(NULL), 62 view_(NULL), 63 animation_(this) { 64 animation_.SetSlideDuration(kAnimationDurationMs); 65 animation_.SetTweenType(Tween::LINEAR); 66} 67 68void VolumeBubble::ShowVolumeBubble(int percent) { 69 if (percent < 0) 70 percent = 0; 71 if (percent > 100) 72 percent = 100; 73 if (previous_percent_ == -1) 74 previous_percent_ = percent; 75 current_percent_ = percent; 76 if (!bubble_) { 77 views::Widget* widget = GetToplevelWidget(); 78 if (widget == NULL) 79 return; 80 DCHECK(view_ == NULL); 81 view_ = new VolumeBubbleView; 82 view_->Init(previous_percent_); 83 // Calculate position of the volume bubble. 84 // TODO(glotov): Place volume bubble over the keys initiated the 85 // volume change. This metric must be specific to the given 86 // architecture. crosbug.com/4028 87 gfx::Rect bounds; 88 widget->GetBounds(&bounds, false); 89 const gfx::Size view_size = view_->GetPreferredSize(); 90 // Note that (x, y) is the point of the center of the bubble. 91 const int x = view_size.width() / 2 + 92 kVolumeBubbleXRatio * (bounds.width() - view_size.width()); 93 const int y = bounds.height() - view_size.height() / 2 - 94 kVolumeBubbleBottomGap; 95 bubble_ = InfoBubble::ShowFocusless(widget, gfx::Rect(x, y, 0, 20), 96 BubbleBorder::FLOAT, view_, this); 97 } else { 98 DCHECK(view_); 99 timeout_timer_.Stop(); 100 } 101 if (animation_.is_animating()) 102 animation_.End(); 103 animation_.Reset(); 104 animation_.Show(); 105 timeout_timer_.Start(base::TimeDelta::FromSeconds(kBubbleShowTimeoutSec), 106 this, &VolumeBubble::OnTimeout); 107} 108 109void VolumeBubble::OnTimeout() { 110 if (bubble_) 111 bubble_->Close(); 112} 113 114void VolumeBubble::InfoBubbleClosing(InfoBubble* info_bubble, bool) { 115 DCHECK(info_bubble == bubble_); 116 timeout_timer_.Stop(); 117 animation_.Stop(); 118 bubble_ = NULL; 119 view_ = NULL; 120} 121 122void VolumeBubble::AnimationEnded(const Animation* animation) { 123 previous_percent_ = current_percent_; 124} 125 126void VolumeBubble::AnimationProgressed(const Animation* animation) { 127 if (view_) { 128 view_->Update( 129 Tween::ValueBetween(animation->GetCurrentValue(), 130 previous_percent_, 131 current_percent_)); 132 } 133} 134 135} // namespace chromeos 136