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

Unified 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: addressed comments Created 7 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ash/display/root_window_transformers.h ('k') | ash/display/root_window_transformers_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ash/display/root_window_transformers.cc
diff --git a/ash/display/root_window_transformers.cc b/ash/display/root_window_transformers.cc
new file mode 100644
index 0000000000000000000000000000000000000000..da5c3975e2c58afdfaa36bcd502e61ea54d5ae43
--- /dev/null
+++ b/ash/display/root_window_transformers.cc
@@ -0,0 +1,276 @@
+// Copyright (c) 2013 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 "ash/display/root_window_transformers.h"
+
+#include <cmath>
+
+#include "ash/display/display_info.h"
+#include "ash/display/display_manager.h"
+#include "ash/magnifier/magnification_controller.h"
+#include "ash/shell.h"
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/utils/SkMatrix44.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/root_window_transformer.h"
+#include "ui/aura/window_property.h"
+#include "ui/compositor/dip_util.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/transform.h"
+#include "ui/gfx/transform.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(gfx::Display::Rotation);
+
+namespace ash {
+namespace internal {
+namespace {
+
+DEFINE_WINDOW_PROPERTY_KEY(gfx::Display::Rotation, kRotationPropertyKey,
+ gfx::Display::ROTATE_0);
+
+// Round near zero value to zero.
+void RoundNearZero(gfx::Transform* transform) {
+ const float kEpsilon = 0.001f;
+ SkMatrix44& matrix = transform->matrix();
+ for (int x = 0; x < 4; ++x) {
+ for (int y = 0; y < 4; ++y) {
+ if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon)
+ matrix.set(x, y, SkFloatToMScalar(0.0f));
+ }
+ }
+}
+
+gfx::Transform CreateRotationTransform(aura::RootWindow* root_window,
+ const gfx::Display& display) {
+ DisplayInfo info =
+ Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
+
+ // TODO(oshima): Add animation. (crossfade+rotation, or just cross-fade)
+#if defined(OS_WIN)
+ // Windows 8 bots refused to resize the host window, and
+ // updating the transform results in incorrectly resizing
+ // the root window. Don't apply the transform unless
+ // necessary so that unit tests pass on win8 bots.
+ if (info.rotation() == root_window->GetProperty(kRotationPropertyKey))
+ return gfx::Transform();
+ root_window->SetProperty(kRotationPropertyKey, info.rotation());
+#endif
+
+ gfx::Transform rotate;
+ // The origin is (0, 0), so the translate width/height must be reduced by
+ // 1 pixel.
+ float one_pixel = 1.0f / display.device_scale_factor();
+ switch (info.rotation()) {
+ case gfx::Display::ROTATE_0:
+ break;
+ case gfx::Display::ROTATE_90:
+ rotate.Translate(display.bounds().height() - one_pixel, 0);
+ rotate.Rotate(90);
+ break;
+ case gfx::Display::ROTATE_270:
+ rotate.Translate(0, display.bounds().width() - one_pixel);
+ rotate.Rotate(270);
+ break;
+ case gfx::Display::ROTATE_180:
+ rotate.Translate(display.bounds().width() - one_pixel,
+ display.bounds().height() - one_pixel);
+ rotate.Rotate(180);
+ break;
+ }
+
+ RoundNearZero(&rotate);
+ return rotate;
+}
+
+gfx::Transform CreateMagnifierTransform(aura::RootWindow* root_window) {
+ MagnificationController* magnifier =
+ Shell::GetInstance()->magnification_controller();
+ float magnifier_scale = 1.f;
+ gfx::Point magnifier_offset;
+ if (magnifier && magnifier->IsEnabled()) {
+ magnifier_scale = magnifier->GetScale();
+ magnifier_offset = magnifier->GetWindowPosition();
+ }
+ gfx::Transform transform;
+ if (magnifier_scale != 1.f) {
+ transform.Scale(magnifier_scale, magnifier_scale);
+ transform.Translate(-magnifier_offset.x(), -magnifier_offset.y());
+ }
+ return transform;
+}
+
+gfx::Transform CreateInsetsAndScaleTransform(const gfx::Insets& insets,
+ float device_scale_factor,
+ float ui_scale) {
+ gfx::Transform transform;
+ if (insets.top() != 0 || insets.left() != 0) {
+ float x_offset = insets.left() / device_scale_factor;
+ float y_offset = insets.top() / device_scale_factor;
+ transform.Translate(x_offset, y_offset);
+ }
+ float inverted_scale = 1.0f / ui_scale;
+ transform.Scale(inverted_scale, inverted_scale);
+ return transform;
+}
+
+gfx::Transform CreateOverscanAndUIScaleTransform(aura::RootWindow* root_window,
+ const gfx::Display& display) {
+ DisplayInfo info =
+ Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
+ return CreateInsetsAndScaleTransform(
+ info.GetOverscanInsetsInPixel(),
+ ui::GetDeviceScaleFactor(root_window->layer()),
+ info.ui_scale());
+}
+
+// RootWindowTransformer for ash environment.
+class AshRootWindowTransformer : public aura::RootWindowTransformer {
+ public:
+ AshRootWindowTransformer(aura::RootWindow* root,
+ const gfx::Display& display)
+ : root_window_(root) {
+ root_window_bounds_transform_ =
+ CreateOverscanAndUIScaleTransform(root, display) *
+ CreateRotationTransform(root, display);
+ transform_ = root_window_bounds_transform_ * CreateMagnifierTransform(root);
+ CHECK(transform_.GetInverse(&invert_transform_));
+
+ DisplayInfo info = Shell::GetInstance()->display_manager()->
+ GetDisplayInfo(display.id());
+ root_window_ui_scale_ = info.ui_scale();
+ host_insets_ = info.GetOverscanInsetsInPixel();
+ MagnificationController* magnifier =
+ Shell::GetInstance()->magnification_controller();
+
+ bool scaled = (root_window_ui_scale_ != 1.f) ||
+ (magnifier && magnifier->GetScale() != 1.f);
+ root_window_->layer()->SetForceRenderSurface(scaled);
+ }
+
+ // aura::RootWindowTransformer overrides:
+ virtual gfx::Transform GetTransform() const OVERRIDE {
+ return transform_;
+ }
+ virtual gfx::Transform GetInverseTransform() const OVERRIDE {
+ return invert_transform_;
+ }
+ virtual gfx::Rect GetRootWindowBounds(
+ const gfx::Size& host_size) const OVERRIDE {
+ gfx::Rect bounds(host_size);
+ bounds.Inset(host_insets_);
+ bounds = ui::ConvertRectToDIP(root_window_->layer(), bounds);
+ gfx::RectF new_bounds(bounds);
+ root_window_bounds_transform_.TransformRect(&new_bounds);
+ // Apply |root_window_scale_| twice as the downscaling
+ // is already applied once in |SetTransformInternal()|.
+ // TODO(oshima): This is a bit ugly. Consider specifying
+ // the pseudo host resolution instead.
+ new_bounds.Scale(root_window_ui_scale_ * root_window_ui_scale_);
+ // Ignore the origin because RootWindow's insets are handled by
+ // the transform.
+ // Floor the size because the bounds is no longer aligned to
+ // backing pixel when |root_window_scale_| is specified
+ // (850 height at 1.25 scale becomes 1062.5 for example.)
+ return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
+ }
+
+ virtual gfx::Insets GetHostInsets() const OVERRIDE {
+ return host_insets_;
+ }
+
+ private:
+ virtual ~AshRootWindowTransformer() {}
+
+ aura::RootWindow* root_window_;
+ gfx::Transform transform_;
+
+ // The accurate representation of the inverse of the |transform_|.
+ // This is used to avoid computation error caused by
+ // |gfx::Transform::GetInverse|.
+ gfx::Transform invert_transform_;
+
+ // The transform of the root window bounds. This is used to calculate
+ // the size of root window.
+ gfx::Transform root_window_bounds_transform_;
+
+ // The scale of the root window. This is used to expand the
+ // area of the root window (useful in HighDPI display).
+ // Note that this should not be confused with the device scale
+ // factor, which specfies the pixel density of the display.
+ float root_window_ui_scale_;
+
+ gfx::Insets host_insets_;
+
+ DISALLOW_COPY_AND_ASSIGN(AshRootWindowTransformer);
+};
+
+// RootWindowTransformer for mirror root window. We simply copy the
+// texture (bitmap) of the source display into the mirror window, so
+// the root window bounds is the same as the source display's
+// pixel size (excluding overscan insets).
+class MirrorRootWindowTransformer : public aura::RootWindowTransformer {
+ public:
+ MirrorRootWindowTransformer(const DisplayInfo& source_display_info,
+ const DisplayInfo& mirror_display_info) {
+ root_bounds_ = gfx::Rect(source_display_info.bounds_in_pixel().size());
+ gfx::Rect mirror_display_rect =
+ gfx::Rect(mirror_display_info.bounds_in_pixel().size());
+
+ // TODO(oshima): Insets & scale has to be adjusted so that
+ // 1) it does letterbox/pillarbox to adjust aspect ratio
+ // 2) visible area excluding insets are correctly mapped
+ // to the other display's visible area.
+ float mirror_scale_ratio =
+ (static_cast<float>(root_bounds_.width()) /
+ static_cast<float>(mirror_display_rect.width()));
+ float inverted_scale = 1.0f / mirror_scale_ratio;
+ transform_.Scale(inverted_scale, inverted_scale);
+ }
+
+ // aura::RootWindowTransformer overrides:
+ virtual gfx::Transform GetTransform() const OVERRIDE {
+ return transform_;
+ }
+ virtual gfx::Transform GetInverseTransform() const OVERRIDE {
+ gfx::Transform invert;
+ CHECK(transform_.GetInverse(&invert));
+ return invert;
+ }
+ virtual gfx::Rect GetRootWindowBounds(
+ const gfx::Size& host_size) const OVERRIDE {
+ return root_bounds_;
+ }
+ virtual gfx::Insets GetHostInsets() const OVERRIDE {
+ return gfx::Insets();
+ }
+
+ private:
+ virtual ~MirrorRootWindowTransformer() {}
+
+ gfx::Transform transform_;
+ gfx::Rect root_bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(MirrorRootWindowTransformer);
+};
+
+} // namespace
+
+aura::RootWindowTransformer* CreateRootWindowTransformerForDisplay(
+ aura::RootWindow* root,
+ const gfx::Display& display) {
+ return new AshRootWindowTransformer(root, display);
+}
+
+aura::RootWindowTransformer* CreateRootWindowTransformerForMirroredDisplay(
+ const DisplayInfo& source_display_info,
+ const DisplayInfo& mirror_display_info) {
+ return new MirrorRootWindowTransformer(source_display_info,
+ mirror_display_info);
+}
+
+} // namespace internal
+} // namespace ash
« no previous file with comments | « ash/display/root_window_transformers.h ('k') | ash/display/root_window_transformers_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698