summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authoryoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-24 07:39:36 +0000
committeryoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-24 07:39:36 +0000
commit0ec58349766d2e02997baa3bf10e65aebb81c1fa (patch)
tree05adf36c4327adb06a8d3d133fe1d92164eaffd3 /ash
parentc694dbe24b86dc875cac1a229c559365955581a3 (diff)
downloadchromium_src-0ec58349766d2e02997baa3bf10e65aebb81c1fa.zip
chromium_src-0ec58349766d2e02997baa3bf10e65aebb81c1fa.tar.gz
chromium_src-0ec58349766d2e02997baa3bf10e65aebb81c1fa.tar.bz2
Let Magnifier, UI Scaling and Rotation use AshRootWindowTransformer to create transform matrix.
This patch enables us to use simultaneously these features. BUG=223983, 230979 TEST=ash_unittests and aura_unittests passes. R=oshima@chromium.org NOTRY=True # NOTRYing for trybots are already passed. Review URL: https://chromiumcodereview.appspot.com/13634002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196077 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/ash.gyp2
-rw-r--r--ash/ash_root_window_transformer.cc151
-rw-r--r--ash/ash_root_window_transformer.h17
-rw-r--r--ash/ash_root_window_transformer_unittest.cc405
-rw-r--r--ash/display/display_controller.cc65
-rw-r--r--ash/magnifier/magnification_controller.cc41
-rw-r--r--ash/magnifier/magnification_controller_unittest.cc2
7 files changed, 583 insertions, 100 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index d38804c..156e0e0 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -616,6 +616,7 @@
'accelerators/accelerator_filter_unittest.cc',
'accelerators/accelerator_table_unittest.cc',
'accelerators/nested_dispatcher_controller_unittest.cc',
+ 'ash_root_window_transformer_unittest.cc',
'desktop_background/desktop_background_controller_unittest.cc',
'dip_unittest.cc',
'display/display_controller_unittest.cc',
@@ -707,6 +708,7 @@
['exclude', 'accelerators/nested_dispatcher_controller_unittest.cc'],
['exclude', 'wm/drag_window_resizer_unittest.cc'],
# Can't resize on Windows Ash. http://crbug.com/165962
+ ['exclude', 'ash_root_window_transformer_unittest.cc'],
['exclude', 'magnifier/magnification_controller_unittest.cc'],
['exclude', 'wm/workspace/workspace_window_resizer_unittest.cc'],
],
diff --git a/ash/ash_root_window_transformer.cc b/ash/ash_root_window_transformer.cc
index e0aa26c..fa8a8a3 100644
--- a/ash/ash_root_window_transformer.cc
+++ b/ash/ash_root_window_transformer.cc
@@ -4,38 +4,143 @@
#include "ash/ash_root_window_transformer.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 "third_party/skia/include/utils/SkMatrix44.h"
#include "ui/aura/root_window.h"
+#include "ui/aura/window_property.h"
#include "ui/compositor/dip_util.h"
+#include "ui/gfx/display.h"
#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/transform.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(gfx::Display::Rotation);
namespace ash {
+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) {
+ internal::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;
+}
-AshRootWindowTransformer::AshRootWindowTransformer(
- aura::RootWindow* root,
- const gfx::Transform& transform,
- const gfx::Insets& host_insets,
- float root_window_scale)
- : root_window_(root),
- transform_(transform),
- root_window_scale_(root_window_scale),
- host_insets_(host_insets) {
- root_window_->layer()->SetForceRenderSurface(root_window_scale_ != 1.0f);
-
- gfx::Transform translate;
-
- if (host_insets.top() != 0 || host_insets.left() != 0) {
- float device_scale_factor = ui::GetDeviceScaleFactor(root_window_->layer());
- float x_offset = host_insets.left() / device_scale_factor;
- float y_offset = host_insets.top() / device_scale_factor;
- translate.Translate(x_offset, y_offset);
+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());
}
- float inverted_scale = 1.0f / root_window_scale_;
- translate.Scale(inverted_scale, inverted_scale);
- transform_ = translate * transform;
+ return transform;
+}
+gfx::Transform CreateOverscanAndUIScaleTransform(aura::RootWindow* root_window,
+ const gfx::Display& display) {
+ internal::DisplayInfo info =
+ Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id());
+ gfx::Insets insets = info.GetOverscanInsetsInPixel();
+ float scale = info.ui_scale();
+
+ gfx::Transform transform;
+ if (insets.top() != 0 || insets.left() != 0) {
+ float device_scale_factor = ui::GetDeviceScaleFactor(root_window->layer());
+ 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 / scale;
+ transform.Scale(inverted_scale, inverted_scale);
+ return transform;
+}
+
+} // namespace
+
+AshRootWindowTransformer::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_));
+
+ internal::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);
}
+AshRootWindowTransformer::~AshRootWindowTransformer() {}
+
gfx::Transform AshRootWindowTransformer::GetTransform() const {
return transform_;
}
@@ -50,12 +155,12 @@ gfx::Rect AshRootWindowTransformer::GetRootWindowBounds(
bounds.Inset(host_insets_);
bounds = ui::ConvertRectToDIP(root_window_->layer(), bounds);
gfx::RectF new_bounds(bounds);
- root_window_->layer()->transform().TransformRect(&new_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_scale_ * root_window_scale_);
+ 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
diff --git a/ash/ash_root_window_transformer.h b/ash/ash_root_window_transformer.h
index d8b7900..424a6cf 100644
--- a/ash/ash_root_window_transformer.h
+++ b/ash/ash_root_window_transformer.h
@@ -7,6 +7,7 @@
#include "ash/ash_export.h"
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "ui/aura/root_window_transformer.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/transform.h"
@@ -15,15 +16,17 @@ namespace aura {
class RootWindow;
}
+namespace gfx {
+class Display;
+}
+
namespace ash {
// RootWindowTransformer for ash environment.
class ASH_EXPORT AshRootWindowTransformer : public aura::RootWindowTransformer {
public:
AshRootWindowTransformer(aura::RootWindow* root,
- const gfx::Transform& transform,
- const gfx::Insets& insets,
- float root_window_scale);
+ const gfx::Display& display);
// aura::RootWindowTransformer overrides:
virtual gfx::Transform GetTransform() const OVERRIDE;
virtual gfx::Transform GetInverseTransform() const OVERRIDE;
@@ -32,7 +35,7 @@ class ASH_EXPORT AshRootWindowTransformer : public aura::RootWindowTransformer {
virtual gfx::Insets GetHostInsets() const OVERRIDE;
private:
- virtual ~AshRootWindowTransformer() {}
+ virtual ~AshRootWindowTransformer();
aura::RootWindow* root_window_;
gfx::Transform transform_;
@@ -42,11 +45,15 @@ class ASH_EXPORT AshRootWindowTransformer : public aura::RootWindowTransformer {
// |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_scale_;
+ float root_window_ui_scale_;
gfx::Insets host_insets_;
diff --git a/ash/ash_root_window_transformer_unittest.cc b/ash/ash_root_window_transformer_unittest.cc
new file mode 100644
index 0000000..c4a1d1e
--- /dev/null
+++ b/ash/ash_root_window_transformer_unittest.cc
@@ -0,0 +1,405 @@
+// 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/ash_root_window_transformer.h"
+
+#include "ash/display/display_controller.h"
+#include "ash/display/display_info.h"
+#include "ash/display/display_manager.h"
+#include "ash/launcher/launcher.h"
+#include "ash/magnifier/magnification_controller.h"
+#include "ash/screen_ash.h"
+#include "ash/shelf/shelf_widget.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test/cursor_manager_test_api.h"
+#include "base/synchronization/waitable_event.h"
+#include "ui/aura/env.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window_tracker.h"
+#include "ui/base/events/event_handler.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+namespace test {
+
+namespace {
+
+const char kDesktopBackgroundView[] = "DesktopBackgroundView";
+
+class TestEventHandler : public ui::EventHandler {
+ public:
+ TestEventHandler() : target_root_(NULL),
+ touch_radius_x_(0.0),
+ touch_radius_y_(0.0),
+ scroll_x_offset_(0.0),
+ scroll_y_offset_(0.0),
+ scroll_x_offset_ordinal_(0.0),
+ scroll_y_offset_ordinal_(0.0) {}
+ virtual ~TestEventHandler() {}
+
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ if (event->flags() & ui::EF_IS_SYNTHESIZED)
+ return;
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ mouse_location_ = event->root_location();
+ target_root_ = target->GetRootWindow();
+ event->StopPropagation();
+ }
+
+ virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ // Only record when the target is the background which covers
+ // entire root window.
+ if (target->name() != kDesktopBackgroundView)
+ return;
+ touch_radius_x_ = event->radius_x();
+ touch_radius_y_ = event->radius_y();
+ event->StopPropagation();
+ }
+
+ virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ // Only record when the target is the background which covers
+ // entire root window.
+ if (target->name() != kDesktopBackgroundView)
+ return;
+
+ if (event->type() == ui::ET_SCROLL) {
+ scroll_x_offset_ = event->x_offset();
+ scroll_y_offset_ = event->y_offset();
+ scroll_x_offset_ordinal_ = event->x_offset_ordinal();
+ scroll_y_offset_ordinal_ = event->y_offset_ordinal();
+ }
+ event->StopPropagation();
+ }
+
+ std::string GetLocationAndReset() {
+ std::string result = mouse_location_.ToString();
+ mouse_location_.SetPoint(0, 0);
+ target_root_ = NULL;
+ return result;
+ }
+
+ float touch_radius_x() const { return touch_radius_x_; }
+ float touch_radius_y() const { return touch_radius_y_; }
+ float scroll_x_offset() const { return scroll_x_offset_; }
+ float scroll_y_offset() const { return scroll_y_offset_; }
+ float scroll_x_offset_ordinal() const { return scroll_x_offset_ordinal_; }
+ float scroll_y_offset_ordinal() const { return scroll_y_offset_ordinal_; }
+
+ private:
+ gfx::Point mouse_location_;
+ aura::RootWindow* target_root_;
+
+ float touch_radius_x_;
+ float touch_radius_y_;
+ float scroll_x_offset_;
+ float scroll_y_offset_;
+ float scroll_x_offset_ordinal_;
+ float scroll_y_offset_ordinal_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
+};
+
+gfx::Display::Rotation GetStoredRotation(int64 id) {
+ return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation();
+}
+
+float GetStoredUIScale(int64 id) {
+ return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).ui_scale();
+}
+
+void MoveMouseToInHostCoord(aura::RootWindow* root_window,
+ int host_x,
+ int host_y) {
+ gfx::Point move_point(host_x, host_y);
+ ui::MouseEvent mouseev(ui::ET_MOUSE_MOVED, move_point, move_point, 0);
+ root_window->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouseev);
+}
+
+} // namespace
+
+typedef test::AshTestBase AshRootWindowTransformerTest;
+
+#if defined(OS_WIN)
+// On Win8 bots, the host window can't be resized and
+// SetTransform updates the window using the orignal host window
+// size.
+#define MAYBE_RotateAndMagnify DISABLED_RotateAndMagniy
+#define MAYBE_ScaleAndMagnify DISABLED_ScaleAndMagnify
+#define MAYBE_TouchScaleAndMagnify DISABLED_TouchScaleAndMagnify
+#define MAYBE_ConvertHostToRootCoords DISABLED_ConvertHostToRootCoords
+#else
+#define MAYBE_RotateAndMagnify RotateAndMagniy
+#define MAYBE_ScaleAndMagnify ScaleAndMagnify
+#define MAYBE_TouchScaleAndMagnify TouchScaleAndMagnify
+#define MAYBE_ConvertHostToRootCoords ConvertHostToRootCoords
+#endif
+
+TEST_F(AshRootWindowTransformerTest, MAYBE_RotateAndMagnify) {
+ DisplayController* display_controller =
+ Shell::GetInstance()->display_controller();
+ MagnificationController* magnifier =
+ Shell::GetInstance()->magnification_controller();
+ internal::DisplayManager* display_manager =
+ Shell::GetInstance()->display_manager();
+
+ TestEventHandler event_handler;
+ Shell::GetInstance()->AddPreTargetHandler(&event_handler);
+
+ UpdateDisplay("120x200,300x400*2");
+ gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
+ int64 display2_id = ScreenAsh::GetSecondaryDisplay().id();
+
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ aura::test::EventGenerator generator1(root_windows[0]);
+ aura::test::EventGenerator generator2(root_windows[1]);
+
+ magnifier->SetEnabled(true);
+ EXPECT_EQ(2.0f, magnifier->GetScale());
+ EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
+ EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
+ EXPECT_EQ("120,0 150x200",
+ ScreenAsh::GetSecondaryDisplay().bounds().ToString());
+ generator1.MoveMouseTo(40, 80);
+ EXPECT_EQ("50,90", event_handler.GetLocationAndReset());
+ EXPECT_EQ("50,90",
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+ EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id()));
+ EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
+ magnifier->SetEnabled(false);
+
+ display_manager->SetDisplayRotation(display1.id(),
+ gfx::Display::ROTATE_90);
+ // Move the cursor to the center of the first root window.
+ generator1.MoveMouseTo(59, 100);
+
+ magnifier->SetEnabled(true);
+ EXPECT_EQ(2.0f, magnifier->GetScale());
+ EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
+ EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
+ EXPECT_EQ("200,0 150x200",
+ ScreenAsh::GetSecondaryDisplay().bounds().ToString());
+ generator1.MoveMouseTo(39, 120);
+ EXPECT_EQ("110,70", event_handler.GetLocationAndReset());
+ EXPECT_EQ("110,70",
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+ EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
+ EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
+ magnifier->SetEnabled(false);
+
+ DisplayLayout display_layout(DisplayLayout::BOTTOM, 50);
+ display_controller->SetLayoutForCurrentDisplays(display_layout);
+ EXPECT_EQ("50,120 150x200",
+ ScreenAsh::GetSecondaryDisplay().bounds().ToString());
+
+ display_manager->SetDisplayRotation(display2_id,
+ gfx::Display::ROTATE_270);
+ // Move the cursor to the center of the second root window.
+ generator2.MoveMouseTo(151, 199);
+
+ magnifier->SetEnabled(true);
+ EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
+ EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
+ EXPECT_EQ("50,120 200x150",
+ ScreenAsh::GetSecondaryDisplay().bounds().ToString());
+ generator2.MoveMouseTo(172, 219);
+ EXPECT_EQ("95,80", event_handler.GetLocationAndReset());
+ EXPECT_EQ("169,175",
+ aura::Env::GetInstance()->last_mouse_location().ToString());
+ EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
+ EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
+ magnifier->SetEnabled(false);
+
+ display_manager->SetDisplayRotation(display1.id(),
+ gfx::Display::ROTATE_180);
+ // Move the cursor to the center of the first root window.
+ generator1.MoveMouseTo(59, 99);
+
+ magnifier->SetEnabled(true);
+ EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
+ EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
+ // Dislay must share at least 100, so the x's offset becomes 20.
+ EXPECT_EQ("20,200 200x150",
+ ScreenAsh::GetSecondaryDisplay().bounds().ToString());
+ generator1.MoveMouseTo(39, 59);
+ EXPECT_EQ("70,120", event_handler.GetLocationAndReset());
+ EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id()));
+ EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
+ magnifier->SetEnabled(false);
+
+ Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
+}
+
+TEST_F(AshRootWindowTransformerTest, MAYBE_ScaleAndMagnify) {
+ TestEventHandler event_handler;
+ Shell::GetInstance()->AddPreTargetHandler(&event_handler);
+
+ UpdateDisplay("600x400*2@1.5,500x300");
+
+ gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
+ gfx::Display::SetInternalDisplayId(display1.id());
+ gfx::Display display2 = ScreenAsh::GetSecondaryDisplay();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ MagnificationController* magnifier =
+ Shell::GetInstance()->magnification_controller();
+
+ magnifier->SetEnabled(true);
+ EXPECT_EQ(2.0f, magnifier->GetScale());
+ EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
+ EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
+ EXPECT_EQ("450,0 500x300", display2.bounds().ToString());
+ EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
+ EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
+
+ aura::test::EventGenerator generator(root_windows[0]);
+ generator.MoveMouseTo(500, 200);
+ EXPECT_EQ("299,150", event_handler.GetLocationAndReset());
+ magnifier->SetEnabled(false);
+
+ internal::DisplayManager* display_manager =
+ Shell::GetInstance()->display_manager();
+ display_manager->SetDisplayUIScale(display1.id(), 1.25);
+ display1 = Shell::GetScreen()->GetPrimaryDisplay();
+ display2 = ScreenAsh::GetSecondaryDisplay();
+ magnifier->SetEnabled(true);
+ EXPECT_EQ(2.0f, magnifier->GetScale());
+ EXPECT_EQ("0,0 375x250", display1.bounds().ToString());
+ EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString());
+ EXPECT_EQ("375,0 500x300", display2.bounds().ToString());
+ EXPECT_EQ(1.25f, GetStoredUIScale(display1.id()));
+ EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
+ magnifier->SetEnabled(false);
+
+ Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
+}
+
+TEST_F(AshRootWindowTransformerTest, MAYBE_TouchScaleAndMagnify) {
+ TestEventHandler event_handler;
+ Shell::GetInstance()->AddPreTargetHandler(&event_handler);
+
+ UpdateDisplay("200x200*2");
+ gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ aura::RootWindow* root_window = root_windows[0];
+ aura::test::EventGenerator generator(root_window);
+ MagnificationController* magnifier =
+ Shell::GetInstance()->magnification_controller();
+
+ magnifier->SetEnabled(true);
+ EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
+ magnifier->SetScale(2.5f, false);
+ EXPECT_FLOAT_EQ(2.5f, magnifier->GetScale());
+ generator.PressMoveAndReleaseTouchTo(50, 50);
+ // Default test touches have radius_x/y = 1.0, with device scale
+ // factor = 2, the scaled radius_x/y should be 0.5.
+ EXPECT_FLOAT_EQ(0.2, event_handler.touch_radius_x());
+ EXPECT_FLOAT_EQ(0.2, event_handler.touch_radius_y());
+
+ generator.ScrollSequence(gfx::Point(0,0),
+ base::TimeDelta::FromMilliseconds(100),
+ 10.0, 1.0, 5, 1);
+
+ // With device scale factor = 2, ordinal_offset * 2 = offset.
+ EXPECT_FLOAT_EQ(event_handler.scroll_x_offset(),
+ event_handler.scroll_x_offset_ordinal() * 2 * 2.5f);
+ EXPECT_FLOAT_EQ(event_handler.scroll_y_offset(),
+ event_handler.scroll_y_offset_ordinal() * 2 * 2.5f);
+ magnifier->SetEnabled(false);
+
+ Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
+}
+
+TEST_F(AshRootWindowTransformerTest, MAYBE_ConvertHostToRootCoords) {
+ TestEventHandler event_handler;
+ Shell::GetInstance()->AddPreTargetHandler(&event_handler);
+ MagnificationController* magnifier =
+ Shell::GetInstance()->magnification_controller();
+
+ // Test 1
+ UpdateDisplay("600x400*2/r@1.5");
+
+ gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+ EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
+ EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
+ EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
+
+ MoveMouseToInHostCoord(root_windows[0], 300, 200);
+ magnifier->SetEnabled(true);
+ EXPECT_EQ("150,224", event_handler.GetLocationAndReset());
+ EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
+
+ MoveMouseToInHostCoord(root_windows[0], 300, 200);
+ EXPECT_EQ("150,224", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 200, 300);
+ EXPECT_EQ("187,261", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 100, 400);
+ EXPECT_EQ("237,299", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 0, 0);
+ EXPECT_EQ("137,348", event_handler.GetLocationAndReset());
+
+ magnifier->SetEnabled(false);
+ EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale());
+
+ // Test 2
+ UpdateDisplay("600x400*2/u@1.5");
+ display1 = Shell::GetScreen()->GetPrimaryDisplay();
+ root_windows = Shell::GetAllRootWindows();
+ EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
+ EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
+ EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
+
+ MoveMouseToInHostCoord(root_windows[0], 300, 200);
+ magnifier->SetEnabled(true);
+ EXPECT_EQ("224,149", event_handler.GetLocationAndReset());
+ EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
+
+ MoveMouseToInHostCoord(root_windows[0], 300, 200);
+ EXPECT_EQ("224,148", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 200, 300);
+ EXPECT_EQ("261,111", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 100, 400);
+ EXPECT_EQ("299,60", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 0, 0);
+ EXPECT_EQ("348,159", event_handler.GetLocationAndReset());
+
+ magnifier->SetEnabled(false);
+ EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale());
+
+ // Test 3
+ UpdateDisplay("600x400*2/l@1.5");
+ display1 = Shell::GetScreen()->GetPrimaryDisplay();
+ root_windows = Shell::GetAllRootWindows();
+ EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
+ EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
+ EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
+
+ MoveMouseToInHostCoord(root_windows[0], 300, 200);
+ magnifier->SetEnabled(true);
+ EXPECT_EQ("149,225", event_handler.GetLocationAndReset());
+ EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
+
+ MoveMouseToInHostCoord(root_windows[0], 300, 200);
+ EXPECT_EQ("148,224", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 200, 300);
+ EXPECT_EQ("111,187", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 100, 400);
+ EXPECT_EQ("60,149", event_handler.GetLocationAndReset());
+ MoveMouseToInHostCoord(root_windows[0], 0, 0);
+ EXPECT_EQ("159,99", event_handler.GetLocationAndReset());
+
+ magnifier->SetEnabled(false);
+ EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale());
+
+ Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
+}
+
+} // namespace test
+} // namespace ash
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index cba80e2..87b22a8 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -54,14 +54,9 @@
#undef RootWindow
#endif // defined(OS_CHROMEOS)
-DECLARE_WINDOW_PROPERTY_TYPE(gfx::Display::Rotation);
-
namespace ash {
namespace {
-DEFINE_WINDOW_PROPERTY_KEY(gfx::Display::Rotation, kRotationPropertyKey,
- gfx::Display::ROTATE_0);
-
// Primary display stored in global object as it can be
// accessed after Shell is deleted. A separate display instance is created
// during the shutdown instead of always keeping two display instances
@@ -129,62 +124,6 @@ internal::DisplayManager* GetDisplayManager() {
return Shell::GetInstance()->display_manager();
}
-// 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));
- }
- }
-}
-
-void RotateRootWindow(aura::RootWindow* root_window,
- const gfx::Display& display,
- const internal::DisplayInfo& info) {
- // 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;
- 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);
-
- scoped_ptr<aura::RootWindowTransformer> transformer(
- new AshRootWindowTransformer(root_window,
- rotate,
- info.GetOverscanInsetsInPixel(),
- info.ui_scale()));
- root_window->SetRootWindowTransformer(transformer.Pass());
-}
-
void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
const gfx::Display& display) {
internal::DisplayInfo info =
@@ -226,7 +165,9 @@ void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
kCARDINAL,
100 * display.device_scale_factor());
#endif
- RotateRootWindow(root, display, info);
+ scoped_ptr<aura::RootWindowTransformer> transformer(
+ new AshRootWindowTransformer(root, display));
+ root->SetRootWindowTransformer(transformer.Pass());
}
} // namespace
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc
index ba1de9e..21cb63b 100644
--- a/ash/magnifier/magnification_controller.cc
+++ b/ash/magnifier/magnification_controller.cc
@@ -4,12 +4,15 @@
#include "ash/magnifier/magnification_controller.h"
+#include "ash/ash_root_window_transformer.h"
#include "ash/display/display_controller.h"
+#include "ash/display/display_manager.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/root_window.h"
+#include "ui/aura/root_window_transformer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_property.h"
#include "ui/base/events/event.h"
@@ -18,6 +21,7 @@
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/point3_f.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/point_f.h"
#include "ui/gfx/rect_conversions.h"
@@ -38,6 +42,14 @@ const float kScrollScaleChangeFactor = 0.05f;
// |kPanningMergin| from the edge, the view-port moves.
const int kPanningMergin = 100;
+void MoveCursorTo(aura::RootWindow* root_window,
+ const gfx::Point root_location) {
+ gfx::Point3F host_location_3f(root_location);
+ root_window->layer()->transform().TransformPoint(host_location_3f);
+ root_window->MoveCursorToHostLoation(
+ gfx::ToCeiledPoint(host_location_3f.AsPointF()));
+}
+
} // namespace
namespace ash {
@@ -74,6 +86,9 @@ class MagnificationControllerImpl : virtual public MagnificationController,
// aura::WindowObserver overrides:
virtual void OnWindowDestroying(aura::Window* root_window) OVERRIDE;
+ virtual void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) OVERRIDE;
// Redraws the magnification window with the given origin position and the
// given scale. Returns true if the window is changed; otherwise, false.
@@ -251,7 +266,11 @@ bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip,
settings.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(animate ? 100 : 0));
- root_window_->layer()->SetTransform(transform);
+ gfx::Display display =
+ Shell::GetScreen()->GetDisplayNearestWindow(root_window_);
+ scoped_ptr<aura::RootWindowTransformer> transformer(
+ new AshRootWindowTransformer(root_window_, display));
+ root_window_->SetRootWindowTransformer(transformer.Pass());
if (animate)
is_on_animation_ = true;
@@ -358,7 +377,7 @@ void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) {
if (ret) {
// If the magnified region is moved, hides the mouse cursor and moves it.
if (x_diff != 0 || y_diff != 0)
- root_window_->MoveCursorTo(mouse);
+ MoveCursorTo(root_window_, mouse);
}
}
}
@@ -381,14 +400,11 @@ void MagnificationControllerImpl::AfterAnimationMoveCursorTo(
}
gfx::Size MagnificationControllerImpl::GetHostSizeDIP() const {
- return ui::ConvertSizeToDIP(root_window_->layer(),
- root_window_->GetHostSize());
+ return root_window_->bounds().size();
}
gfx::RectF MagnificationControllerImpl::GetWindowRectDIP(float scale) const {
- const gfx::Size size_in_dip =
- ui::ConvertSizeToDIP(root_window_->layer(),
- root_window_->GetHostSize());
+ const gfx::Size size_in_dip = root_window_->bounds().size();
const float width = size_in_dip.width() / scale;
const float height = size_in_dip.height() / scale;
@@ -418,7 +434,7 @@ void MagnificationControllerImpl::OnImplicitAnimationsCompleted() {
return;
if (move_cursor_after_animation_) {
- root_window_->MoveCursorTo(position_after_animation_);
+ MoveCursorTo(root_window_, position_after_animation_);
move_cursor_after_animation_ = false;
aura::client::CursorClient* cursor_client =
@@ -448,6 +464,13 @@ void MagnificationControllerImpl::OnWindowDestroying(
}
}
+void MagnificationControllerImpl::OnWindowBoundsChanged(
+ aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ // TODO(yoshiki): implement here. crbug.com/230979
+}
+
void MagnificationControllerImpl::SwitchTargetRootWindow(
aura::RootWindow* new_root_window,
bool redraw_original_root_window) {
@@ -526,9 +549,9 @@ void MagnificationControllerImpl::SetEnabled(bool enabled) {
if (is_enabled_ && scale == scale_)
return;
+ is_enabled_ = enabled;
RedrawKeepingMousePosition(scale, true);
ash::Shell::GetInstance()->delegate()->SaveScreenMagnifierScale(scale);
- is_enabled_ = enabled;
} else {
// Do nothing, if already disabled.
if (!is_enabled_)
diff --git a/ash/magnifier/magnification_controller_unittest.cc b/ash/magnifier/magnification_controller_unittest.cc
index 2060df4..b26ec36 100644
--- a/ash/magnifier/magnification_controller_unittest.cc
+++ b/ash/magnifier/magnification_controller_unittest.cc
@@ -107,7 +107,7 @@ TEST_F(MagnificationControllerTest, MagnifyAndUnmagnify) {
GetMagnificationController()->SetScale(3.0f, false);
EXPECT_EQ(3.0f, GetMagnificationController()->GetScale());
- EXPECT_EQ("266,200 268x200", GetViewport().ToString());
+ EXPECT_EQ("266,200 267x200", GetViewport().ToString());
}
TEST_F(MagnificationControllerTest, MoveWindow) {