• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 "ash/system/chromeos/brightness/tray_brightness.h"
6 
7 #include <algorithm>
8 
9 #include "ash/accelerators/accelerator_controller.h"
10 #include "ash/ash_constants.h"
11 #include "ash/display/display_manager.h"
12 #include "ash/metrics/user_metrics_recorder.h"
13 #include "ash/shell.h"
14 #include "ash/shell_observer.h"
15 #include "ash/system/brightness_control_delegate.h"
16 #include "ash/system/tray/fixed_sized_image_view.h"
17 #include "ash/system/tray/system_tray_delegate.h"
18 #include "ash/system/tray/system_tray_notifier.h"
19 #include "ash/system/tray/tray_constants.h"
20 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
21 #include "base/bind.h"
22 #include "base/message_loop/message_loop.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "chromeos/dbus/dbus_thread_manager.h"
25 #include "chromeos/dbus/power_manager_client.h"
26 #include "grit/ash_resources.h"
27 #include "grit/ash_strings.h"
28 #include "ui/base/resource/resource_bundle.h"
29 #include "ui/gfx/image/image.h"
30 #include "ui/views/controls/button/image_button.h"
31 #include "ui/views/controls/image_view.h"
32 #include "ui/views/controls/label.h"
33 #include "ui/views/controls/slider.h"
34 #include "ui/views/layout/box_layout.h"
35 #include "ui/views/view.h"
36 
37 namespace ash {
38 namespace tray {
39 namespace {
40 
41 // We don't let the screen brightness go lower than this when it's being
42 // adjusted via the slider.  Otherwise, if the user doesn't know about the
43 // brightness keys, they may turn the backlight off and not know how to turn it
44 // back on.
45 const double kMinBrightnessPercent = 5.0;
46 
47 }  // namespace
48 
49 class BrightnessView : public ShellObserver,
50                        public views::View,
51                        public views::SliderListener {
52  public:
53   BrightnessView(bool default_view, double initial_percent);
54   virtual ~BrightnessView();
55 
is_default_view() const56   bool is_default_view() const {
57     return is_default_view_;
58   }
59 
60   // |percent| is in the range [0.0, 100.0].
61   void SetBrightnessPercent(double percent);
62 
63   // ShellObserver:
64   virtual void OnMaximizeModeStarted() OVERRIDE;
65   virtual void OnMaximizeModeEnded() OVERRIDE;
66 
67  private:
68   // views::View:
69   virtual void OnBoundsChanged(const gfx::Rect& old_bounds) OVERRIDE;
70 
71   // views:SliderListener:
72   virtual void SliderValueChanged(views::Slider* sender,
73                                   float value,
74                                   float old_value,
75                                   views::SliderChangeReason reason) OVERRIDE;
76 
77   // views:SliderListener:
78   virtual void SliderDragStarted(views::Slider* slider) OVERRIDE;
79   virtual void SliderDragEnded(views::Slider* slider) OVERRIDE;
80 
81   views::Slider* slider_;
82 
83   // Is |slider_| currently being dragged?
84   bool dragging_;
85 
86   // True if this view is for the default tray view. Used to control hide/show
87   // behaviour of the default view when entering or leaving Maximize Mode.
88   bool is_default_view_;
89 
90   // Last brightness level that we observed, in the range [0.0, 100.0].
91   double last_percent_;
92 
93   DISALLOW_COPY_AND_ASSIGN(BrightnessView);
94 };
95 
BrightnessView(bool default_view,double initial_percent)96 BrightnessView::BrightnessView(bool default_view, double initial_percent)
97     : dragging_(false),
98       is_default_view_(default_view),
99       last_percent_(initial_percent) {
100   SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
101       kTrayPopupPaddingHorizontal, 0, kTrayPopupPaddingBetweenItems));
102 
103   views::ImageView* icon = new FixedSizedImageView(0, kTrayPopupItemHeight);
104   gfx::Image image = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
105       IDR_AURA_UBER_TRAY_BRIGHTNESS);
106   icon->SetImage(image.ToImageSkia());
107   AddChildView(icon);
108 
109   slider_ = new views::Slider(this, views::Slider::HORIZONTAL);
110   slider_->set_focus_border_color(kFocusBorderColor);
111   slider_->SetValue(static_cast<float>(initial_percent / 100.0));
112   slider_->SetAccessibleName(
113       ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
114           IDS_ASH_STATUS_TRAY_BRIGHTNESS));
115   AddChildView(slider_);
116 
117   if (is_default_view_) {
118     Shell::GetInstance()->AddShellObserver(this);
119     SetVisible(Shell::GetInstance()->maximize_mode_controller()->
120                IsMaximizeModeWindowManagerEnabled());
121   }
122 }
123 
~BrightnessView()124 BrightnessView::~BrightnessView() {
125   if (is_default_view_)
126     Shell::GetInstance()->RemoveShellObserver(this);
127 }
128 
SetBrightnessPercent(double percent)129 void BrightnessView::SetBrightnessPercent(double percent) {
130   last_percent_ = percent;
131   if (!dragging_)
132     slider_->SetValue(static_cast<float>(percent / 100.0));
133 }
134 
OnMaximizeModeStarted()135 void BrightnessView::OnMaximizeModeStarted() {
136   SetVisible(true);
137 }
138 
OnMaximizeModeEnded()139 void BrightnessView::OnMaximizeModeEnded() {
140   SetVisible(false);
141 }
142 
OnBoundsChanged(const gfx::Rect & old_bounds)143 void BrightnessView::OnBoundsChanged(const gfx::Rect& old_bounds) {
144   int w = width() - slider_->x();
145   slider_->SetSize(gfx::Size(w, slider_->height()));
146 }
147 
SliderValueChanged(views::Slider * sender,float value,float old_value,views::SliderChangeReason reason)148 void BrightnessView::SliderValueChanged(views::Slider* sender,
149                                 float value,
150                                 float old_value,
151                                 views::SliderChangeReason reason) {
152   DCHECK_EQ(sender, slider_);
153   if (reason != views::VALUE_CHANGED_BY_USER)
154     return;
155   AcceleratorController* ac = Shell::GetInstance()->accelerator_controller();
156   if (ac->brightness_control_delegate()) {
157     double percent = std::max(value * 100.0, kMinBrightnessPercent);
158     ac->brightness_control_delegate()->SetBrightnessPercent(percent, true);
159   }
160 }
161 
SliderDragStarted(views::Slider * slider)162 void BrightnessView::SliderDragStarted(views::Slider* slider) {
163   DCHECK_EQ(slider, slider_);
164   dragging_ = true;
165 }
166 
SliderDragEnded(views::Slider * slider)167 void BrightnessView::SliderDragEnded(views::Slider* slider) {
168   DCHECK_EQ(slider, slider_);
169   dragging_ = false;
170   slider_->SetValue(static_cast<float>(last_percent_ / 100.0));
171 }
172 
173 }  // namespace tray
174 
TrayBrightness(SystemTray * system_tray)175 TrayBrightness::TrayBrightness(SystemTray* system_tray)
176     : SystemTrayItem(system_tray),
177       brightness_view_(NULL),
178       current_percent_(100.0),
179       got_current_percent_(false),
180       weak_ptr_factory_(this) {
181   // Post a task to get the initial brightness; the BrightnessControlDelegate
182   // isn't created yet.
183   base::MessageLoopForUI::current()->PostTask(
184       FROM_HERE,
185       base::Bind(&TrayBrightness::GetInitialBrightness,
186                  weak_ptr_factory_.GetWeakPtr()));
187   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
188       AddObserver(this);
189 }
190 
~TrayBrightness()191 TrayBrightness::~TrayBrightness() {
192   chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
193       RemoveObserver(this);
194 }
195 
GetInitialBrightness()196 void TrayBrightness::GetInitialBrightness() {
197   BrightnessControlDelegate* delegate =
198       Shell::GetInstance()->accelerator_controller()->
199       brightness_control_delegate();
200   // Worrisome, but happens in unit tests, so don't log anything.
201   if (!delegate)
202     return;
203   delegate->GetBrightnessPercent(
204       base::Bind(&TrayBrightness::HandleInitialBrightness,
205                  weak_ptr_factory_.GetWeakPtr()));
206 }
207 
HandleInitialBrightness(double percent)208 void TrayBrightness::HandleInitialBrightness(double percent) {
209   if (!got_current_percent_)
210     HandleBrightnessChanged(percent, false);
211 }
212 
CreateTrayView(user::LoginStatus status)213 views::View* TrayBrightness::CreateTrayView(user::LoginStatus status) {
214   return NULL;
215 }
216 
CreateDefaultView(user::LoginStatus status)217 views::View* TrayBrightness::CreateDefaultView(user::LoginStatus status) {
218   CHECK(brightness_view_ == NULL);
219   brightness_view_ = new tray::BrightnessView(true, current_percent_);
220   return brightness_view_;
221 }
222 
CreateDetailedView(user::LoginStatus status)223 views::View* TrayBrightness::CreateDetailedView(user::LoginStatus status) {
224   CHECK(brightness_view_ == NULL);
225   Shell::GetInstance()->metrics()->RecordUserMetricsAction(
226       ash::UMA_STATUS_AREA_DETAILED_BRIGHTNESS_VIEW);
227   brightness_view_ = new tray::BrightnessView(false, current_percent_);
228   return brightness_view_;
229 }
230 
DestroyTrayView()231 void TrayBrightness::DestroyTrayView() {
232 }
233 
DestroyDefaultView()234 void TrayBrightness::DestroyDefaultView() {
235   if (brightness_view_ && brightness_view_->is_default_view())
236     brightness_view_ = NULL;
237 }
238 
DestroyDetailedView()239 void TrayBrightness::DestroyDetailedView() {
240   if (brightness_view_ && !brightness_view_->is_default_view())
241     brightness_view_ = NULL;
242 }
243 
UpdateAfterLoginStatusChange(user::LoginStatus status)244 void TrayBrightness::UpdateAfterLoginStatusChange(user::LoginStatus status) {
245 }
246 
ShouldHideArrow() const247 bool TrayBrightness::ShouldHideArrow() const {
248   return true;
249 }
250 
ShouldShowShelf() const251 bool TrayBrightness::ShouldShowShelf() const {
252   return false;
253 }
254 
BrightnessChanged(int level,bool user_initiated)255 void TrayBrightness::BrightnessChanged(int level, bool user_initiated) {
256   Shell::GetInstance()->metrics()->RecordUserMetricsAction(
257       ash::UMA_STATUS_AREA_BRIGHTNESS_CHANGED);
258   double percent = static_cast<double>(level);
259   HandleBrightnessChanged(percent, user_initiated);
260 }
261 
HandleBrightnessChanged(double percent,bool user_initiated)262 void TrayBrightness::HandleBrightnessChanged(double percent,
263                                              bool user_initiated) {
264   current_percent_ = percent;
265   got_current_percent_ = true;
266 
267   if (brightness_view_)
268     brightness_view_->SetBrightnessPercent(percent);
269 
270   if (!user_initiated)
271     return;
272 
273   // Never show the bubble on systems that lack internal displays: if an
274   // external display's brightness is changed, it may already display the new
275   // level via an on-screen display.
276   if (!Shell::GetInstance()->display_manager()->HasInternalDisplay())
277     return;
278 
279   if (brightness_view_)
280     SetDetailedViewCloseDelay(kTrayPopupAutoCloseDelayInSeconds);
281   else
282     PopupDetailedView(kTrayPopupAutoCloseDelayInSeconds, false);
283 }
284 
285 }  // namespace ash
286