Commit bb54e63c authored by oshima@chromium.org's avatar oshima@chromium.org

Manually compute inverted matrix for screen rotation

BUG=222483
TEST=no functionality change. covered by existing unit tests.

Review URL: https://codereview.chromium.org/12983010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@190533 0039d316-1c4b-4281-b951-d872f2087c98
parent f80e6550
......@@ -135,6 +135,12 @@ void RotateRootWindow(aura::RootWindow* root_window,
root_window->SetProperty(kRotationPropertyKey, info.rotation());
#endif
gfx::Transform rotate;
// TODO(oshima): Manually complute the inverse of the
// rotate+translate matrix to compensate for computation error in
// the inverted matrix. Ideally, SkMatrix should have special
// case handling for rotate+translate case. crbug.com/222483.
gfx::Transform reverse_rotate;
// The origin is (0, 0), so the translate width/height must be reduced by 1.
switch (info.rotation()) {
case gfx::Display::ROTATE_0:
......@@ -142,18 +148,26 @@ void RotateRootWindow(aura::RootWindow* root_window,
case gfx::Display::ROTATE_90:
rotate.Translate(display.bounds().height() - 1, 0);
rotate.Rotate(90);
// Rotate 270 instead of 90 as it will cause calcuration error.
reverse_rotate.Rotate(270);
reverse_rotate.Translate(-(display.bounds().height() - 1), 0);
break;
case gfx::Display::ROTATE_270:
rotate.Translate(0, display.bounds().width() - 1);
rotate.Rotate(270);
reverse_rotate.Rotate(90);
reverse_rotate.Translate(0, -(display.bounds().width() - 1));
break;
case gfx::Display::ROTATE_180:
rotate.Translate(display.bounds().width() - 1,
display.bounds().height() - 1);
rotate.Rotate(180);
reverse_rotate.Rotate(180);
reverse_rotate.Translate(-(display.bounds().width() - 1),
-(display.bounds().height() - 1));
break;
}
root_window->SetTransform(rotate);
root_window->SetTransformPair(rotate, reverse_rotate);
}
void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
......
......@@ -159,7 +159,8 @@ void RootWindow::Init() {
host_->GetBounds().size());
Window::Init(ui::LAYER_NOT_DRAWN);
compositor()->SetRootLayer(layer());
SetTransformInternal(gfx::Transform());
gfx::Transform identity;
SetTransformInternal(identity, identity);
UpdateWindowSize(host_->GetBounds().size());
Env::GetInstance()->NotifyRootWindowInitialized(this);
Show();
......@@ -403,7 +404,7 @@ void RootWindow::ConvertPointToHost(gfx::Point* point) const {
void RootWindow::ConvertPointFromHost(gfx::Point* point) const {
gfx::Point3F point_3f(*point);
GetRootTransform().TransformPointReverse(point_3f);
GetInvertedRootTransform().TransformPoint(point_3f);
*point = gfx::ToFlooredPoint(point_3f.AsPointF());
}
......@@ -493,7 +494,15 @@ const RootWindow* RootWindow::GetRootWindow() const {
}
void RootWindow::SetTransform(const gfx::Transform& transform) {
SetTransformInternal(transform);
gfx::Transform invert;
if (!transform.GetInverse(&invert))
NOTREACHED() << "Singular matrix is set.";
SetTransformPair(transform, invert);
}
void RootWindow::SetTransformPair(const gfx::Transform& transform,
const gfx::Transform& invert) {
SetTransformInternal(transform, invert);
// If the layer is not animating, then we need to update the host size
// immediately.
......@@ -501,17 +510,23 @@ void RootWindow::SetTransform(const gfx::Transform& transform) {
OnHostResized(host_->GetBounds().size());
}
void RootWindow::SetTransformInternal(const gfx::Transform& transform) {
void RootWindow::SetTransformInternal(const gfx::Transform& transform,
const gfx::Transform& inverted) {
gfx::Insets insets = host_->GetInsets();
gfx::Transform translate;
invert_transform_ = inverted;
invert_transform_.Scale(root_window_scale_, root_window_scale_);
if (insets.top() != 0 || insets.left() != 0) {
float device_scale_factor = GetDeviceScaleFactor();
translate.Translate(insets.left() / device_scale_factor,
insets.top() / device_scale_factor);
Window::SetTransform(translate * transform);
float x_offset = insets.left() / device_scale_factor;
float y_offset = insets.top() / device_scale_factor;
translate.Translate(x_offset, y_offset);
invert_transform_.Translate(-x_offset, -y_offset);
}
float invert = 1.0f / root_window_scale_;
translate.Scale(invert, invert);
float inverted_scale = 1.0f / root_window_scale_;
translate.Scale(inverted_scale, inverted_scale);
Window::SetTransform(translate * transform);
}
......@@ -671,7 +686,7 @@ void RootWindow::ClearMouseHandlers() {
void RootWindow::TransformEventForDeviceScaleFactor(bool keep_inside_root,
ui::LocatedEvent* event) {
event->UpdateForRootTransform(GetRootTransform());
event->UpdateForRootTransform(GetInvertedRootTransform());
#if defined(OS_CHROMEOS)
const gfx::Rect& root_bounds = bounds();
if (keep_inside_root &
......@@ -680,8 +695,8 @@ void RootWindow::TransformEventForDeviceScaleFactor(bool keep_inside_root,
// Make sure that the mouse location inside the host window gets
// translated inside root window.
// TODO(oshima): This is (hopefully) short term bandaid to deal
// with calculation error in inverted matrix. We'll try better
// alternative (crbug.com/222483) for m28.
// with calculation error due to the fact that we rotate in dip
// coordinates instead of pixels. crbug.com/222483.
int x = event->location().x();
int y = event->location().y();
x = std::min(std::max(x, root_bounds.x()), root_bounds.right());
......@@ -1179,4 +1194,11 @@ gfx::Transform RootWindow::GetRootTransform() const {
return transform;
}
gfx::Transform RootWindow::GetInvertedRootTransform() const {
float scale = ui::GetDeviceScaleFactor(layer());
gfx::Transform transform;
transform.Scale(1.0f / scale, 1.0f / scale);
return invert_transform_ * transform;
}
} // namespace aura
......@@ -28,6 +28,7 @@
#include "ui/gfx/insets.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/transform.h"
class SkCanvas;
......@@ -293,6 +294,13 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// window that ate mouse downs).
void ClearMouseHandlers();
// Sets the window's transform and inverted transform. This is necessary
// to reverse translate the point without computation error.
// TODO(oshima): Remove this once the computation error is resolved.
// crbug.com/222483.
void SetTransformPair(const gfx::Transform& transform,
const gfx::Transform& inverted);
private:
FRIEND_TEST_ALL_PREFIXES(RootWindowTest, KeepTranslatedEventInRoot);
......@@ -350,7 +358,8 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// transform and insets.
void UpdateWindowSize(const gfx::Size& host_size);
void SetTransformInternal(const gfx::Transform& transform);
void SetTransformInternal(const gfx::Transform& transform,
const gfx::Transform& insert);
// Overridden from ui::EventDispatcherDelegate.
virtual bool CanDispatchToTarget(EventTarget* target) OVERRIDE;
......@@ -406,6 +415,7 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
void SynthesizeMouseMoveEvent();
gfx::Transform GetRootTransform() const;
gfx::Transform GetInvertedRootTransform() const;
scoped_ptr<ui::Compositor> compositor_;
......@@ -462,6 +472,9 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// factor, which specfies the pixel density of the display.
float root_window_scale_;
// The invert of |layer()|'s transform.
gfx::Transform invert_transform_;
DISALLOW_COPY_AND_ASSIGN(RootWindow);
};
......
......@@ -268,13 +268,10 @@ LocatedEvent::LocatedEvent(EventType type,
}
void LocatedEvent::UpdateForRootTransform(
const gfx::Transform& root_transform) {
const gfx::Transform& reversed_root_transform) {
// Transform has to be done at root level.
gfx::Point3F p(location_);
root_transform.TransformPointReverse(p);
// TODO(oshima): Translating a point using reversed matrix can
// results in small error like 0 -> -0.01, whose floored value
// is -1 instead of 0. crbug.com/222483.
reversed_root_transform.TransformPoint(p);
root_location_ = location_ = gfx::ToFlooredPoint(p.AsPointF());
}
......
......@@ -269,9 +269,10 @@ class UI_EXPORT LocatedEvent : public Event {
}
const gfx::Point& system_location() const { return system_location_; }
// Applies |root_transform| to the event.
// Transform the locations using |inverted_root_transform|.
// This is applied to both |location_| and |root_location_|.
virtual void UpdateForRootTransform(const gfx::Transform& root_transform);
virtual void UpdateForRootTransform(
const gfx::Transform& inverted_root_transform);
template <class T> void ConvertLocationToTarget(T* source, T* target) {
if (target && target != source)
......
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