diff options
author | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-30 23:42:04 +0000 |
---|---|---|
committer | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-30 23:42:04 +0000 |
commit | 429932192b1e0afc28a9f9de1519d98baf04b269 (patch) | |
tree | 1a4dde1612e9501c8bad7bce1fd05b5b7f68bd1e /ash | |
parent | 5f4ed93da5d14f807a7db2f43d1afe62438a67cd (diff) | |
download | chromium_src-429932192b1e0afc28a9f9de1519d98baf04b269.zip chromium_src-429932192b1e0afc28a9f9de1519d98baf04b269.tar.gz chromium_src-429932192b1e0afc28a9f9de1519d98baf04b269.tar.bz2 |
chromeos: Add support for dimming the screen.
This makes Chrome listen for messages from the power manager
asking it to dim or undim the screen. We'll use this on
desktop devices with external displays to dim the screen
just before blanking it when the user is idle.
BUG=125176
TEST=added, also did manual testing with powerd changes
Review URL: http://codereview.chromium.org/10263011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134638 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r-- | ash/ash.gyp | 3 | ||||
-rw-r--r-- | ash/shell.cc | 3 | ||||
-rw-r--r-- | ash/shell.h | 5 | ||||
-rw-r--r-- | ash/wm/screen_dimmer.cc | 66 | ||||
-rw-r--r-- | ash/wm/screen_dimmer.h | 67 | ||||
-rw-r--r-- | ash/wm/screen_dimmer_unittest.cc | 78 |
6 files changed, 222 insertions, 0 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index 34a97b6..f4014ea 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -231,6 +231,8 @@ 'wm/root_window_layout_manager.cc', 'wm/root_window_layout_manager.h', 'wm/scoped_observer.h', + 'wm/screen_dimmer.cc', + 'wm/screen_dimmer.h', 'wm/shadow.cc', 'wm/shadow.h', 'wm/shadow_controller.cc', @@ -375,6 +377,7 @@ 'wm/panel_layout_manager_unittest.cc', 'wm/power_button_controller_unittest.cc', 'wm/root_window_event_filter_unittest.cc', + 'wm/screen_dimmer_unittest.cc', 'wm/shadow_controller_unittest.cc', 'wm/shelf_layout_manager_unittest.cc', 'wm/system_gesture_event_filter_unittest.cc', diff --git a/ash/shell.cc b/ash/shell.cc index dcf4761..3aab8a5 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -41,6 +41,7 @@ #include "ash/wm/resize_shadow_controller.h" #include "ash/wm/root_window_event_filter.h" #include "ash/wm/root_window_layout_manager.h" +#include "ash/wm/screen_dimmer.h" #include "ash/wm/shadow_controller.h" #include "ash/wm/shelf_layout_manager.h" #include "ash/wm/stacking_controller.h" @@ -575,6 +576,7 @@ Shell::~Shell() { drag_drop_controller_.reset(); magnification_controller_.reset(); resize_shadow_controller_.reset(); + screen_dimmer_.reset(); shadow_controller_.reset(); window_cycle_controller_.reset(); event_client_.reset(); @@ -727,6 +729,7 @@ void Shell::Init() { video_detector_.reset(new VideoDetector); window_cycle_controller_.reset(new WindowCycleController); monitor_controller_.reset(new internal::MonitorController); + screen_dimmer_.reset(new internal::ScreenDimmer); } aura::Window* Shell::GetContainer(int container_id) { diff --git a/ash/shell.h b/ash/shell.h index 38fb751..2f47db3 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -77,6 +77,7 @@ class PartialScreenshotEventFilter; class ResizeShadowController; class RootWindowEventFilter; class RootWindowLayoutManager; +class ScreenDimmer; class ShadowController; class ShelfLayoutManager; class ShellContextMenu; @@ -236,6 +237,9 @@ class ASH_EXPORT Shell { internal::MagnificationController* magnification_controller() { return magnification_controller_.get(); } + internal::ScreenDimmer* screen_dimmer() { + return screen_dimmer_.get(); + } Launcher* launcher() { return launcher_.get(); } @@ -339,6 +343,7 @@ class ASH_EXPORT Shell { scoped_ptr<internal::EventClientImpl> event_client_; scoped_ptr<internal::MonitorController> monitor_controller_; scoped_ptr<internal::MagnificationController> magnification_controller_; + scoped_ptr<internal::ScreenDimmer> screen_dimmer_; // An event filter that rewrites or drops a key event. scoped_ptr<internal::KeyRewriterEventFilter> key_rewriter_filter_; diff --git a/ash/wm/screen_dimmer.cc b/ash/wm/screen_dimmer.cc new file mode 100644 index 0000000..b902de0 --- /dev/null +++ b/ash/wm/screen_dimmer.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2012 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. + +#include "ash/wm/screen_dimmer.h" + +#include "ash/shell.h" +#include "base/time.h" +#include "ui/aura/root_window.h" +#include "ui/gfx/compositor/layer.h" +#include "ui/gfx/compositor/scoped_layer_animation_settings.h" +#include "ui/gfx/rect.h" +#include "ui/gfx/size.h" + +namespace ash { +namespace internal { + +namespace { + +// Opacity for |dimming_layer_| when it's dimming the screen. +const float kDimmingLayerOpacity = 0.4f; + +// Duration for dimming animations, in milliseconds. +const int kDimmingTransitionMs = 200; + +} // namespace + +ScreenDimmer::ScreenDimmer() : currently_dimming_(false) { + Shell::GetInstance()->GetRootWindow()->AddRootWindowObserver(this); +} + +ScreenDimmer::~ScreenDimmer() { + Shell::GetInstance()->GetRootWindow()->RemoveRootWindowObserver(this); +} + +void ScreenDimmer::SetDimming(bool should_dim) { + if (should_dim == currently_dimming_) + return; + + if (!dimming_layer_.get()) { + dimming_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); + dimming_layer_->SetColor(SK_ColorBLACK); + dimming_layer_->SetOpacity(0.0f); + ui::Layer* root_layer = Shell::GetRootWindow()->layer(); + dimming_layer_->SetBounds(root_layer->bounds()); + root_layer->Add(dimming_layer_.get()); + root_layer->StackAtTop(dimming_layer_.get()); + } + + currently_dimming_ = should_dim; + + ui::ScopedLayerAnimationSettings scoped_settings( + dimming_layer_->GetAnimator()); + scoped_settings.SetTransitionDuration( + base::TimeDelta::FromMilliseconds(kDimmingTransitionMs)); + dimming_layer_->SetOpacity(should_dim ? kDimmingLayerOpacity : 0.0f); +} + +void ScreenDimmer::OnRootWindowResized(const aura::RootWindow* root, + const gfx::Size& old_size) { + if (dimming_layer_.get()) + dimming_layer_->SetBounds(gfx::Rect(root->bounds().size())); +} + +} // namespace internal +} // namespace ash diff --git a/ash/wm/screen_dimmer.h b/ash/wm/screen_dimmer.h new file mode 100644 index 0000000..2415b58 --- /dev/null +++ b/ash/wm/screen_dimmer.h @@ -0,0 +1,67 @@ +// Copyright (c) 2012 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. + +#ifndef ASH_WM_SCREEN_DIMMER_H_ +#define ASH_WM_SCREEN_DIMMER_H_ +#pragma once + +#include "ash/ash_export.h" +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "ui/aura/root_window_observer.h" + +namespace ui { +class Layer; +} + +namespace ash { +namespace internal { + +// ScreenDimmer displays a partially-opaque layer above everything else to +// darken the screen. It shouldn't be used for long-term brightness adjustments +// due to performance considerations -- it's only intended for cases where we +// want to briefly dim the screen (e.g. to indicate to the user that we're about +// to suspend a machine that lacks an internal backlight that can be adjusted). +class ASH_EXPORT ScreenDimmer : public aura::RootWindowObserver { + public: + class TestApi { + public: + explicit TestApi(ScreenDimmer* dimmer) : dimmer_(dimmer) {} + + ui::Layer* layer() { return dimmer_->dimming_layer_.get(); } + + private: + ScreenDimmer* dimmer_; // not owned + + DISALLOW_COPY_AND_ASSIGN(TestApi); + }; + + ScreenDimmer(); + virtual ~ScreenDimmer(); + + // Dim or undim the screen. + void SetDimming(bool should_dim); + + // aura::RootWindowObserver overrides: + virtual void OnRootWindowResized(const aura::RootWindow* root, + const gfx::Size& old_size) OVERRIDE; + + private: + friend class TestApi; + + // Partially-opaque layer that's stacked above all of the root window's + // children and used to dim the screen. NULL until the first time we dim. + scoped_ptr<ui::Layer> dimming_layer_; + + // Are we currently dimming the screen? + bool currently_dimming_; + + DISALLOW_COPY_AND_ASSIGN(ScreenDimmer); +}; + +} // namespace internal +} // namespace ash + +#endif // ASH_WM_SCREEN_DIMMER_H_ diff --git a/ash/wm/screen_dimmer_unittest.cc b/ash/wm/screen_dimmer_unittest.cc new file mode 100644 index 0000000..b66cd2f --- /dev/null +++ b/ash/wm/screen_dimmer_unittest.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2012 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. + +#include "ash/wm/screen_dimmer.h" + +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "ui/aura/root_window.h" +#include "ui/gfx/compositor/layer.h" + +namespace ash { +namespace test { + +class ScreenDimmerTest : public AshTestBase { + public: + ScreenDimmerTest() : dimmer_(NULL) {} + virtual ~ScreenDimmerTest() {} + + void SetUp() OVERRIDE { + AshTestBase::SetUp(); + dimmer_ = Shell::GetInstance()->screen_dimmer(); + test_api_.reset(new internal::ScreenDimmer::TestApi(dimmer_)); + } + + protected: + internal::ScreenDimmer* dimmer_; // not owned + + scoped_ptr<internal::ScreenDimmer::TestApi> test_api_; + + private: + DISALLOW_COPY_AND_ASSIGN(ScreenDimmerTest); +}; + +TEST_F(ScreenDimmerTest, DimAndUndim) { + // Don't create a layer until we need to. + EXPECT_TRUE(test_api_->layer() == NULL); + dimmer_->SetDimming(false); + EXPECT_TRUE(test_api_->layer() == NULL); + + // When we enable dimming, the layer should be created and stacked at the top + // of the root's children. + dimmer_->SetDimming(true); + ASSERT_TRUE(test_api_->layer() != NULL); + ui::Layer* root_layer = Shell::GetInstance()->GetRootWindow()->layer(); + ASSERT_TRUE(!root_layer->children().empty()); + EXPECT_EQ(test_api_->layer(), root_layer->children().back()); + EXPECT_TRUE(test_api_->layer()->visible()); + EXPECT_GT(test_api_->layer()->GetTargetOpacity(), 0.0f); + + // When we disable dimming, the layer should be animated back to full + // transparency. + dimmer_->SetDimming(false); + ASSERT_TRUE(test_api_->layer() != NULL); + EXPECT_TRUE(test_api_->layer()->visible()); + EXPECT_FLOAT_EQ(0.0f, test_api_->layer()->GetTargetOpacity()); +} + +TEST_F(ScreenDimmerTest, ResizeLayer) { + // The dimming layer should be initially sized to cover the root window. + dimmer_->SetDimming(true); + ui::Layer* dimming_layer = test_api_->layer(); + ASSERT_TRUE(dimming_layer != NULL); + ui::Layer* root_layer = Shell::GetInstance()->GetRootWindow()->layer(); + EXPECT_EQ(gfx::Rect(root_layer->bounds().size()).ToString(), + dimming_layer->bounds().ToString()); + + // When we resize the root window, the dimming layer should be resized to + // match. + gfx::Size kNewSize(400, 300); + Shell::GetInstance()->GetRootWindow()->SetHostSize(kNewSize); + EXPECT_EQ(kNewSize.ToString(), dimming_layer->bounds().size().ToString()); +} + +} // namespace test +} // namespace ash |