Commit cc619c2d authored by Jun Mukai's avatar Jun Mukai Committed by Commit Bot

Mash: make root_location in root window coordinate

It seems that Event's root_location is in display's coordinate
in WindowTreeClient (i.e. browser). This could complicate the
coordinate conversions like aura::ScreenCoordinateClient and
cause problems like crbug.com/876509.

Since root_location is relative to the root window in desktop
aura (like desktop Linux), I believe we want to do so too on
Mash.

This is actually contradicting with crrev.com/583488 but
I believe this is better for us.

Bug: 876509
Test: unit tests pass, manually checked crbug.com/873763 behavior
Change-Id: I51f03772e2872783cf5fb9ce78cdcfe3dd7b0e67
Reviewed-on: https://chromium-review.googlesource.com/1187134
Commit-Queue: Jun Mukai <mukai@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#586067}
parent 8ed19ab9
...@@ -177,9 +177,28 @@ void WindowTree::SendEventToClient(aura::Window* window, const Event& event) { ...@@ -177,9 +177,28 @@ void WindowTree::SendEventToClient(aura::Window* window, const Event& event) {
for (WindowServiceObserver& observer : window_service_->observers()) for (WindowServiceObserver& observer : window_service_->observers())
observer.OnWillSendEventToClient(client_id_, event_id); observer.OnWillSendEventToClient(client_id_, event_id);
// Translate the root location for located events. Event's root location
// should be in the coordinate of the root window, however the root for the
// target window in the client can be different from the one in the server,
// thus the root location needs to be converted from the original coordinate
// to the one used in the client. See also 'WindowTreeTest.EventLocation' test
// case.
std::unique_ptr<ui::Event> event_to_send =
PointerWatcher::CreateEventForClient(event);
if (event.IsLocatedEvent()) {
aura::Window* client_root_window = GetClientRootWindowFor(window);
// The client_root_ may have been removed on shutdown.
if (client_root_window) {
gfx::PointF root_location =
event_to_send->AsLocatedEvent()->root_location_f();
aura::Window::ConvertPointToTarget(window->GetRootWindow(),
client_root_window, &root_location);
event_to_send->AsLocatedEvent()->set_root_location_f(root_location);
}
}
window_tree_client_->OnWindowInputEvent( window_tree_client_->OnWindowInputEvent(
event_id, TransportIdForWindow(window), display_id, event_id, TransportIdForWindow(window), display_id,
PointerWatcher::CreateEventForClient(event), matches_pointer_watcher); std::move(event_to_send), matches_pointer_watcher);
} }
void WindowTree::SendPointerWatcherEventToClient( void WindowTree::SendPointerWatcherEventToClient(
...@@ -382,6 +401,15 @@ bool WindowTree::IsClientRootWindow(aura::Window* window) { ...@@ -382,6 +401,15 @@ bool WindowTree::IsClientRootWindow(aura::Window* window) {
return window && FindClientRootWithRoot(window) != client_roots_.end(); return window && FindClientRootWithRoot(window) != client_roots_.end();
} }
aura::Window* WindowTree::GetClientRootWindowFor(aura::Window* window) {
if (!window)
return nullptr;
auto iter = FindClientRootWithRoot(window);
if (iter != client_roots_.end())
return iter->get()->window();
return GetClientRootWindowFor(window->parent());
}
WindowTree::ClientRoots::iterator WindowTree::FindClientRootWithRoot( WindowTree::ClientRoots::iterator WindowTree::FindClientRootWithRoot(
aura::Window* window) { aura::Window* window) {
if (!window) if (!window)
......
...@@ -176,6 +176,10 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowTree ...@@ -176,6 +176,10 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowTree
bool IsClientCreatedWindow(aura::Window* window); bool IsClientCreatedWindow(aura::Window* window);
bool IsClientRootWindow(aura::Window* window); bool IsClientRootWindow(aura::Window* window);
// Returns the window which is corresponded with the root window for the
// specified |window| in the client.
aura::Window* GetClientRootWindowFor(aura::Window* window);
ClientRoots::iterator FindClientRootWithRoot(aura::Window* window); ClientRoots::iterator FindClientRootWithRoot(aura::Window* window);
// Returns true if |window| has been exposed to this client. A client // Returns true if |window| has been exposed to this client. A client
......
...@@ -356,8 +356,8 @@ TEST(WindowTreeTest, WindowToWindowData) { ...@@ -356,8 +356,8 @@ TEST(WindowTreeTest, WindowToWindowData) {
TEST(WindowTreeTest, EventLocation) { TEST(WindowTreeTest, EventLocation) {
WindowServiceTestSetup setup; WindowServiceTestSetup setup;
TestWindowTreeClient* window_tree_client = setup.window_tree_client(); TestWindowTreeClient* window_tree_client = setup.window_tree_client();
aura::Window* top_level = WindowTreeTestHelper* helper = setup.window_tree_test_helper();
setup.window_tree_test_helper()->NewTopLevelWindow(); aura::Window* top_level = helper->NewTopLevelWindow();
ASSERT_TRUE(top_level); ASSERT_TRUE(top_level);
top_level->Show(); top_level->Show();
...@@ -374,22 +374,70 @@ TEST(WindowTreeTest, EventLocation) { ...@@ -374,22 +374,70 @@ TEST(WindowTreeTest, EventLocation) {
event_generator.MoveMouseTo(33, 44); event_generator.MoveMouseTo(33, 44);
ASSERT_EQ(1u, window_tree_client->input_events().size()); ASSERT_EQ(1u, window_tree_client->input_events().size());
TestWindowTreeClient::InputEvent event1 = window_tree_client->PopInputEvent(); TestWindowTreeClient::InputEvent event1 = window_tree_client->PopInputEvent();
EXPECT_EQ(helper->TransportIdForWindow(top_level), event1.window_id);
ASSERT_TRUE(event1.event->IsLocatedEvent()); ASSERT_TRUE(event1.event->IsLocatedEvent());
ui::LocatedEvent* located_event1 = event1.event->AsLocatedEvent(); ui::LocatedEvent* located_event1 = event1.event->AsLocatedEvent();
// The location is in the top-level's (client-root) coordinate system. // The location is in the target window's coordinate system.
EXPECT_EQ(gfx::Point(23, 24), located_event1->location()); EXPECT_EQ(gfx::Point(23, 24), located_event1->location());
// The root location is in the display's (display-root) coordinate system. // The root location is in the client-root coordinate system.
EXPECT_EQ(gfx::Point(33, 44), located_event1->root_location()); EXPECT_EQ(gfx::Point(23, 24), located_event1->root_location());
event_generator.MoveMouseTo(55, 66); event_generator.MoveMouseTo(55, 86);
ASSERT_EQ(1u, window_tree_client->input_events().size()); // 2 input events should happen -- exit on |top_level| and enter on |window|.
ASSERT_EQ(2u, window_tree_client->input_events().size());
// Check the exit event on |top_level|.
TestWindowTreeClient::InputEvent event2 = window_tree_client->PopInputEvent(); TestWindowTreeClient::InputEvent event2 = window_tree_client->PopInputEvent();
EXPECT_EQ(helper->TransportIdForWindow(top_level), event2.window_id);
ASSERT_TRUE(event2.event->IsLocatedEvent()); ASSERT_TRUE(event2.event->IsLocatedEvent());
ui::LocatedEvent* located_event2 = event2.event->AsLocatedEvent(); ui::LocatedEvent* located_event2 = event2.event->AsLocatedEvent();
// The location is in the top-level's (client-root) coordinate system. // The location is in the target window's coordinate system.
EXPECT_EQ(gfx::Point(45, 46), located_event2->location()); EXPECT_EQ(gfx::Point(45, 66), located_event2->location());
// The root location is in the display's (display-root) coordinate system. // The root location is in the client-root coordinate system.
EXPECT_EQ(gfx::Point(55, 66), located_event2->root_location()); EXPECT_EQ(gfx::Point(45, 66), located_event2->root_location());
// Check the enter event on |window|.
TestWindowTreeClient::InputEvent event3 = window_tree_client->PopInputEvent();
EXPECT_EQ(helper->TransportIdForWindow(window), event3.window_id);
ASSERT_TRUE(event3.event->IsLocatedEvent());
ui::LocatedEvent* located_event3 = event3.event->AsLocatedEvent();
// The location is in the target window's coordinate system.
EXPECT_EQ(gfx::Point(45, 16), located_event3->location());
// The root location is in the client-root coordinate system.
EXPECT_EQ(gfx::Point(45, 66), located_event3->root_location());
}
TEST(WindowTreeTest, EventLocationForTransientChildWindow) {
WindowServiceTestSetup setup;
TestWindowTreeClient* window_tree_client = setup.window_tree_client();
WindowTreeTestHelper* helper = setup.window_tree_test_helper();
aura::Window* top_level = helper->NewTopLevelWindow();
ASSERT_TRUE(top_level);
top_level->Show();
top_level->SetBounds(gfx::Rect(10, 20, 100, 100));
aura::Window* transient = helper->NewTopLevelWindow();
ASSERT_TRUE(transient);
transient->Show();
transient->SetBounds(gfx::Rect(50, 30, 60, 90));
helper->window_tree()->AddTransientWindow(
10, helper->TransportIdForWindow(top_level),
helper->TransportIdForWindow(transient));
test::EventGenerator event_generator(setup.root());
event_generator.MoveMouseTo(61, 44);
ASSERT_EQ(1u, window_tree_client->input_events().size());
TestWindowTreeClient::InputEvent event = window_tree_client->PopInputEvent();
EXPECT_EQ(helper->TransportIdForWindow(transient), event.window_id);
ASSERT_TRUE(event.event->IsLocatedEvent());
ui::LocatedEvent* located_event = event.event->AsLocatedEvent();
// The location is in the target window's coordinate system.
EXPECT_EQ(gfx::Point(11, 14), located_event->location());
// The root location is in the client-root coordinate system. Transient
// parents won't affect the coordinate system.
EXPECT_EQ(gfx::Point(11, 14), located_event->root_location());
} }
TEST(WindowTreeTest, MovePressDragRelease) { TEST(WindowTreeTest, MovePressDragRelease) {
......
...@@ -72,6 +72,10 @@ void EnvInputStateController::SetLastMouseLocation( ...@@ -72,6 +72,10 @@ void EnvInputStateController::SetLastMouseLocation(
const gfx::Point& location_in_root) const { const gfx::Point& location_in_root) const {
// If |root_window| is null, we are only using the event to update event // If |root_window| is null, we are only using the event to update event
// states, so we shouldn't update mouse location. // states, so we shouldn't update mouse location.
// This should be able to be skipped for Mus regardless of |root_window|, the
// last mouse location should be taken care of by MusMouseLocationUpdater. But
// leave this as-is for now since some test functions rely on it.
// TODO(mukai): fix this.
if (!root_window && env_->mode() == aura::Env::Mode::MUS) if (!root_window && env_->mode() == aura::Env::Mode::MUS)
return; return;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "ui/aura/mus/mus_mouse_location_updater.h" #include "ui/aura/mus/mus_mouse_location_updater.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/events/event.h" #include "ui/events/event.h"
...@@ -43,8 +44,20 @@ void MusMouseLocationUpdater::OnEventProcessingStarted(const ui::Event& event) { ...@@ -43,8 +44,20 @@ void MusMouseLocationUpdater::OnEventProcessingStarted(const ui::Event& event) {
} }
is_processing_trigger_event_ = true; is_processing_trigger_event_ = true;
Env::GetInstance()->SetLastMouseLocation( gfx::Point location_in_screen = event.AsMouseEvent()->root_location();
event.AsMouseEvent()->root_location()); // event.target() may not exist in some tests.
if (event.target()) {
aura::Window* root_window =
static_cast<aura::Window*>(event.target())->GetRootWindow();
auto* screen_position_client =
aura::client::GetScreenPositionClient(root_window);
// screen_position_client may not exist in tests.
if (screen_position_client) {
screen_position_client->ConvertPointToScreen(root_window,
&location_in_screen);
}
}
Env::GetInstance()->SetLastMouseLocation(location_in_screen);
Env::GetInstance()->get_last_mouse_location_from_mus_ = false; Env::GetInstance()->get_last_mouse_location_from_mus_ = false;
} }
......
...@@ -129,11 +129,7 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window, ...@@ -129,11 +129,7 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
// This is used for bezel gesture events (eg. swiping in from screen edge). // This is used for bezel gesture events (eg. swiping in from screen edge).
display::Display display = display::Display display =
display::Screen::GetScreen()->GetDisplayNearestWindow(root_window); display::Screen::GetScreen()->GetDisplayNearestWindow(root_window);
// event.location() is in |root_window|'s coordinate system at this point. gfx::Point screen_location = event.root_location();
// Using event.root_location() breaks calculations in mus clients, because
// event.root_location() is in the display-root's coordinate system, but
// |root_window| is actually the top-level window of the mus client.
gfx::Point screen_location = event.location();
if (client::GetScreenPositionClient(root_window)) { if (client::GetScreenPositionClient(root_window)) {
client::GetScreenPositionClient(root_window) client::GetScreenPositionClient(root_window)
->ConvertPointToScreen(root_window, &screen_location); ->ConvertPointToScreen(root_window, &screen_location);
......
...@@ -62,6 +62,8 @@ TEST_P(WindowTargeterTest, Basic) { ...@@ -62,6 +62,8 @@ TEST_P(WindowTargeterTest, Basic) {
one->SetBounds(gfx::Rect(0, 0, 500, 100)); one->SetBounds(gfx::Rect(0, 0, 500, 100));
two->SetBounds(gfx::Rect(501, 0, 500, 1000)); two->SetBounds(gfx::Rect(501, 0, 500, 1000));
root_window()->Show();
ui::test::TestEventHandler handler; ui::test::TestEventHandler handler;
one->AddPreTargetHandler(&handler); one->AddPreTargetHandler(&handler);
...@@ -106,17 +108,6 @@ TEST_P(WindowTargeterTest, FindTargetInRootWindow) { ...@@ -106,17 +108,6 @@ TEST_P(WindowTargeterTest, FindTargetInRootWindow) {
EXPECT_EQ(nullptr, targeter.FindTargetInRootWindow(root_window(), mouse2)); EXPECT_EQ(nullptr, targeter.FindTargetInRootWindow(root_window(), mouse2));
EXPECT_EQ(root_window(), EXPECT_EQ(root_window(),
targeter.FindTargetInRootWindow(root_window(), touch2)); targeter.FindTargetInRootWindow(root_window(), touch2));
// Simulate a mus client root (top level app window) with bottom-right bounds.
// Touches in the root and display should yield null targets crbug.com/873763.
// (mus clients root locations are display coords, not client-root coords)
root_window()->SetBounds(gfx::Rect(600, 500, 200, 100));
gfx::Point root_touch_coords(199, 99);
gfx::Point display_touch_coords(799, 699);
ui::TouchEvent touch3(ui::ET_TOUCH_PRESSED, root_touch_coords,
ui::EventTimeForNow(), ui::PointerDetails());
touch3.set_root_location(display_touch_coords);
EXPECT_EQ(nullptr, targeter.FindTargetInRootWindow(root_window(), touch3));
} }
TEST_P(WindowTargeterTest, ScopedWindowTargeter) { TEST_P(WindowTargeterTest, ScopedWindowTargeter) {
......
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