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 d2c3c65ccde80b0ef8f6645789f7b2931f660cff..742055b29377474e9f8150492199c3a22f8a0abc 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" |
@@ -48,6 +49,221 @@ bool TabContentsHasFocus(const TabContents* contents) { |
} // namespace |
+OrientationChangeHack::OrientationChangeHack(TouchBrowserFrameView* frame, |
+ OrientationChangeFn function) |
+ : frame_(frame), |
+ function_(function) { |
+ connection_ = sensors::Provider::GetInstance()->Open(this); |
+ LOG(ERROR) << "opened sensor connection " << connection_; |
+} |
+ |
+OrientationChangeHack::~OrientationChangeHack() { |
+ if (connection_ != NULL) |
+ connection_->Close(); |
+} |
+ |
+void OrientationChangeHack::SensorChanged(sensors::Channel channel, |
+ const std::string& data) { |
+ if (channel == sensors::kScreenOrientationChannel) { |
+ const sensors::ScreenOrientationChange* change = |
+ reinterpret_cast<const sensors::ScreenOrientationChange*>(data.c_str()); |
+ (frame_->*function_)(change); |
+ } |
+} |
+ |
+void OrientationChangeHack::InjectSensorChanged( |
+ sensors::Channel channel, |
+ const std::string& data) { |
+ sensors::Provider::GetInstance()->FireSensorChanged(channel, data); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Animation |
+ |
+class TouchBrowserFrameRotation : public ui::AnimationDelegate { |
+ public: |
+ static void Perform(views::View* root, |
+ sensors::ScreenOrientationChange::Side oldUp, |
+ sensors::ScreenOrientationChange::Side newUp, |
+ int original_width, |
+ int original_height) { |
+ new TouchBrowserFrameRotation(root, |
+ oldUp, |
+ newUp, |
+ original_width, |
+ original_height); |
+ } |
+ |
+ private: |
+ TouchBrowserFrameRotation(views::View* root, |
+ sensors::ScreenOrientationChange::Side old_up, |
+ sensors::ScreenOrientationChange::Side new_up, |
+ int original_width, |
+ int original_height) |
+ : root_(root), |
+ old_up_(old_up), |
+ new_up_(new_up), |
+ old_xform_(root->GetTransform()), |
+ original_width_(original_width), |
+ original_height_(original_height) { |
+ animation_.reset(new ui::SlideAnimation(this)); |
+ animation_->SetTweenType(ui::Tween::LINEAR); |
+ animation_->SetSlideDuration(1000); |
+ Start(); |
+ } |
+ |
+ ui::Transform BuildTransform(float anim_value, |
+ float degrees, |
+ int pivot_x, int pivot_y, |
+ int dx, int dy) { |
+ ui::Transform transform = old_xform_; |
+ gfx::Point p(pivot_x, pivot_y); |
+ transform.TransformPoint(&p); |
+ transform.ConcatTranslate(-p.x(), -p.y()); |
+ transform.ConcatRotate(degrees * anim_value); |
+ transform.ConcatTranslate(p.x(), p.y()); |
+ transform.ConcatTranslate(dx * anim_value, dy * anim_value); |
+ return transform; |
+ } |
+ |
+ virtual void AnimationProgressed(const ui::Animation* anim) OVERRIDE { |
+ TRACE_EVENT0("animation", "AnimationProgressed"); |
+ { |
+ TRACE_EVENT0("animation", "Updating Transform"); |
+ // Make a copy of the view's transform. We'll modify the copy, |
+ // then pass it back to SetTransform. |
+ float value = anim->GetCurrentValue(); |
+ ui::Transform transform = root_->GetTransform(); |
+ switch (old_up_) { |
+ case sensors::ScreenOrientationChange::TOP: |
+ switch (new_up_) { |
+ case sensors::ScreenOrientationChange::BOTTOM: |
+ transform = BuildTransform( |
+ value, 180, original_width_ / 2, original_height_ / 2, 0, 0); |
+ break; |
+ case sensors::ScreenOrientationChange::LEFT: |
+ transform = BuildTransform(value, -90, 0, 0, 0, original_height_); |
+ break; |
+ case sensors::ScreenOrientationChange::RIGHT: |
+ transform = BuildTransform( |
+ value, 90, original_width_, 0, 0, original_height_); |
+ break; |
+ default: |
+ return; |
+ } |
+ break; |
+ case sensors::ScreenOrientationChange::BOTTOM: |
+ switch (new_up_) { |
+ case sensors::ScreenOrientationChange::TOP: |
+ transform = BuildTransform( |
+ value, 180, original_width_ / 2, original_height_ / 2, 0, 0); |
+ break; |
+ case sensors::ScreenOrientationChange::LEFT: |
+ transform = BuildTransform( |
+ value, 90, original_width_, 0, 0, -original_height_); |
+ break; |
+ case sensors::ScreenOrientationChange::RIGHT: |
+ transform = BuildTransform(value, -90, 0, 0, 0, -original_height_); |
+ break; |
+ default: |
+ return; |
+ } |
+ break; |
+ case sensors::ScreenOrientationChange::LEFT: |
+ switch (new_up_) { |
+ case sensors::ScreenOrientationChange::BOTTOM: |
+ transform = BuildTransform(value, -90, 0, 0, original_height_, 0); |
+ break; |
+ case sensors::ScreenOrientationChange::TOP: |
+ transform = BuildTransform( |
+ value, 90, original_height_, 0, original_height_, 0); |
+ break; |
+ case sensors::ScreenOrientationChange::RIGHT: |
+ transform = BuildTransform( |
+ value, 180, original_height_ / 2, original_width_ / 2, 0, 0); |
+ break; |
+ default: |
+ return; |
+ } |
+ break; |
+ case sensors::ScreenOrientationChange::RIGHT: |
+ switch (new_up_) { |
+ case sensors::ScreenOrientationChange::BOTTOM: |
+ transform = BuildTransform( |
+ value, 90, original_height_, 0, -original_height_, 0); |
+ break; |
+ case sensors::ScreenOrientationChange::TOP: |
+ transform = BuildTransform(value, -90, 0, 0, -original_height_, 0); |
+ break; |
+ case sensors::ScreenOrientationChange::LEFT: |
+ transform = BuildTransform( |
+ value, 180, original_height_ / 2, original_width_ / 2, 0, 0); |
+ break; |
+ default: |
+ return; |
+ } |
+ break; |
+ default: |
+ return; |
+ } |
+ //root_->SetTransformNoSideEffect(transform); |
+ root_->SetTransform(transform); // should not cause pixels to be painted. |
+ } |
+ //root_->GetWidget()->OnNativeWidgetCompositeAccelerated(); |
+ root_->ScheduleComposite(); // also, should not cause pixels to be painted. |
+ } |
+ |
+ virtual void AnimationEnded(const ui::Animation* anim) OVERRIDE { |
+ TRACE_EVENT_END0("RotateAnimation", "Start rotating"); |
+ root_->SetPaintingEnabled(true); |
+ ui::Transform transform; |
+ switch (new_up_) { |
+ case sensors::ScreenOrientationChange::TOP: |
+ root_->SetTransform(transform); |
+ root_->SetBounds(0, 0, original_width_, original_height_); |
+ break; |
+ case sensors::ScreenOrientationChange::BOTTOM: |
+ transform.SetRotate(180); |
+ transform.ConcatTranslate(original_width_, original_height_); |
+ root_->SetTransform(transform); |
+ root_->SetBounds(0, 0, original_width_, original_height_); |
+ break; |
+ case sensors::ScreenOrientationChange::LEFT: |
+ transform.SetRotate(-90); |
+ transform.ConcatTranslate(0, original_height_); |
+ root_->SetTransform(transform); |
+ root_->SetBounds(0, 0, original_height_, original_width_); |
+ break; |
+ case sensors::ScreenOrientationChange::RIGHT: |
+ transform.SetRotate(90); |
+ transform.ConcatTranslate(original_width_, 0); |
+ root_->SetTransform(transform); |
+ root_->SetBounds(0, 0, original_height_, original_width_); |
+ break; |
+ default: |
+ break; |
+ } |
+ delete this; |
+ root_->SchedulePaint(); |
+ } |
+ |
+ void Start() { |
+ TRACE_EVENT_BEGIN0("RotateAnimation", "Start rotating"); |
+ root_->SetPaintingEnabled(false); |
+ animation_->Show(); |
+ } |
+ |
+ views::View* root_; |
+ scoped_ptr<ui::SlideAnimation> animation_; |
+ sensors::ScreenOrientationChange::Side old_up_; |
+ sensors::ScreenOrientationChange::Side new_up_; |
+ ui::Transform old_xform_; |
+ int original_width_; |
+ int original_height_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TouchBrowserFrameRotation); |
+}; |
+ |
// static |
const char TouchBrowserFrameView::kViewClassName[] = |
"browser/ui/touch/frame/TouchBrowserFrameView"; |
@@ -61,7 +277,11 @@ TouchBrowserFrameView::TouchBrowserFrameView(BrowserFrame* frame, |
keyboard_showing_(false), |
keyboard_height_(kDefaultKeyboardHeight), |
focus_listener_added_(false), |
- keyboard_(NULL) { |
+ keyboard_(NULL), |
+ up_(sensors::ScreenOrientationChange::TOP), |
+ original_width_(0), |
+ original_height_(0), |
+ hack_(this, &TouchBrowserFrameView::OnScreenOrientationChanged) { |
registrar_.Add(this, |
NotificationType::NAV_ENTRY_COMMITTED, |
NotificationService::AllSources()); |
@@ -361,6 +581,25 @@ void TouchBrowserFrameView::AnimationEnded(const ui::Animation* animation) { |
SchedulePaint(); |
} |
+void TouchBrowserFrameView::OnScreenOrientationChanged( |
+ const sensors::ScreenOrientationChange* change) { |
+ |
+ // Do the good old switcheroo |
+ views::Widget* widget = GetWidget(); |
+ views::View* root = widget->GetRootView(); |
+ |
+ if (original_width_ == 0 || original_height_ == 0) { |
+ original_width_ = root->width(); |
+ original_height_ = root->height(); |
+ } |
+ |
+ TouchBrowserFrameRotation::Perform(root, |
+ up_, change->upward, |
+ original_width_, |
+ original_height_); |
+ up_ = change->upward; |
+} |
+ |
#if defined(OS_CHROMEOS) |
void TouchBrowserFrameView::VirtualKeyboardChanged( |
chromeos::InputMethodLibrary* obj, |