Permalink
Browse files

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
  • Loading branch information...
1 parent d2e45cc commit 0dfd64b8b9cd293a62480c96f416797b89b9dcf8 derat@chromium.org committed Apr 30, 2012
View
@@ -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',
View
@@ -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) {
View
@@ -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_;
View
@@ -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
View
@@ -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_
@@ -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
@@ -40,6 +40,7 @@
#include "chrome/browser/chromeos/power/power_button_observer.h"
#include "chrome/browser/chromeos/power/power_state_override.h"
#include "chrome/browser/chromeos/power/resume_observer.h"
+#include "chrome/browser/chromeos/power/screen_dimming_observer.h"
#include "chrome/browser/chromeos/power/screen_lock_observer.h"
#include "chrome/browser/chromeos/power/video_property_writer.h"
#include "chrome/browser/chromeos/system/statistics_provider.h"
@@ -70,8 +71,6 @@
#include "net/url_request/url_request.h"
#include "ui/base/l10n/l10n_util.h"
-
-
class MessageLoopObserver : public MessageLoopForUI::Observer {
virtual base::EventStatus WillProcessEvent(
const base::NativeEvent& event) OVERRIDE {
@@ -439,6 +438,7 @@ void ChromeBrowserMainPartsChromeos::PostBrowserStart() {
// initialized.
power_button_observer_.reset(new chromeos::PowerButtonObserver);
video_property_writer_.reset(new chromeos::VideoPropertyWriter);
+ screen_dimming_observer_.reset(new chromeos::ScreenDimmingObserver);
ChromeBrowserMainPartsLinux::PostBrowserStart();
}
@@ -488,9 +488,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
// Let VideoPropertyWriter unregister itself as an observer of the ash::Shell
// singleton before the shell is destroyed.
video_property_writer_.reset();
- // Remove PowerButtonObserver attached to a D-Bus client before
- // DBusThreadManager is shut down.
+
+ // Detach D-Bus clients before DBusThreadManager is shut down.
power_button_observer_.reset();
+ screen_dimming_observer_.reset();
ChromeBrowserMainPartsLinux::PostMainMessageLoopRun();
}
@@ -14,6 +14,7 @@ class DesktopBackgroundObserver;
class PowerButtonObserver;
class PowerStateOverride;
class ResumeObserver;
+class ScreenDimmingObserver;
class ScreenLockObserver;
class SessionManagerObserver;
class VideoPropertyWriter;
@@ -48,6 +49,7 @@ class ChromeBrowserMainPartsChromeos : public ChromeBrowserMainPartsLinux {
scoped_ptr<chromeos::PowerButtonObserver> power_button_observer_;
scoped_ptr<chromeos::PowerStateOverride> power_state_override_;
scoped_ptr<chromeos::VideoPropertyWriter> video_property_writer_;
+ scoped_ptr<chromeos::ScreenDimmingObserver> screen_dimming_observer_;
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainPartsChromeos);
};
@@ -0,0 +1,26 @@
+// 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 "chrome/browser/chromeos/power/screen_dimming_observer.h"
+
+#include "ash/shell.h"
+#include "ash/wm/screen_dimmer.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+
+namespace chromeos {
+
+ScreenDimmingObserver::ScreenDimmingObserver() {
+ DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
+}
+
+ScreenDimmingObserver::~ScreenDimmingObserver() {
+ DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
+}
+
+void ScreenDimmingObserver::ScreenDimmingRequested(ScreenDimmingState state) {
+ ash::Shell::GetInstance()->screen_dimmer()->SetDimming(
+ state == PowerManagerClient::Observer::SCREEN_DIMMING_IDLE);
+}
+
+} // namespace chromeos
@@ -0,0 +1,32 @@
+// 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 CHROME_BROWSER_CHROMEOS_POWER_SCREEN_DIMMING_OBSERVER_H_
+#define CHROME_BROWSER_CHROMEOS_POWER_SCREEN_DIMMING_OBSERVER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chromeos/dbus/power_manager_client.h"
+
+namespace chromeos {
+
+// Listens for requests to enable or disable dimming of the screen in software
+// (as opposed to by adjusting a backlight).
+class ScreenDimmingObserver : public PowerManagerClient::Observer {
+ public:
+ // This class registers/unregisters itself as an observer in ctor/dtor.
+ ScreenDimmingObserver();
+ virtual ~ScreenDimmingObserver();
+
+ private:
+ // PowerManagerClient::Observer implementation.
+ virtual void ScreenDimmingRequested(ScreenDimmingState state) OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenDimmingObserver);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_POWER_SCREEN_DIMMING_OBSERVER_H_
Oops, something went wrong.

0 comments on commit 0dfd64b

Please sign in to comment.