Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: ash/display/root_window_transformers.cc

Issue 15730006: Use the source display's pixel size as a mirror window's size. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/ash_root_window_transformer.h" 5 #include "ash/display/root_window_transformers.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "ash/display/display_info.h" 9 #include "ash/display/display_info.h"
10 #include "ash/display/display_manager.h" 10 #include "ash/display/display_manager.h"
11 #include "ash/magnifier/magnification_controller.h" 11 #include "ash/magnifier/magnification_controller.h"
12 #include "ash/shell.h" 12 #include "ash/shell.h"
13 #include "base/basictypes.h"
14 #include "base/memory/scoped_ptr.h"
13 #include "third_party/skia/include/utils/SkMatrix44.h" 15 #include "third_party/skia/include/utils/SkMatrix44.h"
14 #include "ui/aura/root_window.h" 16 #include "ui/aura/root_window.h"
17 #include "ui/aura/root_window_transformer.h"
15 #include "ui/aura/window_property.h" 18 #include "ui/aura/window_property.h"
16 #include "ui/compositor/dip_util.h" 19 #include "ui/compositor/dip_util.h"
17 #include "ui/gfx/display.h" 20 #include "ui/gfx/display.h"
21 #include "ui/gfx/insets.h"
18 #include "ui/gfx/size_conversions.h" 22 #include "ui/gfx/size_conversions.h"
19 #include "ui/gfx/transform.h" 23 #include "ui/gfx/transform.h"
24 #include "ui/gfx/transform.h"
20 25
21 DECLARE_WINDOW_PROPERTY_TYPE(gfx::Display::Rotation); 26 DECLARE_WINDOW_PROPERTY_TYPE(gfx::Display::Rotation);
22 27
23 namespace ash { 28 namespace ash {
29 namespace internal {
24 namespace { 30 namespace {
25 31
26 DEFINE_WINDOW_PROPERTY_KEY(gfx::Display::Rotation, kRotationPropertyKey, 32 DEFINE_WINDOW_PROPERTY_KEY(gfx::Display::Rotation, kRotationPropertyKey,
27 gfx::Display::ROTATE_0); 33 gfx::Display::ROTATE_0);
28 34
29 // Round near zero value to zero. 35 // Round near zero value to zero.
30 void RoundNearZero(gfx::Transform* transform) { 36 void RoundNearZero(gfx::Transform* transform) {
31 const float kEpsilon = 0.001f; 37 const float kEpsilon = 0.001f;
32 SkMatrix44& matrix = transform->matrix(); 38 SkMatrix44& matrix = transform->matrix();
33 for (int x = 0; x < 4; ++x) { 39 for (int x = 0; x < 4; ++x) {
34 for (int y = 0; y < 4; ++y) { 40 for (int y = 0; y < 4; ++y) {
35 if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon) 41 if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon)
36 matrix.set(x, y, SkFloatToMScalar(0.0f)); 42 matrix.set(x, y, SkFloatToMScalar(0.0f));
37 } 43 }
38 } 44 }
39 } 45 }
40 46
41 gfx::Transform CreateRotationTransform(aura::RootWindow* root_window, 47 gfx::Transform CreateRotationTransform(aura::RootWindow* root_window,
42 const gfx::Display& display) { 48 const gfx::Display& display) {
43 internal::DisplayInfo info = 49 DisplayInfo info =
44 Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id()); 50 Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
45 51
46 // TODO(oshima): Add animation. (crossfade+rotation, or just cross-fade) 52 // TODO(oshima): Add animation. (crossfade+rotation, or just cross-fade)
47 #if defined(OS_WIN) 53 #if defined(OS_WIN)
48 // Windows 8 bots refused to resize the host window, and 54 // Windows 8 bots refused to resize the host window, and
49 // updating the transform results in incorrectly resizing 55 // updating the transform results in incorrectly resizing
50 // the root window. Don't apply the transform unless 56 // the root window. Don't apply the transform unless
51 // necessary so that unit tests pass on win8 bots. 57 // necessary so that unit tests pass on win8 bots.
52 if (info.rotation() == root_window->GetProperty(kRotationPropertyKey)) 58 if (info.rotation() == root_window->GetProperty(kRotationPropertyKey))
53 return gfx::Transform(); 59 return gfx::Transform();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 magnifier_offset = magnifier->GetWindowPosition(); 96 magnifier_offset = magnifier->GetWindowPosition();
91 } 97 }
92 gfx::Transform transform; 98 gfx::Transform transform;
93 if (magnifier_scale != 1.f) { 99 if (magnifier_scale != 1.f) {
94 transform.Scale(magnifier_scale, magnifier_scale); 100 transform.Scale(magnifier_scale, magnifier_scale);
95 transform.Translate(-magnifier_offset.x(), -magnifier_offset.y()); 101 transform.Translate(-magnifier_offset.x(), -magnifier_offset.y());
96 } 102 }
97 return transform; 103 return transform;
98 } 104 }
99 105
106 gfx::Transform CreateInsetsAndScaleTransform(const gfx::Insets& insets,
107 float device_scale_factor,
108 float ui_scale) {
109 gfx::Transform transform;
110 if (insets.top() != 0 || insets.left() != 0) {
111 float x_offset = insets.left() / device_scale_factor;
112 float y_offset = insets.top() / device_scale_factor;
113 transform.Translate(x_offset, y_offset);
114 }
115 float inverted_scale = 1.0f / ui_scale;
116 transform.Scale(inverted_scale, inverted_scale);
117 return transform;
118 }
119
100 gfx::Transform CreateOverscanAndUIScaleTransform(aura::RootWindow* root_window, 120 gfx::Transform CreateOverscanAndUIScaleTransform(aura::RootWindow* root_window,
101 const gfx::Display& display) { 121 const gfx::Display& display) {
102 internal::DisplayInfo info = 122 DisplayInfo info =
103 Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id()); 123 Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
104 gfx::Insets insets = info.GetOverscanInsetsInPixel(); 124 return CreateInsetsAndScaleTransform(
105 float scale = info.ui_scale(); 125 info.GetOverscanInsetsInPixel(),
126 ui::GetDeviceScaleFactor(root_window->layer()),
127 info.ui_scale());
128 }
106 129
107 gfx::Transform transform; 130 // RootWindowTransformer for ash environment.
108 if (insets.top() != 0 || insets.left() != 0) { 131 class ASH_EXPORT AshRootWindowTransformer : public aura::RootWindowTransformer {
James Cook 2013/05/29 12:22:43 Dumb question: If these are internal classes in a
oshima 2013/05/29 15:39:49 good point. I just copied from header and apparent
109 float device_scale_factor = ui::GetDeviceScaleFactor(root_window->layer()); 132 public:
110 float x_offset = insets.left() / device_scale_factor; 133 AshRootWindowTransformer(aura::RootWindow* root,
111 float y_offset = insets.top() / device_scale_factor; 134 const gfx::Display& display)
112 transform.Translate(x_offset, y_offset); 135 : root_window_(root) {
136 root_window_bounds_transform_ =
137 CreateOverscanAndUIScaleTransform(root, display) *
138 CreateRotationTransform(root, display);
139 transform_ = root_window_bounds_transform_ * CreateMagnifierTransform(root);
140 CHECK(transform_.GetInverse(&invert_transform_));
141
142 DisplayInfo info = Shell::GetInstance()->display_manager()->
143 GetDisplayInfo(display.id());
144 root_window_ui_scale_ = info.ui_scale();
145 host_insets_ = info.GetOverscanInsetsInPixel();
146 MagnificationController* magnifier =
147 Shell::GetInstance()->magnification_controller();
148
149 bool scaled = (root_window_ui_scale_ != 1.f) ||
150 (magnifier && magnifier->GetScale() != 1.f);
151 root_window_->layer()->SetForceRenderSurface(scaled);
113 } 152 }
114 float inverted_scale = 1.0f / scale; 153
115 transform.Scale(inverted_scale, inverted_scale); 154 // aura::RootWindowTransformer overrides:
116 return transform; 155 virtual gfx::Transform GetTransform() const OVERRIDE {
117 } 156 return transform_;
157 }
158 virtual gfx::Transform GetInverseTransform() const OVERRIDE {
159 return invert_transform_;
160 }
161 virtual gfx::Rect GetRootWindowBounds(
162 const gfx::Size& host_size) const OVERRIDE {
163 gfx::Rect bounds(host_size);
164 bounds.Inset(host_insets_);
165 bounds = ui::ConvertRectToDIP(root_window_->layer(), bounds);
166 gfx::RectF new_bounds(bounds);
167 root_window_bounds_transform_.TransformRect(&new_bounds);
168 // Apply |root_window_scale_| twice as the downscaling
169 // is already applied once in |SetTransformInternal()|.
170 // TODO(oshima): This is a bit ugly. Consider specifying
171 // the pseudo host resolution instead.
172 new_bounds.Scale(root_window_ui_scale_ * root_window_ui_scale_);
173 // Ignore the origin because RootWindow's insets are handled by
174 // the transform.
175 // Floor the size because the bounds is no longer aligned to
176 // backing pixel when |root_window_scale_| is specified
177 // (850 height at 1.25 scale becomes 1062.5 for example.)
178 return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
179 }
180
181 virtual gfx::Insets GetHostInsets() const OVERRIDE {
182 return host_insets_;
183 }
184
185 private:
186 virtual ~AshRootWindowTransformer() {}
187
188 aura::RootWindow* root_window_;
189 gfx::Transform transform_;
190
191 // The accurate representation of the inverse of the |transform_|.
192 // This is used to avoid computation error caused by
193 // |gfx::Transform::GetInverse|.
194 gfx::Transform invert_transform_;
195
196 // The transform of the root window bounds. This is used to calculate
197 // the size of root window.
198 gfx::Transform root_window_bounds_transform_;
199
200 // The scale of the root window. This is used to expand the
201 // area of the root window (useful in HighDPI display).
202 // Note that this should not be confused with the device scale
203 // factor, which specfies the pixel density of the display.
204 float root_window_ui_scale_;
205
206 gfx::Insets host_insets_;
207
208 DISALLOW_COPY_AND_ASSIGN(AshRootWindowTransformer);
209 };
210
211 // RootWindowTransformer for mirror root window. We simply copy the
212 // texture (bitmap) of the source display into the mirror window, so
213 // kthe root window bounds is the same as the source display's
James Cook 2013/05/29 12:22:43 kthe -> the
oshima 2013/05/29 15:39:49 Done.
214 // pixel size (excluding overscan insets).
215 class ASH_EXPORT MirrorRootWindowTransformer
216 : public aura::RootWindowTransformer {
217 public:
218 MirrorRootWindowTransformer(const DisplayInfo& source_display_info,
219 const DisplayInfo& mirror_display_info) {
220 root_bounds_ = gfx::Rect(source_display_info.bounds_in_pixel().size());
221 gfx::Rect mirror_display_rect =
222 gfx::Rect(mirror_display_info.bounds_in_pixel().size());
223
224 // TODO(oshima): Insets & scale has to be adjusted so that
225 // 1) it does letterbox/pillarbox to adjust aspect ration
James Cook 2013/05/29 12:22:43 ration -> ratio
oshima 2013/05/29 15:39:49 Done.
226 // 2) visible area excluding insets are corretly mapped
James Cook 2013/05/29 12:22:43 corretly -> correctly I'm like a human spelling-c
oshima 2013/05/29 15:39:49 Done.
227 // to the other display's visible area.
228 float mirror_scale_ratio =
229 (static_cast<float>(root_bounds_.width()) /
230 static_cast<float>(mirror_display_rect.width()));
231 float inverted_scale = 1.0f / mirror_scale_ratio;
232 transform_.Scale(inverted_scale, inverted_scale);
233 }
234
235 // aura::RootWindowTransformer overrides:
236 virtual gfx::Transform GetTransform() const OVERRIDE {
237 return transform_;
238 }
239 virtual gfx::Transform GetInverseTransform() const OVERRIDE {
240 gfx::Transform invert;
241 CHECK(transform_.GetInverse(&invert));
242 return invert;
243 }
244 virtual gfx::Rect GetRootWindowBounds(
245 const gfx::Size& host_size) const OVERRIDE {
246 return root_bounds_;
247 }
248 virtual gfx::Insets GetHostInsets() const OVERRIDE {
249 return gfx::Insets();
250 }
251
252 private:
253 virtual ~MirrorRootWindowTransformer() {}
254
255 gfx::Transform transform_;
256 gfx::Rect root_bounds_;
257
258 DISALLOW_COPY_AND_ASSIGN(MirrorRootWindowTransformer);
259 };
118 260
119 } // namespace 261 } // namespace
120 262
121 AshRootWindowTransformer::AshRootWindowTransformer(aura::RootWindow* root, 263 aura::RootWindowTransformer* CreateRootWindowTransformerForDisplay(
122 const gfx::Display& display) 264 aura::RootWindow* root,
123 : root_window_(root) { 265 const gfx::Display& display) {
124 root_window_bounds_transform_ = 266 return new AshRootWindowTransformer(root, display);
125 CreateOverscanAndUIScaleTransform(root, display) *
126 CreateRotationTransform(root, display);
127 transform_ = root_window_bounds_transform_ * CreateMagnifierTransform(root);
128 CHECK(transform_.GetInverse(&invert_transform_));
129
130 internal::DisplayInfo info = Shell::GetInstance()->
131 display_manager()->GetDisplayInfo(display.id());
132 root_window_ui_scale_ = info.ui_scale();
133 host_insets_ = info.GetOverscanInsetsInPixel();
134 MagnificationController* magnifier =
135 Shell::GetInstance()->magnification_controller();
136
137 bool scaled = (root_window_ui_scale_ != 1.f) ||
138 (magnifier && magnifier->GetScale() != 1.f);
139 root_window_->layer()->SetForceRenderSurface(scaled);
140 } 267 }
141 268
142 AshRootWindowTransformer::~AshRootWindowTransformer() {} 269 aura::RootWindowTransformer* CreateRootWindowTransformerForMirroredDisplay(
143 270 const DisplayInfo& source_display_info,
144 gfx::Transform AshRootWindowTransformer::GetTransform() const { 271 const DisplayInfo& mirror_display_info) {
145 return transform_; 272 return new MirrorRootWindowTransformer(source_display_info,
273 mirror_display_info);
146 } 274 }
147 275
148 gfx::Transform AshRootWindowTransformer::GetInverseTransform() const { 276 } // namespace internal
149 return invert_transform_;
150 }
151
152 gfx::Rect AshRootWindowTransformer::GetRootWindowBounds(
153 const gfx::Size& host_size) const {
154 gfx::Rect bounds(host_size);
155 bounds.Inset(host_insets_);
156 bounds = ui::ConvertRectToDIP(root_window_->layer(), bounds);
157 gfx::RectF new_bounds(bounds);
158 root_window_bounds_transform_.TransformRect(&new_bounds);
159 // Apply |root_window_scale_| twice as the downscaling
160 // is already applied once in |SetTransformInternal()|.
161 // TODO(oshima): This is a bit ugly. Consider specifying
162 // the pseudo host resolution instead.
163 new_bounds.Scale(root_window_ui_scale_ * root_window_ui_scale_);
164 // Ignore the origin because RootWindow's insets are handled by
165 // the transform.
166 // Floor the size because the bounds is no longer aligned to
167 // backing pixel when |root_window_scale_| is specified
168 // (850 height at 1.25 scale becomes 1062.5 for example.)
169 return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
170 }
171
172 gfx::Insets AshRootWindowTransformer::GetHostInsets() const {
173 return host_insets_;
174 }
175
176 } // namespace ash 277 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698