summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-20 16:11:21 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-20 16:11:21 +0000
commite1850856986a812c7a84fbc34899a6c5af8187f8 (patch)
tree1954dd261d8b80da778bac1ac2e90aa3a84cb439
parentf66f1c0b76001e9e988827fab799eeab704c9f16 (diff)
downloadchromium_src-e1850856986a812c7a84fbc34899a6c5af8187f8.zip
chromium_src-e1850856986a812c7a84fbc34899a6c5af8187f8.tar.gz
chromium_src-e1850856986a812c7a84fbc34899a6c5af8187f8.tar.bz2
events: Fix event-targeting for transformed windows.
Applying the transforms on a Window's bounds does not give the correct transformed bounds of the window in its parent's coordinate system. For example, a Window with size 300x200 at position 20,10 and scaled at 50% has bounds (20, 10, 150, 100), and not (10, 5, 150, 100). So remove this transform from the window-targeting code, and instead convert the event's location to be in the child Window's coordinate system when doing hit-testing. This fixes selecting windows when in overview mode. BUG=339834 R=sky@chromium.org Review URL: https://codereview.chromium.org/167323004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@252257 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/wm/overview/window_selector_unittest.cc46
-rw-r--r--ui/aura/window_targeter.cc8
-rw-r--r--ui/aura/window_targeter_unittest.cc56
-rw-r--r--ui/wm/core/easy_resize_window_targeter.cc19
4 files changed, 116 insertions, 13 deletions
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index db3c6fb5..c23fedc 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -198,6 +198,20 @@ class WindowSelectorTest : public test::AshTestBase {
return bounds;
}
+ gfx::RectF GetTransformedBoundsInRootWindow(aura::Window* window) {
+ gfx::RectF bounds = gfx::Rect(window->bounds().size());
+ aura::Window* root = window->GetRootWindow();
+ CHECK(window->layer());
+ CHECK(root->layer());
+ gfx::Transform transform;
+ if (!window->layer()->GetTargetTransformRelativeTo(root->layer(),
+ &transform)) {
+ return gfx::RectF();
+ }
+ transform.TransformRect(&bounds);
+ return bounds;
+ }
+
void ClickWindow(aura::Window* window) {
aura::test::EventGenerator event_generator(window->GetRootWindow(), window);
gfx::RectF target = GetTransformedBounds(window);
@@ -1030,5 +1044,37 @@ TEST_F(WindowSelectorTest, DISABLED_DragDropInProgress) {
RunAllPendingInMessageLoop();
}
+TEST_F(WindowSelectorTest, HitTestingInOverview) {
+ gfx::Rect window_bounds(20, 10, 200, 300);
+ aura::Window* root_window = Shell::GetPrimaryRootWindow();
+ scoped_ptr<aura::Window> window1(CreateWindow(window_bounds));
+ scoped_ptr<aura::Window> window2(CreateWindow(window_bounds));
+
+ ToggleOverview();
+ gfx::RectF bounds1 = GetTransformedBoundsInRootWindow(window1.get());
+ gfx::RectF bounds2 = GetTransformedBoundsInRootWindow(window2.get());
+ EXPECT_NE(bounds1.ToString(), bounds2.ToString());
+
+ ui::EventTarget* root_target = root_window;
+ ui::EventTargeter* targeter = root_target->GetEventTargeter();
+ aura::Window* windows[] = { window1.get(), window2.get() };
+ for (size_t w = 0; w < arraysize(windows); ++w) {
+ gfx::RectF bounds = GetTransformedBoundsInRootWindow(windows[w]);
+ gfx::Point points[] = {
+ gfx::Point(bounds.x(), bounds.y()),
+ gfx::Point(bounds.right() - 1, bounds.y()),
+ gfx::Point(bounds.x(), bounds.bottom() - 1),
+ gfx::Point(bounds.right() - 1, bounds.bottom() - 1),
+ };
+
+ for (size_t p = 0; p < arraysize(points); ++p) {
+ ui::MouseEvent event(ui::ET_MOUSE_MOVED, points[p], points[p],
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(windows[w],
+ targeter->FindTargetForEvent(root_target, &event));
+ }
+ }
+}
+
} // namespace internal
} // namespace ash
diff --git a/ui/aura/window_targeter.cc b/ui/aura/window_targeter.cc
index 942d8c7..7db90de 100644
--- a/ui/aura/window_targeter.cc
+++ b/ui/aura/window_targeter.cc
@@ -37,10 +37,10 @@ bool WindowTargeter::WindowCanAcceptEvent(aura::Window* window,
bool WindowTargeter::EventLocationInsideBounds(
aura::Window* window, const ui::LocatedEvent& event) const {
- gfx::RectF bounds = window->bounds();
- if (window->layer())
- window->layer()->transform().TransformRect(&bounds);
- return bounds.Contains(event.location());
+ gfx::Point point = event.location();
+ if (window->parent())
+ aura::Window::ConvertPointToTarget(window->parent(), window, &point);
+ return gfx::Rect(window->bounds().size()).Contains(point);
}
ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
diff --git a/ui/aura/window_targeter_unittest.cc b/ui/aura/window_targeter_unittest.cc
index fb84ee4..985426b 100644
--- a/ui/aura/window_targeter_unittest.cc
+++ b/ui/aura/window_targeter_unittest.cc
@@ -40,6 +40,18 @@ class WindowTargeterTest : public test::AuraTestBase {
Window* root_window() { return AuraTestBase::root_window(); }
};
+gfx::RectF GetEffectiveVisibleBoundsInRootWindow(Window* window) {
+ gfx::RectF bounds = gfx::Rect(window->bounds().size());
+ Window* root = window->GetRootWindow();
+ CHECK(window->layer());
+ CHECK(root->layer());
+ gfx::Transform transform;
+ if (!window->layer()->GetTargetTransformRelativeTo(root->layer(), &transform))
+ return gfx::RectF();
+ transform.TransformRect(&bounds);
+ return bounds;
+}
+
TEST_F(WindowTargeterTest, Basic) {
test::TestWindowDelegate delegate;
scoped_ptr<Window> window(CreateNormalWindow(1, root_window(), &delegate));
@@ -106,4 +118,48 @@ TEST_F(WindowTargeterTest, ScopedWindowTargeter) {
}
}
+TEST_F(WindowTargeterTest, TargetTransformedWindow) {
+ root_window()->Show();
+
+ test::TestWindowDelegate delegate;
+ scoped_ptr<Window> window(CreateNormalWindow(2, root_window(), &delegate));
+
+ const gfx::Rect window_bounds(100, 20, 400, 80);
+ window->SetBounds(window_bounds);
+
+ ui::EventTarget* root_target = root_window();
+ ui::EventTargeter* targeter = root_target->GetEventTargeter();
+ gfx::Point event_location(490, 50);
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
+ }
+
+ // Scale |window| by 50%. This should move it away from underneath
+ // |event_location|, so an event in that location will not be targeted to it.
+ gfx::Transform transform;
+ transform.Scale(0.5, 0.5);
+ window->SetTransform(transform);
+ EXPECT_EQ(gfx::RectF(100, 20, 200, 40).ToString(),
+ GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(root_window(), targeter->FindTargetForEvent(root_target, &mouse));
+ }
+
+ transform = gfx::Transform();
+ transform.Translate(200, 10);
+ transform.Scale(0.5, 0.5);
+ window->SetTransform(transform);
+ EXPECT_EQ(gfx::RectF(300, 30, 200, 40).ToString(),
+ GetEffectiveVisibleBoundsInRootWindow(window.get()).ToString());
+ {
+ ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &mouse));
+ }
+}
+
} // namespace aura
diff --git a/ui/wm/core/easy_resize_window_targeter.cc b/ui/wm/core/easy_resize_window_targeter.cc
index 1f0e90a..5b48c81 100644
--- a/ui/wm/core/easy_resize_window_targeter.cc
+++ b/ui/wm/core/easy_resize_window_targeter.cc
@@ -27,18 +27,19 @@ bool EasyResizeWindowTargeter::EventLocationInsideBounds(
aura::Window* window,
const ui::LocatedEvent& event) const {
if (ShouldUseExtendedBounds(window)) {
- gfx::RectF bounds(window->bounds());
- gfx::Transform transform = window->layer()->transform();
- transform.TransformRect(&bounds);
- if (event.IsTouchEvent() || event.IsGestureEvent()) {
+ // Note that |event|'s location is in |window|'s parent's coordinate system,
+ // so convert it to |window|'s coordinate system first.
+ gfx::Point point = event.location();
+ if (window->parent())
+ aura::Window::ConvertPointToTarget(window->parent(), window, &point);
+
+ gfx::Rect bounds(window->bounds().size());
+ if (event.IsTouchEvent() || event.IsGestureEvent())
bounds.Inset(touch_extend_);
- } else {
+ else
bounds.Inset(mouse_extend_);
- }
- // Note that |event|'s location is in the |container_|'s coordinate system,
- // as is |bounds|.
- return bounds.Contains(event.location());
+ return bounds.Contains(point);
}
return WindowTargeter::EventLocationInsideBounds(window, event);
}