Commit 2ca7594c authored by sadrul@chromium.org's avatar sadrul@chromium.org

aura: Make sure redirected events have the correct location.

If an event is redirected to a different WindowTreeHost because the target
window belongs to that, then make sure the event is in the WindowTreeHost's
root-window's coordinate space. This is necessary to make sure that the
target (and the pre/post-target handlers) see the event in the correct
location.

BUG=385770
R=sky@chromium.org

Review URL: https://codereview.chromium.org/380343002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282794 0039d316-1c4b-4281-b951-d872f2087c98
parent 1820b9a5
......@@ -117,6 +117,29 @@ class EventLocationRecordingEventHandler : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(EventLocationRecordingEventHandler);
};
class EventLocationHandler : public ui::EventHandler {
public:
EventLocationHandler() {}
virtual ~EventLocationHandler() {}
const gfx::Point& press_location() const { return press_location_; }
const gfx::Point& release_location() const { return release_location_; }
private:
// ui::EventHandler:
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
if (event->type() == ui::ET_MOUSE_PRESSED)
press_location_ = event->location();
else if (event->type() == ui::ET_MOUSE_RELEASED)
release_location_ = event->location();
}
gfx::Point press_location_;
gfx::Point release_location_;
DISALLOW_COPY_AND_ASSIGN(EventLocationHandler);
};
} // namespace
class ExtendedDesktopTest : public test::AshTestBase {
......@@ -415,6 +438,115 @@ TEST_F(ExtendedDesktopTest, Capture) {
EXPECT_EQ("0 0", r1_d2.GetMouseButtonCountsAndReset());
}
TEST_F(ExtendedDesktopTest, CaptureEventLocation) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("1000x600,600x400");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
aura::test::EventCountDelegate r1_d1;
aura::test::EventCountDelegate r1_d2;
aura::test::EventCountDelegate r2_d1;
scoped_ptr<aura::Window> r1_w1(aura::test::CreateTestWindowWithDelegate(
&r1_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[0]));
scoped_ptr<aura::Window> r1_w2(aura::test::CreateTestWindowWithDelegate(
&r1_d2, 0, gfx::Rect(10, 100, 100, 100), root_windows[0]));
scoped_ptr<aura::Window> r2_w1(aura::test::CreateTestWindowWithDelegate(
&r2_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[1]));
r1_w1->SetCapture();
aura::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseToCenterOf(r2_w1.get());
EXPECT_EQ(gfx::Point(1060, 60).ToString(),
generator.current_location().ToString());
EventLocationHandler location_handler;
r1_w1->AddPreTargetHandler(&location_handler);
generator.ClickLeftButton();
r1_w1->RemovePreTargetHandler(&location_handler);
EXPECT_EQ(gfx::Point(1050, 50).ToString(),
location_handler.press_location().ToString());
EXPECT_EQ(gfx::Point(1050, 50).ToString(),
location_handler.release_location().ToString());
}
TEST_F(ExtendedDesktopTest, CaptureEventLocationHighDPI) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("1000x600*2,600x400");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
aura::test::EventCountDelegate r1_d1;
aura::test::EventCountDelegate r1_d2;
aura::test::EventCountDelegate r2_d1;
scoped_ptr<aura::Window> r1_w1(aura::test::CreateTestWindowWithDelegate(
&r1_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[0]));
scoped_ptr<aura::Window> r1_w2(aura::test::CreateTestWindowWithDelegate(
&r1_d2, 0, gfx::Rect(10, 100, 100, 100), root_windows[0]));
scoped_ptr<aura::Window> r2_w1(aura::test::CreateTestWindowWithDelegate(
&r2_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[1]));
r1_w1->SetCapture();
aura::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseToCenterOf(r2_w1.get());
EXPECT_EQ(gfx::Point(560, 60).ToString(),
generator.current_location().ToString());
EventLocationHandler location_handler;
r1_w1->AddPreTargetHandler(&location_handler);
generator.ClickLeftButton();
r1_w1->RemovePreTargetHandler(&location_handler);
EXPECT_EQ(gfx::Point(550, 50).ToString(),
location_handler.press_location().ToString());
EXPECT_EQ(gfx::Point(550, 50).ToString(),
location_handler.release_location().ToString());
}
TEST_F(ExtendedDesktopTest, CaptureEventLocationHighDPI_2) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("1000x600,600x400*2");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
aura::test::EventCountDelegate r1_d1;
aura::test::EventCountDelegate r1_d2;
aura::test::EventCountDelegate r2_d1;
scoped_ptr<aura::Window> r1_w1(aura::test::CreateTestWindowWithDelegate(
&r1_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[0]));
scoped_ptr<aura::Window> r1_w2(aura::test::CreateTestWindowWithDelegate(
&r1_d2, 0, gfx::Rect(10, 100, 100, 100), root_windows[0]));
scoped_ptr<aura::Window> r2_w1(aura::test::CreateTestWindowWithDelegate(
&r2_d1, 0, gfx::Rect(10, 10, 100, 100), root_windows[1]));
r1_w1->SetCapture();
aura::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseToCenterOf(r2_w1.get());
EXPECT_EQ(gfx::Point(1060, 60).ToString(),
generator.current_location().ToString());
EventLocationHandler location_handler;
r1_w1->AddPreTargetHandler(&location_handler);
generator.ClickLeftButton();
r1_w1->RemovePreTargetHandler(&location_handler);
// Event-generator dispatches the event in the primary root-window's coord
// space. Since the location is (1060, 60), it goes to the secondary
// root-window as (30, 30) since the secondary root-window has a device scale
// factor of 2.
EXPECT_EQ(gfx::Point(1020, 20).ToString(),
location_handler.press_location().ToString());
EXPECT_EQ(gfx::Point(1020, 20).ToString(),
location_handler.release_location().ToString());
}
TEST_F(ExtendedDesktopTest, MoveWindow) {
if (!SupportsMultipleDisplays())
return;
......
......@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/event_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/env.h"
......@@ -2203,4 +2204,43 @@ TEST_F(WindowEventDispatcherTest,
EXPECT_EQ("0 0 1", delegate.GetMouseMotionCountsAndReset());
}
TEST_F(WindowEventDispatcherTest,
RedirectedEventToDifferentDispatcherLocation) {
scoped_ptr<WindowTreeHost> second_host(
WindowTreeHost::Create(gfx::Rect(20, 30, 100, 50)));
second_host->InitHost();
client::SetCaptureClient(second_host->window(),
client::GetCaptureClient(root_window()));
test::EventCountDelegate delegate;
scoped_ptr<Window> window_first(CreateTestWindowWithDelegate(&delegate, 123,
gfx::Rect(20, 10, 10, 20), root_window()));
window_first->Show();
scoped_ptr<Window> window_second(CreateTestWindowWithDelegate(&delegate, 12,
gfx::Rect(10, 10, 20, 30), second_host->window()));
window_second->Show();
window_second->SetCapture();
EXPECT_EQ(window_second.get(),
client::GetCaptureWindow(root_window()));
// Send an event to the first host. Make sure it goes to |window_second| in
// |second_host| instead (since it has capture).
EventFilterRecorder recorder_first;
window_first->AddPreTargetHandler(&recorder_first);
EventFilterRecorder recorder_second;
window_second->AddPreTargetHandler(&recorder_second);
const gfx::Point event_location(25, 15);
ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, event_location,
event_location, ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
DispatchEventUsingWindowDispatcher(&mouse);
EXPECT_TRUE(recorder_first.events().empty());
ASSERT_EQ(1u, recorder_second.events().size());
EXPECT_EQ(ui::ET_MOUSE_PRESSED, recorder_second.events()[0]);
EXPECT_EQ(event_location.ToString(),
recorder_second.mouse_locations()[0].ToString());
}
} // namespace aura
......@@ -15,6 +15,15 @@
namespace aura {
namespace {
bool IsLocatedEvent(const ui::Event& event) {
return event.IsMouseEvent() || event.IsTouchEvent() ||
event.IsScrollEvent() || event.IsGestureEvent();
}
} // namespace
WindowTargeter::WindowTargeter() {}
WindowTargeter::~WindowTargeter() {}
......@@ -24,16 +33,25 @@ ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
Window* target = event->IsKeyEvent() ?
FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event)) :
static_cast<Window*>(EventTargeter::FindTargetForEvent(root, event));
if (target && !window->parent()) {
// |window| is the root window.
if (!window->Contains(target)) {
// |target| is not a descendent of |window|. So do not allow dispatching
// from here. Instead, dispatch the event through the
// WindowEventDispatcher that owns |target|.
ui::EventDispatchDetails details ALLOW_UNUSED =
target->GetHost()->event_processor()->OnEventFromSource(event);
target = NULL;
if (target && !window->parent() && !window->Contains(target)) {
// |window| is the root window, but |target| is not a descendent of
// |window|. So do not allow dispatching from here. Instead, dispatch the
// event through the WindowEventDispatcher that owns |target|.
aura::Window* new_root = target->GetRootWindow();
if (IsLocatedEvent(*event)) {
// The event has been transformed to be in |target|'s coordinate system.
// But dispatching the event through the EventProcessor requires the event
// to be in the host's coordinate system. So, convert the event to be in
// the root's coordinate space, and then to the host's coordinate space by
// applying the host's transform.
ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
located_event->ConvertLocationToTarget(target, new_root);
located_event->UpdateForRootTransform(
new_root->GetHost()->GetRootTransform());
}
ui::EventDispatchDetails details ALLOW_UNUSED =
new_root->GetHost()->event_processor()->OnEventFromSource(event);
target = NULL;
}
return target;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment