Commit e1402f87 authored by vollick@chromium.org's avatar vollick@chromium.org

Restore chrome/browser/ui/touch/animation/*

Fix BrowserThread bug.

BUG=None
TEST=Linux touch build succeeds.

Review URL: http://codereview.chromium.org/8400062

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107728 0039d316-1c4b-4281-b951-d872f2087c98
parent 3b78b67c
......@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "chrome/browser/chromeos/system/runtime_environment.h"
#include "content/browser/browser_thread.h"
#include "content/public/browser/browser_thread.h"
#include "content/browser/sensors/sensors_provider.h"
#include "dbus/bus.h"
#include "dbus/message.h"
......
// Copyright (c) 2011 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/ui/touch/animation/screen_rotation.h"
#include "base/debug/trace_event.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "ui/base/animation/slide_animation.h"
#include "ui/gfx/compositor/layer.h"
#include "ui/gfx/interpolated_transform.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"
#include "views/paint_lock.h"
#include "views/view.h"
#include "views/widget/widget.h"
namespace {
const int kDefaultTransitionDurationMs = 350;
} // namespace
////////////////////////////////////////////////////////////////////////////////
// ScreenRotationListener public:
//
ScreenRotationListener::~ScreenRotationListener() {
}
////////////////////////////////////////////////////////////////////////////////
// ScreenRotation public:
//
ScreenRotation::ScreenRotation(views::View* view,
ScreenRotationListener* listener,
float old_degrees,
float new_degrees)
: view_(view),
widget_(view->GetWidget()),
listener_(listener),
old_degrees_(old_degrees),
new_degrees_(new_degrees),
duration_(kDefaultTransitionDurationMs),
animation_started_(false),
animation_stopped_(false) {
DCHECK(view);
DCHECK(listener);
if (!view->layer() || !widget_) {
Finalize();
} else {
// Screen rotations are trigged as a result of a call to SetTransform which
// causes a paint to be scheduled to occur. At this point, the paint has
// been scheduled, but has not yet been started. We will listen for this
// paint to be completed before we start animating.
view->layer()->GetCompositor()->AddObserver(this);
}
}
ScreenRotation::~ScreenRotation() {
if (view_->layer())
view_->layer()->GetCompositor()->RemoveObserver(this);
}
void ScreenRotation::Stop() {
animation_.reset();
if (view_->layer()) {
if (!interpolated_transform_.get()) {
// attempt to initialize.
Init();
}
if (interpolated_transform_.get()) {
view_->layer()->SetTransform(interpolated_transform_->Interpolate(1.0));
view_->GetWidget()->SchedulePaintInRect(
view_->GetWidget()->GetClientAreaScreenBounds());
}
}
Finalize();
}
////////////////////////////////////////////////////////////////////////////////
// ScreenRotation private:
//
void ScreenRotation::AnimationProgressed(const ui::Animation* anim) {
TRACE_EVENT0("ScreenRotation", "step");
view_->layer()->SetTransform(interpolated_transform_->Interpolate(
anim->GetCurrentValue()));
widget_->SchedulePaintInRect(widget_->GetClientAreaScreenBounds());
}
void ScreenRotation::AnimationEnded(const ui::Animation* anim) {
TRACE_EVENT_END0("ScreenRotation", "ScreenRotation");
// TODO(vollick) massage matrix so that entries sufficiently close
// to 0, 1, or -1 are clamped to these values. The idea is to fight
// accumulated numeric error due to successive rotations.
ui::Transform xform = view_->layer()->transform();
gfx::Point origin;
xform.TransformPoint(origin);
ui::Transform translation;
translation.SetTranslate(new_origin_.x() - origin.x(),
new_origin_.y() - origin.y());
xform.ConcatTransform(translation);
view_->layer()->SetTransform(xform);
widget_->SchedulePaintInRect(widget_->GetClientAreaScreenBounds());
animation_stopped_ = true;
}
void ScreenRotation::OnCompositingEnded(ui::Compositor* compositor) {
DoPendingWork();
}
void ScreenRotation::Init() {
TRACE_EVENT0("ScreenRotation", "init");
ui::Transform current_transform = view_->layer()->transform();
int degrees = new_degrees_ - old_degrees_;
degrees = NormalizeAngle(degrees);
// No rotation required.
if (degrees == 0)
return;
gfx::Point old_pivot;
gfx::Point new_pivot;
int width = view_->layer()->bounds().width();
int height = view_->layer()->bounds().height();
switch (degrees) {
case 90:
new_origin_ = new_pivot = gfx::Point(width, 0);
new_size_.SetSize(height, width);
break;
case -90:
new_origin_ = new_pivot = gfx::Point(0, height);
new_size_.SetSize(height, width);
break;
case 180:
duration_ = 550;
new_pivot = old_pivot = gfx::Point(width / 2, height / 2);
new_origin_.SetPoint(width, height);
new_size_.SetSize(width, height);
break;
}
// Convert points to world space.
current_transform.TransformPoint(old_pivot);
current_transform.TransformPoint(new_pivot);
current_transform.TransformPoint(new_origin_);
scoped_ptr<ui::InterpolatedTransform> rotation(
new ui::InterpolatedTransformAboutPivot(
old_pivot,
new ui::InterpolatedRotation(0, degrees)));
scoped_ptr<ui::InterpolatedTransform> translation(
new ui::InterpolatedTranslation(
gfx::Point(0, 0),
gfx::Point(new_pivot.x() - old_pivot.x(),
new_pivot.y() - old_pivot.y())));
float scale_factor = 0.9f;
scoped_ptr<ui::InterpolatedTransform> scale_down(
new ui::InterpolatedScale(1.0f, scale_factor, 0.0f, 0.5f));
scoped_ptr<ui::InterpolatedTransform> scale_up(
new ui::InterpolatedScale(1.0f, 1.0f / scale_factor, 0.5f, 1.0f));
interpolated_transform_.reset(
new ui::InterpolatedConstantTransform(current_transform));
scale_up->SetChild(scale_down.release());
translation->SetChild(scale_up.release());
rotation->SetChild(translation.release());
interpolated_transform_->SetChild(rotation.release());
}
void ScreenRotation::Start() {
TRACE_EVENT_BEGIN0("ScreenRotation", "ScreenRotation");
Init();
if (interpolated_transform_.get()) {
paint_lock_.reset(new views::PaintLock(view_));
animation_.reset(new ui::SlideAnimation(this));
animation_->SetTweenType(ui::Tween::LINEAR);
animation_->SetSlideDuration(duration_);
animation_->Show();
animation_started_ = true;
} else {
Finalize();
}
}
void ScreenRotation::Finalize() {
ui::Transform final_transform = view_->GetTransform();
gfx::Rect final_bounds(0, 0, new_size_.width(), new_size_.height());
listener_->OnScreenRotationCompleted(final_transform, final_bounds);
}
int ScreenRotation::NormalizeAngle(int degrees) {
while (degrees <= -180) degrees += 360;
while (degrees > 180) degrees -= 360;
return degrees;
}
void ScreenRotation::DoPendingWork() {
if (!animation_started_)
Start();
else if (animation_stopped_) {
view_->layer()->GetCompositor()->RemoveObserver(this);
Finalize();
}
}
// Copyright (c) 2011 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_UI_TOUCH_ANIMATION_SCREEN_ROTATION_H_
#define CHROME_BROWSER_UI_TOUCH_ANIMATION_SCREEN_ROTATION_H_
#pragma once
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/bind.h"
#include "ui/base/animation/animation_delegate.h"
#include "ui/gfx/compositor/compositor_observer.h"
#include "ui/gfx/point.h"
#include "ui/gfx/size.h"
namespace ui {
class InterpolatedTransform;
class Layer;
class SlideAnimation;
class Transform;
}
namespace gfx {
class Rect;
}
namespace views {
class PaintLock;
class View;
class Widget;
}
// Classes that wish to be notified when a screen rotation completes must
// implement the screen rotation listener interface.
class ScreenRotationListener {
public:
virtual void OnScreenRotationCompleted(const ui::Transform& target_transform,
const gfx::Rect& target_bounds) = 0;
protected:
virtual ~ScreenRotationListener();
};
// A screen rotation represents a single transition from one screen orientation
// to another. The intended usage is that a new instance of the class is
// created for every transition. It is possible to update the target orientation
// in the middle of a transition.
class ScreenRotation : public ui::AnimationDelegate,
public ui::CompositorObserver {
public:
// The screen rotation does not own the view or the listener, and these
// objects are required to outlive the Screen rotation object.
ScreenRotation(views::View* view,
ScreenRotationListener* listener,
float old_degrees,
float new_degrees);
virtual ~ScreenRotation();
// Aborts the animation by skipping to the end and applying the final
// transform before calling |Finalize|.
void Stop();
private:
// Implementation of ui::AnimationDelegate
virtual void AnimationEnded(const ui::Animation* anim) OVERRIDE;
virtual void AnimationProgressed(const ui::Animation* anim) OVERRIDE;
// Implementation of ui::CompositorObserver
void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE;
// Initializes |interpolated_transform_|, |new_origin_|, |new_size_|, and
// (if it has not already been initialized) |old_transform_|
void Init();
// Initializes the screen rotation and starts |animation_|.
void Start();
// Called after the animation is finished and the view has completed painting
// in its final state.
void Finalize();
// Converts degrees to an angle in the range [-180, 180).
int NormalizeAngle(int degrees);
// We occasionally need to wait for a paint to finish before progressing.
// This function (which is triggered by OnPainted and OnComposited) does
// any pending work.
void DoPendingWork();
// This is the view that will be animated. The animation will operate mainly
// on |view_|'s layer, but it is used upon completion of the rotation to
// update the bounds.
views::View* view_;
// This widget will be used for scheduling paints.
views::Widget* widget_;
// A ScreenRotation may be associated with a listener that is notified when
// the screen rotation completes.
ScreenRotationListener* listener_;
// The animation object that instigates stepping of the animation.
scoped_ptr<ui::SlideAnimation> animation_;
// Generates the intermediate transformation matrices used during the
// animation.
scoped_ptr<ui::InterpolatedTransform> interpolated_transform_;
// Ensures that the view is not repainted during the screen rotation.
scoped_ptr<views::PaintLock> paint_lock_;
// The original orientation (not updated by |SetTarget|.
float old_degrees_;
// The target orientation.
float new_degrees_;
// The target size for |view_|
gfx::Size new_size_;
// The target origin for |view_|
gfx::Point new_origin_;
// This is the duration of the transition in milliseconds
int duration_;
// These are used by DoPendingWork to decide what needs to be done.
bool animation_started_;
bool animation_stopped_;
DISALLOW_COPY_AND_ASSIGN(ScreenRotation);
};
#endif // CHROME_BROWSER_UI_TOUCH_ANIMATION_SCREEN_ROTATION_H_
// Copyright (c) 2011 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/ui/touch/animation/screen_rotation_setter.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/touch/animation/screen_rotation.h"
#include "ui/gfx/compositor/layer.h"
#include "ui/gfx/interpolated_transform.h"
#include "views/layer_property_setter.h"
#include "views/view.h"
namespace {
static int SymmetricRound(float x) {
return static_cast<int>(
x > 0
? std::floor(x + 0.5f)
: std::ceil(x - 0.5f));
}
// A screen rotation setter is a LayerPropertySetter that initiates screen
// rotations in response to calls to |SetTransform|. Calls to |SetBounds| are
// applied to the layer immediately.
class ScreenRotationSetter : public views::LayerPropertySetter,
public ScreenRotationListener {
public:
explicit ScreenRotationSetter(views::View* view);
// implementation of LayerPropertySetter
virtual void Installed(ui::Layer* layer) OVERRIDE;
virtual void Uninstalled(ui::Layer* layer) OVERRIDE;
virtual void SetTransform(ui::Layer* layer,
const ui::Transform& transform) OVERRIDE;
virtual void SetBounds(ui::Layer* layer, const gfx::Rect& bounds) OVERRIDE;
// implementation of ScreenRotationListener
virtual void OnScreenRotationCompleted(const ui::Transform& final_transform,
const gfx::Rect& final_rect) OVERRIDE;
private:
// This is the currently animating rotation. We hang onto it so that if a
// call to |SetTransform| is made during the rotation, we can update the
// target orientation of this rotation.
scoped_ptr<ScreenRotation> rotation_;
// If a call to SetBounds happens during a rotation its effect is delayed
// until the rotation completes. If this happens several times, only the last
// call to SetBounds will have any effect.
scoped_ptr<gfx::Rect> pending_bounds_;
// If a call to SetTransform happens during a rotation its effect is delayed
// until the rotation completes. If this happens several times, only the last
// call to SetTransform will have any effect.
scoped_ptr<ui::Transform> pending_transform_;
// The screen rotation setter is associated with a view so that the view's
// bounds may be set when the animation completes.
views::View* view_;
DISALLOW_COPY_AND_ASSIGN(ScreenRotationSetter);
};
ScreenRotationSetter::ScreenRotationSetter(views::View* view) : view_(view) {
}
void ScreenRotationSetter::Installed(ui::Layer* layer) OVERRIDE {
}
void ScreenRotationSetter::Uninstalled(ui::Layer* layer) OVERRIDE {
if (rotation_.get())
rotation_->Stop();
}
void ScreenRotationSetter::SetTransform(ui::Layer* layer,
const ui::Transform& transform) {
if (rotation_.get()) {
pending_transform_.reset(new ui::Transform(transform));
} else {
float new_degrees, old_degrees;
if (ui::InterpolatedTransform::FactorTRS(transform,
NULL, &new_degrees, NULL) &&
ui::InterpolatedTransform::FactorTRS(layer->transform(),
NULL, &old_degrees, NULL)) {
rotation_.reset(new ScreenRotation(view_,
this,
SymmetricRound(old_degrees),
SymmetricRound(new_degrees)));
}
}
}
void ScreenRotationSetter::SetBounds(ui::Layer* layer,
const gfx::Rect& bounds) {
// cache bounds changes during an animation.
if (rotation_.get())
pending_bounds_.reset(new gfx::Rect(bounds));
else
layer->SetBounds(bounds);
}
void ScreenRotationSetter::OnScreenRotationCompleted(
const ui::Transform& final_transform,
const gfx::Rect& final_bounds) {
// destroy the animation.
rotation_.reset();
if (pending_bounds_.get() && view_->layer()) {
// If there are any pending bounds changes, they will have already been
// applied to the view, and are waiting to be applied to the layer.
view_->layer()->SetBounds(*pending_bounds_);
pending_bounds_.reset();
} else if (!final_bounds.IsEmpty()) {
// Otherwise we may have new bounds as the result of the completed screen
// rotation. Apply these to the view.
view_->SetBoundsRect(final_bounds);
}
if (pending_transform_.get() && view_->layer()) {
// If there is a pending transformation, we need to initiate another
// animation.
SetTransform(view_->layer(), *pending_transform_);
pending_transform_.reset();
}
}
} // namespace
views::LayerPropertySetter* ScreenRotationSetterFactory::Create(
views::View* view) {
return new ScreenRotationSetter(view);
}
// Copyright (c) 2011 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_UI_TOUCH_ANIMATION_SCREEN_ROTATION_SETTER_H_
#define CHROME_BROWSER_UI_TOUCH_ANIMATION_SCREEN_ROTATION_SETTER_H_
#pragma once
#include "views/layer_property_setter.h"
namespace views {
class View;
}
class ScreenRotationSetterFactory {
public:
// The setter will not own the view, and it is required that the view
// outlive the setter.
static views::LayerPropertySetter* Create(views::View* view);
};
#endif // CHROME_BROWSER_UI_TOUCH_ANIMATION_SCREEN_ROTATION_SETTER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment