1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/host/transformer_helper.h"
6
7#include "ash/host/ash_window_tree_host.h"
8#include "ash/host/root_window_transformer.h"
9#include "ui/aura/window.h"
10#include "ui/aura/window_tree_host.h"
11#include "ui/compositor/dip_util.h"
12#include "ui/gfx/geometry/insets.h"
13#include "ui/gfx/geometry/rect.h"
14#include "ui/gfx/geometry/rect_f.h"
15#include "ui/gfx/geometry/size.h"
16#include "ui/gfx/size_conversions.h"
17#include "ui/gfx/transform.h"
18
19namespace ash {
20namespace {
21
22// A simple RootWindowTransformer without host insets.
23class SimpleRootWindowTransformer : public RootWindowTransformer {
24 public:
25  SimpleRootWindowTransformer(const aura::Window* root_window,
26                              const gfx::Transform& transform)
27      : root_window_(root_window), transform_(transform) {}
28
29  // RootWindowTransformer overrides:
30  virtual gfx::Transform GetTransform() const OVERRIDE { return transform_; }
31
32  virtual gfx::Transform GetInverseTransform() const OVERRIDE {
33    gfx::Transform invert;
34    if (!transform_.GetInverse(&invert))
35      return transform_;
36    return invert;
37  }
38
39  virtual gfx::Rect GetRootWindowBounds(const gfx::Size& host_size) const
40      OVERRIDE {
41    gfx::Rect bounds(host_size);
42    gfx::RectF new_bounds(ui::ConvertRectToDIP(root_window_->layer(), bounds));
43    transform_.TransformRect(&new_bounds);
44    return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
45  }
46
47  virtual gfx::Insets GetHostInsets() const OVERRIDE { return gfx::Insets(); }
48
49 private:
50  virtual ~SimpleRootWindowTransformer() {}
51
52  const aura::Window* root_window_;
53  const gfx::Transform transform_;
54
55  DISALLOW_COPY_AND_ASSIGN(SimpleRootWindowTransformer);
56};
57
58}  // namespace
59
60TransformerHelper::TransformerHelper(AshWindowTreeHost* ash_host)
61    : ash_host_(ash_host) {
62  SetTransform(gfx::Transform());
63}
64
65TransformerHelper::~TransformerHelper() {}
66
67gfx::Insets TransformerHelper::GetHostInsets() const {
68  return transformer_->GetHostInsets();
69}
70
71void TransformerHelper::SetTransform(const gfx::Transform& transform) {
72  scoped_ptr<RootWindowTransformer> transformer(new SimpleRootWindowTransformer(
73      ash_host_->AsWindowTreeHost()->window(), transform));
74  SetRootWindowTransformer(transformer.Pass());
75}
76
77void TransformerHelper::SetRootWindowTransformer(
78    scoped_ptr<RootWindowTransformer> transformer) {
79  transformer_ = transformer.Pass();
80  aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost();
81  aura::Window* window = host->window();
82  window->SetTransform(transformer_->GetTransform());
83  // If the layer is not animating, then we need to update the root window
84  // size immediately.
85  if (!window->layer()->GetAnimator()->is_animating())
86    host->UpdateRootWindowSize(host->GetBounds().size());
87}
88
89gfx::Transform TransformerHelper::GetTransform() const {
90  float scale = ui::GetDeviceScaleFactor(
91      ash_host_->AsWindowTreeHost()->window()->layer());
92  gfx::Transform transform;
93  transform.Scale(scale, scale);
94  transform *= transformer_->GetTransform();
95  return transform;
96}
97
98gfx::Transform TransformerHelper::GetInverseTransform() const {
99  float scale = ui::GetDeviceScaleFactor(
100      ash_host_->AsWindowTreeHost()->window()->layer());
101  gfx::Transform transform;
102  transform.Scale(1.0f / scale, 1.0f / scale);
103  return transformer_->GetInverseTransform() * transform;
104}
105
106void TransformerHelper::UpdateWindowSize(const gfx::Size& host_size) {
107  ash_host_->AsWindowTreeHost()->window()->SetBounds(
108      transformer_->GetRootWindowBounds(host_size));
109}
110
111}  // namespace ash
112