Chromium Code Reviews| Index: chrome/browser/ui/touch/frame/touch_browser_frame_view.cc |
| diff --git a/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc b/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc |
| index b1ae5b4e448f79eb5900b069d3b4ab81d56e0130..d771ed8df53550bedd967658bad8f013004a7a1c 100644 |
| --- a/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc |
| +++ b/chrome/browser/ui/touch/frame/touch_browser_frame_view.cc |
| @@ -4,6 +4,7 @@ |
| #include "chrome/browser/ui/touch/frame/touch_browser_frame_view.h" |
| +#include "base/debug/trace_event.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/renderer_host/render_widget_host_view_views.h" |
| #include "chrome/browser/tabs/tab_strip_model.h" |
| @@ -20,7 +21,7 @@ |
| #include "content/common/content_notification_types.h" |
| #include "content/common/notification_service.h" |
| #include "content/common/view_messages.h" |
| -#include "ui/base/animation/slide_animation.h" |
| +#include "ui/gfx/interpolated_transform.h" |
| #include "ui/gfx/rect.h" |
| #include "ui/gfx/transform.h" |
| #include "views/controls/button/image_button.h" |
| @@ -48,6 +49,141 @@ bool TabContentsHasFocus(const TabContents* contents) { |
| } // namespace |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// Animation |
| + |
| +class TouchBrowserFrameRotation : public ui::AnimationDelegate { |
|
sadrul
2011/07/15 15:25:48
This probably should be in the anonymous namespace
|
| + public: |
| + static void Perform(views::View* root, |
| + sensors::ScreenOrientation::Side oldUp, |
| + sensors::ScreenOrientation::Side newUp) { |
| + new TouchBrowserFrameRotation(root, oldUp, newUp); |
| + } |
| + |
| + private: |
| + TouchBrowserFrameRotation(views::View* root, |
| + sensors::ScreenOrientation::Side old_up, |
| + sensors::ScreenOrientation::Side new_up) |
| + : root_(root), |
|
sadrul
2011/07/15 15:25:48
4-space indent
|
| + old_up_(old_up), |
| + new_up_(new_up) { |
| + animation_.reset(new ui::SlideAnimation(this)); |
| + animation_->SetTweenType(ui::Tween::LINEAR); |
| + animation_->SetSlideDuration(1000); |
| + Start(); |
| + } |
| + |
| + virtual void AnimationProgressed(const ui::Animation* anim) OVERRIDE { |
| + if (!interpolated_transform_.get()) |
| + return; |
| + |
| + float t = static_cast<float>(anim->GetCurrentValue()); |
| + root_->SetTransform(interpolated_transform_->Interpolate(t)); |
| + root_->ScheduleComposite(); |
| + } |
| + |
| + virtual void AnimationEnded(const ui::Animation* anim) OVERRIDE { |
| + TRACE_EVENT_END0("RotateAnimation", "Start rotating"); |
| + // 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 = root_->GetTransform(); |
| + gfx::Point origin; |
| + xform.TransformPoint(origin); |
| + ui::Transform translation; |
| + translation.SetTranslate(new_origin_.x() - origin.x(), |
| + new_origin_.y() - origin.y()); |
| + xform.ConcatTransform(translation); |
| + root_->SetTransform(xform); |
| + root_->SetBounds(0, 0, new_size_.width(), new_size_.height()); |
| + root_->SetPaintingEnabled(true); |
| + root_->SchedulePaint(); |
| + delete this; |
| + } |
| + |
| + int SideToDegrees(sensors::ScreenOrientation::Side side) { |
| + switch (side) { |
| + case sensors::ScreenOrientation::RIGHT: return 90; |
|
sadrul
2011/07/15 15:25:48
indentations!
|
| + case sensors::ScreenOrientation::LEFT: return -90; |
| + case sensors::ScreenOrientation::BOTTOM: return 180; |
| + default: return 0; |
| + } |
| + } |
| + |
| + int NormalizeAngle(int degrees) { |
| + while (degrees <= -180) degrees += 360; |
| + while (degrees > 180) degrees -= 360; |
| + return degrees; |
| + } |
| + |
| + void Start() { |
| + TRACE_EVENT_BEGIN0("RotateAnimation", "Start rotating"); |
| + root_->SetPaintingEnabled(false); |
| + int degrees = SideToDegrees(new_up_) - SideToDegrees(old_up_); |
| + degrees = NormalizeAngle(degrees); |
| + |
| + // No rotation required. |
| + if (degrees == 0) |
| + return; |
| + |
| + gfx::Point old_pivot; |
| + gfx::Point new_pivot; |
| + |
| + switch (degrees) { |
| + case 90: |
|
sadrul
2011/07/15 15:25:48
ditto
|
| + new_origin_ = old_pivot = gfx::Point(root_->width(), 0); |
| + new_pivot.SetPoint(root_->width(), root_->height()); |
| + new_size_.SetSize(root_->height(), root_->width()); |
| + break; |
| + case -90: |
| + new_origin_ = new_pivot = gfx::Point(0, root_->height()); |
| + new_size_.SetSize(root_->height(), root_->width()); |
| + break; |
| + case 180: |
| + new_pivot = old_pivot = gfx::Point(root_->width() / 2, |
| + root_->height() / 2); |
| + new_origin_.SetPoint(root_->width(), root_->height()); |
| + new_size_.SetSize(root_->width(), root_->height()); |
| + break; |
| + } |
| + |
| + // Convert points to world space. |
| + const ui::Transform& xform = root_->GetTransform(); |
| + xform.TransformPoint(old_pivot); |
| + xform.TransformPoint(new_pivot); |
| + xform.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()))); |
| + |
| + interpolated_transform_.reset( |
| + new ui::InterpolatedConstantTransform(xform)); |
| + |
| + rotation->SetChild(translation.release()); |
| + interpolated_transform_->SetChild(rotation.release()); |
| + |
| + animation_->Show(); |
| + } |
| + |
| + views::View* root_; |
| + scoped_ptr<ui::SlideAnimation> animation_; |
| + scoped_ptr<ui::InterpolatedTransform> interpolated_transform_; |
| + sensors::ScreenOrientation::Side old_up_; |
| + sensors::ScreenOrientation::Side new_up_; |
| + gfx::Size new_size_; |
| + gfx::Point new_origin_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TouchBrowserFrameRotation); |
| +}; |
| + |
| // static |
| const char TouchBrowserFrameView::kViewClassName[] = |
| "browser/ui/touch/frame/TouchBrowserFrameView"; |
| @@ -61,7 +197,8 @@ TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame, |
| keyboard_showing_(false), |
| keyboard_height_(kDefaultKeyboardHeight), |
| focus_listener_added_(false), |
| - keyboard_(NULL) { |
| + keyboard_(NULL), |
| + up_(sensors::ScreenOrientation::TOP) { |
| registrar_.Add(this, |
| content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| NotificationService::AllSources()); |
| @@ -92,10 +229,13 @@ TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame, |
| chromeos::input_method::InputMethodManager::GetInstance(); |
| manager->AddVirtualKeyboardObserver(this); |
| #endif |
| + |
| + sensors::Provider::GetInstance()->AddListener(this); |
| } |
| TouchBrowserFrameView::~TouchBrowserFrameView() { |
| browser_view()->browser()->tabstrip_model()->RemoveObserver(this); |
| + sensors::Provider::GetInstance()->RemoveListener(this); |
| } |
| std::string TouchBrowserFrameView::GetClassName() const { |
| @@ -361,6 +501,15 @@ void TouchBrowserFrameView::AnimationEnded(const ui::Animation* animation) { |
| SchedulePaint(); |
| } |
| +void TouchBrowserFrameView::OnScreenOrientationChange( |
| + const sensors::ScreenOrientation& change) { |
| + |
| + views::Widget* widget = GetWidget(); |
|
sadrul
2011/07/15 15:25:48
Please try this with --views-desktop and see if th
|
| + views::View* root = widget->GetRootView(); |
| + TouchBrowserFrameRotation::Perform(root, up_, change.upward); |
| + up_ = change.upward; |
| +} |
| + |
| #if defined(OS_CHROMEOS) |
| void TouchBrowserFrameView::VirtualKeyboardChanged( |
| chromeos::input_method::InputMethodManager* manager, |