blob: 05223c34a6a6b1b860849f0757f4c4c48761ca1e [file] [log] [blame]
// Copyright 2014 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 "remoting/host/chromeos/point_transformer.h"
#include "ash/shell.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/dip_util.h"
namespace remoting {
PointTransformer::PointTransformer() {
root_window_ = ash::Shell::GetPrimaryRootWindow();
root_window_->AddObserver(this);
// Set the initial display rotation.
OnWindowTargetTransformChanging(root_window_,
root_window_->layer()->GetTargetTransform());
}
PointTransformer::~PointTransformer() {
root_window_->RemoveObserver(this);
}
void PointTransformer::OnWindowTargetTransformChanging(
aura::Window* window,
const gfx::Transform& new_transform) {
CHECK_EQ(window, root_window_);
ui::Layer* layer = root_window_->layer();
float scale = ui::GetDeviceScaleFactor(layer);
gfx::Transform to_device_pixels;
gfx::Transform to_dip;
to_device_pixels.Scale(scale, scale);
to_dip.Scale(1 / scale, 1 / scale);
// Use WindowTreeHost::GetRootTransform instead of |new_transform| because
// |new_transform| no longer contains rotation. The root transform contains
// a transform comprising a rotation and a translation, but it expects DIPs as
// input in DIPs and convert to device pixels. So we need to switch device
// pixels to DIPs then apply it.
gfx::Transform rotation = root_window_->GetHost()->GetRootTransform();
// Use GetInverseRootTransform instead of using root transform inverse. The
// two normally should be the same but GetInverseRootTransform() is
// constructed at the same time of root transform and has less rounding
// errors. It expect device pixels as input and convert to DIPs. So we need to
// switch to device pixels after applying it.
gfx::Transform inverse_rotation =
root_window_->GetHost()->GetInverseRootTransform();
// Matrix transformations are applied from right to left. See annotations.
// (2) (1)
root_to_screen_ = rotation * to_dip;
screen_to_root_ = to_device_pixels * inverse_rotation;
}
gfx::PointF PointTransformer::ToScreenCoordinates(
const gfx::PointF& root_location) {
gfx::Point3F screen_location(root_location);
root_to_screen_.TransformPoint(&screen_location);
return screen_location.AsPointF();
}
gfx::PointF PointTransformer::FromScreenCoordinates(
const gfx::PointF& screen_location) {
gfx::Point3F root_location(screen_location);
screen_to_root_.TransformPoint(&root_location);
return root_location.AsPointF();
}
} // namespace remoting