15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/rotator/screen_rotation.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/layer.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/interpolated_transform.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/transform.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int k90DegreeTransitionDurationMs = 350; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int k180DegreeTransitionDurationMs = 550; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int k360DegreeTransitionDurationMs = 750; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::TimeDelta GetTransitionDuration(int degrees) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (degrees == 360) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::TimeDelta::FromMilliseconds(k360DegreeTransitionDurationMs); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (degrees == 180) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::TimeDelta::FromMilliseconds(k180DegreeTransitionDurationMs); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (degrees == 0) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::TimeDelta::FromMilliseconds(0); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::TimeDelta::FromMilliseconds(k90DegreeTransitionDurationMs); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScreenRotation::ScreenRotation(int degrees, ui::Layer* layer) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : ui::LayerAnimationElement(LayerAnimationElement::TRANSFORM, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTransitionDuration(degrees)), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) degrees_(degrees) { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InitTransform(layer); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScreenRotation::~ScreenRotation() { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScreenRotation::InitTransform(ui::Layer* layer) { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No rotation required, use the identity transform. 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (degrees_ == 0) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) interpolated_transform_.reset( 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new ui::InterpolatedConstantTransform(gfx::Transform())); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use the target transform/bounds in case the layer is already animating. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Transform& current_transform = layer->GetTargetTransform(); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect& bounds = layer->GetTargetBounds(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point old_pivot; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point new_pivot; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width = bounds.width(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int height = bounds.height(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (degrees_) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 90: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_origin_ = new_pivot = gfx::Point(width, 0); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case -90: 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_origin_ = new_pivot = gfx::Point(0, height); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 180: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 360: 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_pivot = old_pivot = gfx::Point(width / 2, height / 2); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_origin_.SetPoint(width, height); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert points to world space. 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) current_transform.TransformPoint(&old_pivot); 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) current_transform.TransformPoint(&new_pivot); 78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) current_transform.TransformPoint(&new_origin_); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ui::InterpolatedTransform> rotation( 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ui::InterpolatedTransformAboutPivot( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_pivot, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ui::InterpolatedRotation(0, degrees_))); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ui::InterpolatedTransform> translation( 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ui::InterpolatedTranslation( 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(0, 0), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point(new_pivot.x() - old_pivot.x(), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_pivot.y() - old_pivot.y()))); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scale_factor = 0.9f; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ui::InterpolatedTransform> scale_down( 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ui::InterpolatedScale(1.0f, scale_factor, 0.0f, 0.5f)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ui::InterpolatedTransform> scale_up( 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ui::InterpolatedScale(1.0f, 1.0f / scale_factor, 0.5f, 1.0f)); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interpolated_transform_.reset( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ui::InterpolatedConstantTransform(current_transform)); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale_up->SetChild(scale_down.release()); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translation->SetChild(scale_up.release()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rotation->SetChild(translation.release()); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interpolated_transform_->SetChild(rotation.release()); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScreenRotation::OnStart(ui::LayerAnimationDelegate* delegate) { 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ScreenRotation::OnProgress(double t, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::LayerAnimationDelegate* delegate) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate->SetTransformFromAnimation(interpolated_transform_->Interpolate(t)); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScreenRotation::OnGetTarget(TargetValue* target) const { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target->transform = interpolated_transform_->Interpolate(1.0); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScreenRotation::OnAbort(ui::LayerAnimationDelegate* delegate) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ash 124