Skip to content
This repository has been archived by the owner on Sep 25, 2019. It is now read-only.

Commit

Permalink
chromeos: Add support for dimming the screen.
Browse files Browse the repository at this point in the history
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
derat@chromium.org committed Apr 30, 2012
1 parent d2e45cc commit 0dfd64b
Show file tree
Hide file tree
Showing 13 changed files with 329 additions and 5 deletions.
3 changes: 3 additions & 0 deletions ash/ash.gyp
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
3 changes: 3 additions & 0 deletions ash/shell.cc
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand Down
5 changes: 5 additions & 0 deletions ash/shell.h
Expand Up @@ -77,6 +77,7 @@ class PartialScreenshotEventFilter;
class ResizeShadowController;
class RootWindowEventFilter;
class RootWindowLayoutManager;
class ScreenDimmer;
class ShadowController;
class ShelfLayoutManager;
class ShellContextMenu;
Expand Down Expand Up @@ -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(); }

Expand Down Expand Up @@ -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_;
Expand Down
66 changes: 66 additions & 0 deletions 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
67 changes: 67 additions & 0 deletions 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_
78 changes: 78 additions & 0 deletions 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
9 changes: 5 additions & 4 deletions chrome/browser/chromeos/chrome_browser_main_chromeos.cc
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
}
2 changes: 2 additions & 0 deletions chrome/browser/chromeos/chrome_browser_main_chromeos.h
Expand Up @@ -14,6 +14,7 @@ class DesktopBackgroundObserver;
class PowerButtonObserver;
class PowerStateOverride;
class ResumeObserver;
class ScreenDimmingObserver;
class ScreenLockObserver;
class SessionManagerObserver;
class VideoPropertyWriter;
Expand Down Expand Up @@ -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);
};
Expand Down
26 changes: 26 additions & 0 deletions chrome/browser/chromeos/power/screen_dimming_observer.cc
@@ -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
32 changes: 32 additions & 0 deletions chrome/browser/chromeos/power/screen_dimming_observer.h
@@ -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_

0 comments on commit 0dfd64b

Please sign in to comment.