[go: nahoru, domu]

Avoid two targeting phases in aura client-lib and EventProcessor.

1. Client-lib now skips the step where it converted the event location from
target window's coordinate system to root window's coordinate system; and
sets the target window received from mus-ws to be the target for that event.

2. Added two virtual functions in EventProcessor responsible for getting the
window with the right targeter (either root window or the farthest ancestor
with a targeter set) and for getting the default targeter (WindowTargeter)
respectively.

3. WindowEventDispatcher now is responsible for finding the right target and
doing the conversion between their coordinate systems.

4. WindowTreeHost only sets a targeter for the root window in non-mus mode
so that we don't end up walking all the way up to the root window just to use
the default event targeter.

This also solves the bug where we were using DIP for conversion in the
client-lib but event location was still in pixels at that time.

BUG=687700
TEST=aura_unittests
     manual (--force-device-scale-factor=2)

Review-Url: https://codereview.chromium.org/2681613002
Cr-Original-Commit-Position: refs/heads/master@{#452393}
Committed: https://chromium.googlesource.com/chromium/src/+/6b3d9805494f966193ad47181d39544d541e79f2
Review-Url: https://codereview.chromium.org/2681613002
Cr-Commit-Position: refs/heads/master@{#454530}
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index dde74bfe..f621e805 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -486,8 +486,9 @@
                             location_in_root, ui::EventTimeForNow(),
                             ui::EF_NONE, ui::EF_NONE);
   ui::EventTarget* event_handler =
-      static_cast<ui::EventTarget*>(root_window)
-          ->GetEventTargeter()
+      root_window->GetHost()
+          ->dispatcher()
+          ->GetDefaultEventTargeter()
           ->FindTargetForEvent(root_window, &test_event);
   return WmWindow::Get(static_cast<aura::Window*>(event_handler));
 }
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc
index 69e4315..2e8941af 100644
--- a/ash/shelf/shelf_widget_unittest.cc
+++ b/ash/shelf/shelf_widget_unittest.cc
@@ -214,8 +214,9 @@
   gfx::Rect widget_bounds = widget->GetWindowBoundsInScreen();
   EXPECT_TRUE(widget_bounds.Intersects(shelf_bounds));
 
-  ui::EventTarget* root = widget->GetNativeWindow()->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = widget->GetNativeWindow()->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
   {
     // Create a mouse-event targeting the top of the shelf widget. The
     // window-targeter should find |widget| as the target (instead of the
@@ -290,8 +291,9 @@
   widget->Init(params);
   widget->Show();
 
-  ui::EventTarget* root = shelf_widget->GetNativeWindow()->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = shelf_widget->GetNativeWindow()->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
   // Touch just over the shelf. Since the shelf is visible, the window-targeter
   // should not find the shelf as the target.
   {
diff --git a/ash/wm/immersive_fullscreen_controller_unittest.cc b/ash/wm/immersive_fullscreen_controller_unittest.cc
index cfb4f1c..45e67ae4 100644
--- a/ash/wm/immersive_fullscreen_controller_unittest.cc
+++ b/ash/wm/immersive_fullscreen_controller_unittest.cc
@@ -770,8 +770,9 @@
 
   ui::TouchEvent touch(ui::ET_TOUCH_MOVED, gfx::Point(10, top), 0,
                        ui::EventTimeForNow());
-  ui::EventTarget* root = window()->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = window()->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
   EXPECT_EQ(window(), targeter->FindTargetForEvent(root, &touch));
 
   SetEnabled(true);
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 70eba6a..ce60320 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -1028,7 +1028,8 @@
                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
 
   ui::EventTarget* root_target = root_window;
-  ui::EventTargeter* targeter = root_target->GetEventTargeter();
+  ui::EventTargeter* targeter =
+      root_window->GetHost()->dispatcher()->GetDefaultEventTargeter();
 
   // The event should target the window because we are still not in overview
   // mode.
diff --git a/ash/wm/panels/panel_layout_manager_unittest.cc b/ash/wm/panels/panel_layout_manager_unittest.cc
index 5c8c445..01f0bbc0 100644
--- a/ash/wm/panels/panel_layout_manager_unittest.cc
+++ b/ash/wm/panels/panel_layout_manager_unittest.cc
@@ -839,8 +839,9 @@
   aura::test::TestWindowDelegate delegate;
   std::unique_ptr<aura::Window> w(
       CreatePanelWindowWithDelegate(&delegate, gfx::Rect(0, 0, 200, 200)));
-  ui::EventTarget* root = w->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = w->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
 
   // Note that the constants used in the touch locations below are
   // arbitrarily-selected small numbers which will ensure the point is
diff --git a/ash/wm/workspace_controller_unittest.cc b/ash/wm/workspace_controller_unittest.cc
index db4d586..e51dedc49 100644
--- a/ash/wm/workspace_controller_unittest.cc
+++ b/ash/wm/workspace_controller_unittest.cc
@@ -1481,8 +1481,9 @@
   ParentWindowInPrimaryRootWindow(second.get());
   second->Show();
 
-  ui::EventTarget* root = first->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = first->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
 
   // The windows overlap, and |second| is on top of |first|. Events targeted
   // slightly outside the edges of the |second| window should still be targeted
@@ -1530,8 +1531,9 @@
   aura::test::TestWindowDelegate delegate;
   std::unique_ptr<Window> window(
       CreateTestPanel(&delegate, gfx::Rect(20, 10, 100, 50)));
-  ui::EventTarget* root = window->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = window->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
   const gfx::Rect bounds = window->bounds();
   const int kNumPoints = 5;
   struct {
@@ -1566,8 +1568,9 @@
   aura::test::TestWindowDelegate delegate;
   std::unique_ptr<Window> window(
       CreateTestPanel(&delegate, gfx::Rect(20, 10, 100, 50)));
-  ui::EventTarget* root = window->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = window->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
   const gfx::Rect bounds = window->bounds();
   const int kNumPoints = 5;
   struct {
@@ -1607,8 +1610,9 @@
       window->GetRootWindow(), kShellWindowId_DockedContainer);
   docked_container->AddChild(window.get());
   window->Show();
-  ui::EventTarget* root = window->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = window->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
   const gfx::Rect bounds = window->bounds();
   const int kNumPoints = 5;
   struct {
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 15e9793..7406176 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -250,6 +250,8 @@
     "test/test_window_delegate.h",
     "test/test_window_parenting_client.cc",
     "test/test_window_parenting_client.h",
+    "test/test_window_targeter.cc",
+    "test/test_window_targeter.h",
     "test/test_windows.cc",
     "test/test_windows.h",
     "test/ui_controls_factory_aura.h",
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 0f7351c..93426157 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -160,6 +160,14 @@
   event->set_root_location(root_location);
 }
 
+// Set the |target| to be the target window of this |event| and send it to
+// the EventProcessor.
+void DispatchEventToTarget(ui::Event* event, WindowMus* target) {
+  ui::Event::DispatcherApi dispatch_helper(event);
+  dispatch_helper.set_target(target->GetWindow());
+  GetWindowTreeHostMus(target)->SendEventToProcessor(event);
+}
+
 }  // namespace
 
 WindowTreeClient::WindowTreeClient(
@@ -1150,34 +1158,22 @@
     return;
   }
 
-  WindowTreeHostMus* host = GetWindowTreeHostMus(window);
-  DCHECK(host);
-
-  // The location of the event is relative to |window|. As the event is handed
-  // to WindowTreeHost we need it to be relative to WindowTreeHost.
-  if (event->IsLocatedEvent()) {
-    gfx::Point host_location = event->AsLocatedEvent()->location();
-    aura::Window::ConvertPointToTarget(window->GetWindow(), host->window(),
-                                       &host_location);
-    event->AsLocatedEvent()->set_location(host_location);
-  }
-
   EventAckHandler ack_handler(CreateEventResultCallback(event_id));
   // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or
   // ui::TouchEvent once we have proper support for pointer events.
   if (event->IsMousePointerEvent()) {
     if (event->type() == ui::ET_POINTER_WHEEL_CHANGED) {
       ui::MouseWheelEvent mapped_event(*event->AsPointerEvent());
-      host->SendEventToProcessor(&mapped_event);
+      DispatchEventToTarget(&mapped_event, window);
     } else {
       ui::MouseEvent mapped_event(*event->AsPointerEvent());
-      host->SendEventToProcessor(&mapped_event);
+      DispatchEventToTarget(&mapped_event, window);
     }
   } else if (event->IsTouchPointerEvent()) {
     ui::TouchEvent mapped_event(*event->AsPointerEvent());
-    host->SendEventToProcessor(&mapped_event);
+    DispatchEventToTarget(&mapped_event, window);
   } else {
-    host->SendEventToProcessor(event.get());
+    DispatchEventToTarget(event.get(), window);
   }
   ack_handler.set_handled(event->handled());
 }
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index 86c9d4c..c15f3b7 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -31,7 +31,9 @@
 #include "ui/aura/test/mus/test_window_tree.h"
 #include "ui/aura/test/mus/window_tree_client_private.h"
 #include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/test/test_window_targeter.h"
 #include "ui/aura/window.h"
+#include "ui/aura/window_targeter.h"
 #include "ui/aura/window_tracker.h"
 #include "ui/aura/window_tree_host_observer.h"
 #include "ui/base/class_property.h"
@@ -499,8 +501,6 @@
 
 class InputEventBasicTestWindowDelegate : public test::TestWindowDelegate {
  public:
-  static uint32_t constexpr kEventId = 1;
-
   explicit InputEventBasicTestWindowDelegate(TestWindowTree* test_window_tree)
       : test_window_tree_(test_window_tree) {}
   ~InputEventBasicTestWindowDelegate() override {}
@@ -508,21 +508,30 @@
   bool got_move() const { return got_move_; }
   bool was_acked() const { return was_acked_; }
   const gfx::Point& last_event_location() const { return last_event_location_; }
+  void set_event_id(uint32_t event_id) { event_id_ = event_id; }
 
   // TestWindowDelegate::
   void OnMouseEvent(ui::MouseEvent* event) override {
-    was_acked_ = test_window_tree_->WasEventAcked(kEventId);
+    was_acked_ = test_window_tree_->WasEventAcked(event_id_);
     if (event->type() == ui::ET_MOUSE_MOVED)
       got_move_ = true;
     last_event_location_ = event->location();
     event->SetHandled();
   }
 
+  void reset() {
+    was_acked_ = false;
+    got_move_ = false;
+    last_event_location_ = gfx::Point();
+    event_id_ = 0;
+  }
+
  private:
   TestWindowTree* test_window_tree_;
   bool was_acked_ = false;
   bool got_move_ = false;
   gfx::Point last_event_location_;
+  uint32_t event_id_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(InputEventBasicTestWindowDelegate);
 };
@@ -547,22 +556,229 @@
   EXPECT_FALSE(window_delegate.got_move());
   EXPECT_FALSE(window_delegate.was_acked());
   const gfx::Point event_location_in_child(2, 3);
+  const uint32_t event_id = 1;
+  window_delegate.set_event_id(event_id);
   std::unique_ptr<ui::Event> ui_event(
       new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location_in_child,
                          gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0));
   window_tree_client()->OnWindowInputEvent(
-      InputEventBasicTestWindowDelegate::kEventId, server_id(&child),
-      window_tree_host.display_id(), ui::Event::Clone(*ui_event.get()), 0);
-  EXPECT_TRUE(window_tree()->WasEventAcked(
-      InputEventBasicTestWindowDelegate::kEventId));
+      event_id, server_id(&child), window_tree_host.display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
   EXPECT_EQ(ui::mojom::EventResult::HANDLED,
-            window_tree()->GetEventResult(
-                InputEventBasicTestWindowDelegate::kEventId));
+            window_tree()->GetEventResult(event_id));
   EXPECT_TRUE(window_delegate.got_move());
   EXPECT_FALSE(window_delegate.was_acked());
   EXPECT_EQ(event_location_in_child, window_delegate.last_event_location());
 }
 
+TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) {
+  WindowTreeHostMus window_tree_host(window_tree_client_impl());
+  Window* top_level = window_tree_host.window();
+  const gfx::Rect bounds(0, 0, 100, 100);
+  window_tree_host.SetBoundsInPixels(bounds);
+  window_tree_host.InitHost();
+  window_tree_host.Show();
+  EXPECT_EQ(bounds, top_level->bounds());
+  EXPECT_EQ(bounds, window_tree_host.GetBoundsInPixels());
+  InputEventBasicTestWindowDelegate window_delegate1(window_tree());
+  Window child1(&window_delegate1);
+  child1.Init(ui::LAYER_NOT_DRAWN);
+  child1.SetEventTargeter(base::MakeUnique<WindowTargeter>());
+  top_level->AddChild(&child1);
+  child1.SetBounds(gfx::Rect(10, 10, 100, 100));
+  child1.Show();
+  InputEventBasicTestWindowDelegate window_delegate2(window_tree());
+  Window child2(&window_delegate2);
+  child2.Init(ui::LAYER_NOT_DRAWN);
+  child1.AddChild(&child2);
+  child2.SetBounds(gfx::Rect(20, 30, 100, 100));
+  child2.Show();
+
+  EXPECT_FALSE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+
+  // child1 has a targeter set and event_location is (50, 60), child2
+  // should get the event even though mus-ws wants to send to child1.
+  const gfx::Point event_location(50, 60);
+  uint32_t event_id = 1;
+  window_delegate1.set_event_id(event_id);
+  window_delegate2.set_event_id(event_id);
+  std::unique_ptr<ui::Event> ui_event(
+      new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, gfx::Point(),
+                         ui::EventTimeForNow(), ui::EF_NONE, 0));
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(&child1), window_tree_host.display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_FALSE(window_delegate1.got_move());
+  EXPECT_TRUE(window_delegate2.got_move());
+  EXPECT_EQ(gfx::Point(30, 30), window_delegate2.last_event_location());
+  window_delegate1.reset();
+  window_delegate2.reset();
+
+  // Remove the targeter for child1 and specify the event to go to child1. This
+  // time child1 should receive the event not child2.
+  child1.SetEventTargeter(nullptr);
+  event_id = 2;
+  window_delegate1.set_event_id(event_id);
+  window_delegate2.set_event_id(event_id);
+  std::unique_ptr<ui::Event> ui_event1(
+      new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, gfx::Point(),
+                         ui::EventTimeForNow(), ui::EF_NONE, 0));
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(&child1), window_tree_host.display_id(),
+      ui::Event::Clone(*ui_event1.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_TRUE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+  EXPECT_EQ(gfx::Point(50, 60), window_delegate1.last_event_location());
+}
+
+TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) {
+  WindowTreeHostMus window_tree_host(window_tree_client_impl());
+  Window* top_level = window_tree_host.window();
+  const gfx::Rect bounds(0, 0, 100, 100);
+  window_tree_host.SetBoundsInPixels(bounds);
+  window_tree_host.InitHost();
+  window_tree_host.Show();
+  EXPECT_EQ(bounds, top_level->bounds());
+  EXPECT_EQ(bounds, window_tree_host.GetBoundsInPixels());
+  InputEventBasicTestWindowDelegate window_delegate1(window_tree());
+  Window child1(&window_delegate1);
+  child1.Init(ui::LAYER_NOT_DRAWN);
+  child1.SetEventTargeter(base::MakeUnique<test::TestWindowTargeter>());
+  top_level->AddChild(&child1);
+  child1.SetBounds(gfx::Rect(10, 10, 100, 100));
+  child1.Show();
+  InputEventBasicTestWindowDelegate window_delegate2(window_tree());
+  Window child2(&window_delegate2);
+  child2.Init(ui::LAYER_NOT_DRAWN);
+  child1.AddChild(&child2);
+  child2.SetBounds(gfx::Rect(20, 30, 100, 100));
+  child2.Show();
+
+  EXPECT_FALSE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+
+  // child1 has a custom targeter set which would always return itself as the
+  // target window therefore event should go to child1 unlike
+  // WindowTreeClientClientTest.InputEventFindTargetAndConversion.
+  const gfx::Point event_location(50, 60);
+  uint32_t event_id = 1;
+  window_delegate1.set_event_id(event_id);
+  window_delegate2.set_event_id(event_id);
+  std::unique_ptr<ui::Event> ui_event(
+      new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, gfx::Point(),
+                         ui::EventTimeForNow(), ui::EF_NONE, 0));
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(&child1), window_tree_host.display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_TRUE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+  EXPECT_EQ(gfx::Point(50, 60), window_delegate1.last_event_location());
+  window_delegate1.reset();
+  window_delegate2.reset();
+
+  // child1 should get the event even though mus-ws specifies child2 and it's
+  // actually in child2's space. Event location will be transformed.
+  event_id = 2;
+  window_delegate1.set_event_id(event_id);
+  window_delegate2.set_event_id(event_id);
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(&child2), window_tree_host.display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_TRUE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+  EXPECT_EQ(gfx::Point(70, 90), window_delegate1.last_event_location());
+}
+
+TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) {
+  std::unique_ptr<WindowTreeHostMus> window_tree_host =
+      base::MakeUnique<WindowTreeHostMus>(window_tree_client_impl());
+  Window* top_level = window_tree_host->window();
+  const gfx::Rect bounds(0, 0, 100, 100);
+  window_tree_host->SetBoundsInPixels(bounds);
+  window_tree_host->InitHost();
+  window_tree_host->Show();
+  EXPECT_EQ(bounds, top_level->bounds());
+  EXPECT_EQ(bounds, window_tree_host->GetBoundsInPixels());
+  std::unique_ptr<InputEventBasicTestWindowDelegate> window_delegate1(
+      base::MakeUnique<InputEventBasicTestWindowDelegate>(window_tree()));
+  std::unique_ptr<Window> child1(
+      base::MakeUnique<Window>(window_delegate1.get()));
+  child1->Init(ui::LAYER_NOT_DRAWN);
+  child1->SetEventTargeter(base::MakeUnique<test::TestWindowTargeter>());
+  top_level->AddChild(child1.get());
+  child1->SetBounds(gfx::Rect(10, 10, 100, 100));
+  child1->Show();
+  std::unique_ptr<InputEventBasicTestWindowDelegate> window_delegate2(
+      base::MakeUnique<InputEventBasicTestWindowDelegate>(window_tree()));
+  std::unique_ptr<Window> child2(
+      base::MakeUnique<Window>(window_delegate2.get()));
+  child2->Init(ui::LAYER_NOT_DRAWN);
+  child1->AddChild(child2.get());
+  child2->SetBounds(gfx::Rect(20, 30, 100, 100));
+  child2->Show();
+
+  EXPECT_FALSE(window_delegate1->got_move());
+  EXPECT_FALSE(window_delegate2->got_move());
+
+  // child1 has a custom targeter set which would always return itself as the
+  // target window therefore event should go to child1.
+  const gfx::Point event_location(50, 60);
+  uint32_t event_id = 1;
+  window_delegate1->set_event_id(event_id);
+  window_delegate2->set_event_id(event_id);
+  std::unique_ptr<ui::Event> ui_event(
+      new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, gfx::Point(),
+                         ui::EventTimeForNow(), ui::EF_NONE, 0));
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(child1.get()), window_tree_host->display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_TRUE(window_delegate1->got_move());
+  EXPECT_FALSE(window_delegate2->got_move());
+  EXPECT_EQ(gfx::Point(50, 60), window_delegate1->last_event_location());
+  window_delegate1->reset();
+  window_delegate2->reset();
+
+  // The same event should go to child2 if child2 is the capture window.
+  std::unique_ptr<client::DefaultCaptureClient> capture_client(
+      base::MakeUnique<client::DefaultCaptureClient>());
+  client::SetCaptureClient(top_level, capture_client.get());
+  child2->SetCapture();
+  EXPECT_EQ(child2.get(), client::GetCaptureWindow(child2->GetRootWindow()));
+  event_id = 2;
+  window_delegate1->set_event_id(event_id);
+  window_delegate2->set_event_id(event_id);
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(child1.get()), window_tree_host->display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_FALSE(window_delegate1->got_move());
+  EXPECT_TRUE(window_delegate2->got_move());
+  EXPECT_EQ(gfx::Point(30, 30), window_delegate2->last_event_location());
+  child2.reset();
+  child1.reset();
+  window_tree_host.reset();
+  capture_client.reset();
+}
+
 class WindowTreeClientPointerObserverTest : public WindowTreeClientClientTest {
  public:
   WindowTreeClientPointerObserverTest() {}
@@ -1594,7 +1810,7 @@
   EXPECT_EQ(gfx::Rect(2, 4, 6, 8), top_level->GetHost()->GetBoundsInPixels());
 }
 
-TEST_F(WindowTreeClientClientTestHighDPI, PointerEventsInDips) {
+TEST_F(WindowTreeClientClientTestHighDPI, PointerEventsInDip) {
   display::Screen* screen = display::Screen::GetScreen();
   const display::Display primary_display = screen->GetPrimaryDisplay();
   ASSERT_EQ(2.0f, primary_display.device_scale_factor());
@@ -1628,4 +1844,77 @@
             last_event->root_location());
 }
 
+TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) {
+  WindowTreeHostMus window_tree_host(window_tree_client_impl());
+  display::Screen* screen = display::Screen::GetScreen();
+  display::Display display;
+  ASSERT_TRUE(
+      screen->GetDisplayWithDisplayId(window_tree_host.display_id(), &display));
+  ASSERT_EQ(2.0f, display.device_scale_factor());
+
+  Window* top_level = window_tree_host.window();
+  const gfx::Rect bounds_in_pixels(0, 0, 100, 100);
+  window_tree_host.SetBoundsInPixels(bounds_in_pixels);
+  window_tree_host.InitHost();
+  window_tree_host.Show();
+  EXPECT_EQ(gfx::ConvertRectToDIP(2.0f, bounds_in_pixels), top_level->bounds());
+  EXPECT_EQ(bounds_in_pixels, window_tree_host.GetBoundsInPixels());
+
+  InputEventBasicTestWindowDelegate window_delegate1(window_tree());
+  Window child1(&window_delegate1);
+  child1.Init(ui::LAYER_NOT_DRAWN);
+  child1.SetEventTargeter(base::MakeUnique<test::TestWindowTargeter>());
+  top_level->AddChild(&child1);
+  child1.SetBounds(gfx::Rect(10, 10, 100, 100));
+  child1.Show();
+  InputEventBasicTestWindowDelegate window_delegate2(window_tree());
+  Window child2(&window_delegate2);
+  child2.Init(ui::LAYER_NOT_DRAWN);
+  child1.AddChild(&child2);
+  child2.SetBounds(gfx::Rect(20, 30, 100, 100));
+  child2.Show();
+
+  EXPECT_FALSE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+
+  // child1 has a custom targeter set which would always return itself as the
+  // target window therefore event should go to child1 and should be in dip.
+  const gfx::Point event_location_in_pixels(50, 60);
+  uint32_t event_id = 1;
+  window_delegate1.set_event_id(event_id);
+  window_delegate2.set_event_id(event_id);
+  std::unique_ptr<ui::Event> ui_event(
+      new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location_in_pixels,
+                         gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0));
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(&child1), window_tree_host.display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_TRUE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+  const gfx::Point event_location_in_dip(25, 30);
+  EXPECT_EQ(event_location_in_dip, window_delegate1.last_event_location());
+  window_delegate1.reset();
+  window_delegate2.reset();
+
+  // Event location will be transformed and should be in dip.
+  event_id = 2;
+  window_delegate1.set_event_id(event_id);
+  window_delegate2.set_event_id(event_id);
+  window_tree_client()->OnWindowInputEvent(
+      event_id, server_id(&child2), window_tree_host.display_id(),
+      ui::Event::Clone(*ui_event.get()), 0);
+  EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
+  EXPECT_EQ(ui::mojom::EventResult::HANDLED,
+            window_tree()->GetEventResult(event_id));
+  EXPECT_TRUE(window_delegate1.got_move());
+  EXPECT_FALSE(window_delegate2.got_move());
+  gfx::Point transformed_event_location_in_dip(event_location_in_dip.x() + 20,
+                                               event_location_in_dip.y() + 30);
+  EXPECT_EQ(transformed_event_location_in_dip,
+            window_delegate1.last_event_location());
+}
+
 }  // namespace aura
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index 9a71aa92..ccbd85342f 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -24,6 +24,7 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_port_local.h"
+#include "ui/aura/window_targeter.h"
 #include "ui/base/ime/input_method_factory.h"
 #include "ui/base/ime/input_method_initializer.h"
 #include "ui/base/platform_window_defaults.h"
@@ -129,6 +130,8 @@
   if (!screen)
     display::Screen::SetScreenInstance(test_screen_.get());
   host_.reset(test_screen_->CreateHostForPrimaryDisplay());
+  host_->window()->SetEventTargeter(
+      std::unique_ptr<ui::EventTargeter>(new WindowTargeter()));
 
   client::SetFocusClient(root_window(), focus_client_.get());
   client::SetCaptureClient(root_window(), capture_client());
diff --git a/ui/aura/test/test_window_targeter.cc b/ui/aura/test/test_window_targeter.cc
new file mode 100644
index 0000000..1eff0b70
--- /dev/null
+++ b/ui/aura/test/test_window_targeter.cc
@@ -0,0 +1,26 @@
+// Copyright 2017 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 "ui/aura/test/test_window_targeter.h"
+
+namespace aura {
+namespace test {
+
+TestWindowTargeter::TestWindowTargeter() {}
+
+TestWindowTargeter::~TestWindowTargeter() {}
+
+ui::EventTarget* TestWindowTargeter::FindTargetForEvent(ui::EventTarget* root,
+                                                        ui::Event* event) {
+  return root;
+}
+
+ui::EventTarget* TestWindowTargeter::FindNextBestTarget(
+    ui::EventTarget* previous_target,
+    ui::Event* event) {
+  return previous_target;
+}
+
+}  // namespace test
+}  // namespace aura
diff --git a/ui/aura/test/test_window_targeter.h b/ui/aura/test/test_window_targeter.h
new file mode 100644
index 0000000..664fd163
--- /dev/null
+++ b/ui/aura/test/test_window_targeter.h
@@ -0,0 +1,37 @@
+// Copyright 2017 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.
+
+#ifndef UI_AURA_TEST_TEST_WINDOW_TARGETER_H_
+#define UI_AURA_TEST_TEST_WINDOW_TARGETER_H_
+
+#include "base/macros.h"
+#include "ui/aura/window_targeter.h"
+#include "ui/events/event_targeter.h"
+
+namespace aura {
+namespace test {
+
+// A test WindowTargeter implementation that would always return the
+// EventTarget it received from FindTargetForEvent or FindNextBestTarget
+// as the EventTarget that should receive the event.
+class TestWindowTargeter : public WindowTargeter {
+ public:
+  TestWindowTargeter();
+  ~TestWindowTargeter() override;
+
+ protected:
+  // WindowTargeter:
+  ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
+                                      ui::Event* event) override;
+  ui::EventTarget* FindNextBestTarget(ui::EventTarget* previous_target,
+                                      ui::Event* event) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestWindowTargeter);
+};
+
+}  // namespace test
+}  // namespace aura
+
+#endif  // UI_AURA_TEST_TEST_WINDOW_TARGETER_H_
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index 6cd3c43e2da..02885e5 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -60,6 +60,22 @@
   return false;
 }
 
+void ConvertEventLocationToTarget(ui::EventTarget* event_target,
+                                  ui::EventTarget* target,
+                                  ui::Event* event) {
+  if (target == event_target || !event->IsLocatedEvent())
+    return;
+
+  gfx::Point location = event->AsLocatedEvent()->location();
+  gfx::Point root_location = event->AsLocatedEvent()->root_location();
+  Window::ConvertPointToTarget(static_cast<Window*>(event_target),
+                               static_cast<Window*>(target), &location);
+  Window::ConvertPointToTarget(static_cast<Window*>(event_target),
+                               static_cast<Window*>(target), &root_location);
+  event->AsLocatedEvent()->set_location(location);
+  event->AsLocatedEvent()->set_root_location(root_location);
+}
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -76,6 +92,7 @@
       dispatching_held_event_(nullptr),
       observer_manager_(this),
       env_controller_(new EnvInputStateController),
+      event_targeter_(new WindowTargeter),
       repost_event_factory_(this),
       held_event_factory_(this) {
   ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
@@ -90,6 +107,10 @@
   ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
 }
 
+ui::EventTargeter* WindowEventDispatcher::GetDefaultEventTargeter() {
+  return event_targeter_.get();
+}
+
 void WindowEventDispatcher::RepostEvent(const ui::LocatedEvent* event) {
   DCHECK(event->type() == ui::ET_MOUSE_PRESSED ||
          event->type() == ui::ET_GESTURE_TAP_DOWN ||
@@ -416,8 +437,33 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // WindowEventDispatcher, ui::EventProcessor implementation:
-ui::EventTarget* WindowEventDispatcher::GetRootTarget() {
-  return window();
+ui::EventTarget* WindowEventDispatcher::GetRootForEvent(ui::Event* event) {
+  if (Env::GetInstance()->mode() == Env::Mode::LOCAL)
+    return window();
+
+  if (!event->target())
+    return window();
+
+  ui::EventTarget* event_target = event->target();
+  if (event->IsLocatedEvent()) {
+    ui::EventTarget* target = event_targeter_->FindTargetInRootWindow(
+        window(), *event->AsLocatedEvent());
+    if (target) {
+      ConvertEventLocationToTarget(event_target, target, event);
+      return target;
+    }
+  }
+
+  ui::EventTarget* ancestor_with_targeter = event_target;
+  for (ui::EventTarget* ancestor = event_target->GetParentTarget(); ancestor;
+       ancestor = ancestor->GetParentTarget()) {
+    if (ancestor->GetEventTargeter())
+      ancestor_with_targeter = ancestor;
+    if (ancestor == window())
+      break;
+  }
+  ConvertEventLocationToTarget(event_target, ancestor_with_targeter, event);
+  return ancestor_with_targeter;
 }
 
 void WindowEventDispatcher::OnEventProcessingStarted(ui::Event* event) {
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h
index 32b2b90..9693f722 100644
--- a/ui/aura/window_event_dispatcher.h
+++ b/ui/aura/window_event_dispatcher.h
@@ -38,6 +38,7 @@
 class MusMouseLocationUpdater;
 class TestScreen;
 class EnvInputStateController;
+class WindowTargeter;
 class WindowTreeHost;
 
 namespace test {
@@ -60,6 +61,9 @@
   Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
   Window* mouse_moved_handler() { return mouse_moved_handler_; }
 
+  // Overridden from ui::EventProcessor:
+  ui::EventTargeter* GetDefaultEventTargeter() override;
+
   // Repost event for re-processing. Used when exiting context menus.
   // We support the ET_MOUSE_PRESSED, ET_TOUCH_PRESSED and ET_GESTURE_TAP_DOWN
   // event types (although the latter is currently a no-op).
@@ -173,7 +177,7 @@
   void ReleaseNativeCapture() override;
 
   // Overridden from ui::EventProcessor:
-  ui::EventTarget* GetRootTarget() override;
+  ui::EventTarget* GetRootForEvent(ui::Event* event) override;
   void OnEventProcessingStarted(ui::Event* event) override;
   void OnEventProcessingFinished(ui::Event* event) override;
 
@@ -262,6 +266,9 @@
 
   std::unique_ptr<MusMouseLocationUpdater> mus_mouse_location_updater_;
 
+  // The default EventTargeter for WindowEventDispatcher generated events.
+  std::unique_ptr<WindowTargeter> event_targeter_;
+
   // Used to schedule reposting an event.
   base::WeakPtrFactory<WindowEventDispatcher> repost_event_factory_;
 
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc
index ca48fb2d..3197a45 100644
--- a/ui/aura/window_event_dispatcher_unittest.cc
+++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -2742,6 +2742,50 @@
   EXPECT_EQ(gfx::Point(0, 0), Env::GetInstance()->last_mouse_location());
 }
 
+TEST_F(WindowEventDispatcherMusTest, UseDefaultTargeterToFindTarget) {
+  LastEventLocationDelegate last_event_location_delegate1;
+  std::unique_ptr<Window> child1(
+      CreateTestWindowWithDelegate(&last_event_location_delegate1, 123,
+                                   gfx::Rect(10, 10, 100, 100), root_window()));
+  LastEventLocationDelegate last_event_location_delegate2;
+  std::unique_ptr<Window> child2(
+      CreateTestWindowWithDelegate(&last_event_location_delegate2, 124,
+                                   gfx::Rect(20, 30, 100, 100), child1.get()));
+
+  const gfx::Point mouse_location(30, 40);
+  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, mouse_location,
+                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+                       ui::EF_LEFT_MOUSE_BUTTON);
+  DispatchEventUsingWindowDispatcher(&mouse);
+  EXPECT_EQ(0, last_event_location_delegate1.mouse_event_count());
+  EXPECT_EQ(1, last_event_location_delegate2.mouse_event_count());
+  EXPECT_EQ(gfx::Point(), last_event_location_delegate1.last_mouse_location());
+  EXPECT_EQ(mouse_location,
+            last_event_location_delegate2.last_mouse_location());
+}
+
+TEST_F(WindowEventDispatcherMusTest, UseDefaultTargeterToFindTarget2) {
+  LastEventLocationDelegate last_event_location_delegate1;
+  std::unique_ptr<Window> child1(
+      CreateTestWindowWithDelegate(&last_event_location_delegate1, 123,
+                                   gfx::Rect(10, 10, 100, 100), root_window()));
+  LastEventLocationDelegate last_event_location_delegate2;
+  std::unique_ptr<Window> child2(
+      CreateTestWindowWithDelegate(&last_event_location_delegate2, 124,
+                                   gfx::Rect(20, 30, 100, 100), child1.get()));
+
+  const gfx::Point mouse_location(15, 25);
+  ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, mouse_location,
+                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+                       ui::EF_LEFT_MOUSE_BUTTON);
+  DispatchEventUsingWindowDispatcher(&mouse);
+  EXPECT_EQ(1, last_event_location_delegate1.mouse_event_count());
+  EXPECT_EQ(0, last_event_location_delegate2.mouse_event_count());
+  EXPECT_EQ(mouse_location,
+            last_event_location_delegate1.last_mouse_location());
+  EXPECT_EQ(gfx::Point(), last_event_location_delegate2.last_mouse_location());
+}
+
 class NestedLocationDelegate : public test::TestWindowDelegate {
  public:
   NestedLocationDelegate() {}
diff --git a/ui/aura/window_targeter.h b/ui/aura/window_targeter.h
index 048d8ad2..bc893d5ae 100644
--- a/ui/aura/window_targeter.h
+++ b/ui/aura/window_targeter.h
@@ -31,6 +31,9 @@
   virtual bool SubtreeShouldBeExploredForEvent(Window* window,
                                                const ui::LocatedEvent& event);
 
+  Window* FindTargetInRootWindow(Window* root_window,
+                                 const ui::LocatedEvent& event);
+
  protected:
   // Same as FindTargetForEvent(), but used for positional events. The location
   // etc. of |event| are in |root|'s coordinate system. When finding the target
@@ -63,8 +66,6 @@
  private:
   Window* FindTargetForKeyEvent(Window* root_window, const ui::KeyEvent& event);
   Window* FindTargetForNonKeyEvent(Window* root_window, ui::Event* event);
-  Window* FindTargetInRootWindow(Window* root_window,
-                                 const ui::LocatedEvent& event);
   Window* FindTargetForLocatedEventRecursively(Window* root_window,
                                                ui::LocatedEvent* event);
 
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index 039ec6d..e624728 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -260,8 +260,6 @@
     window()->Init(ui::LAYER_NOT_DRAWN);
     window()->set_host(this);
     window()->SetName("RootWindow");
-    window()->SetEventTargeter(
-        std::unique_ptr<ui::EventTargeter>(new WindowTargeter()));
     dispatcher_.reset(new WindowEventDispatcher(this));
   }
 }
diff --git a/ui/events/event_processor.cc b/ui/events/event_processor.cc
index 61d2e72..f80cb91 100644
--- a/ui/events/event_processor.cc
+++ b/ui/events/event_processor.cc
@@ -10,14 +10,11 @@
 namespace ui {
 
 EventDispatchDetails EventProcessor::OnEventFromSource(Event* event) {
-  EventTarget* root = GetRootTarget();
-  CHECK(root);
-  EventTargeter* targeter = root->GetEventTargeter();
-  CHECK(targeter);
-
   // If |event| is in the process of being dispatched or has already been
-  // dispatched, then dispatch a copy of the event instead.
+  // dispatched, then dispatch a copy of the event instead. We expect event
+  // target to be already set if event phase is after EP_PREDISPATCH.
   bool dispatch_original_event = event->phase() == EP_PREDISPATCH;
+  DCHECK(dispatch_original_event || event->target());
   Event* event_to_dispatch = event;
   std::unique_ptr<Event> event_copy;
   if (!dispatch_original_event) {
@@ -26,9 +23,23 @@
   }
 
   OnEventProcessingStarted(event_to_dispatch);
-  EventTarget* target = NULL;
-  if (!event_to_dispatch->handled())
-    target = targeter->FindTargetForEvent(root, event_to_dispatch);
+  EventTarget* target = nullptr;
+  EventTargeter* targeter = nullptr;
+  if (!event_to_dispatch->handled()) {
+    EventTarget* root = GetRootForEvent(event_to_dispatch);
+    DCHECK(root);
+    targeter = root->GetEventTargeter();
+    if (targeter) {
+      target = targeter->FindTargetForEvent(root, event_to_dispatch);
+    } else {
+      targeter = GetDefaultEventTargeter();
+      if (event_to_dispatch->target())
+        target = root;
+      else
+        target = targeter->FindTargetForEvent(root, event_to_dispatch);
+    }
+    DCHECK(targeter);
+  }
 
   EventDispatchDetails details;
   while (target) {
diff --git a/ui/events/event_processor.h b/ui/events/event_processor.h
index 8e63051..82d30ce 100644
--- a/ui/events/event_processor.h
+++ b/ui/events/event_processor.h
@@ -10,14 +10,21 @@
 
 namespace ui {
 
+class EventTargeter;
+
 // EventProcessor receives an event from an EventSource and dispatches it to a
 // tree of EventTargets.
 class EVENTS_EXPORT EventProcessor : public EventDispatcherDelegate {
  public:
   ~EventProcessor() override {}
 
-  // Returns the root of the tree this event processor owns.
-  virtual EventTarget* GetRootTarget() = 0;
+  // Returns the EventTarget with the right EventTargeter that we should use for
+  // dispatching this |event|.
+  virtual EventTarget* GetRootForEvent(Event* event) = 0;
+
+  // If the root target returned by GetRootForEvent() does not have a
+  // targeter set, then the default targeter is used to find the target.
+  virtual EventTargeter* GetDefaultEventTargeter() = 0;
 
   // Dispatches an event received from the EventSource to the tree of
   // EventTargets (whose root is returned by GetRootTarget()).  The co-ordinate
diff --git a/ui/events/event_processor_unittest.cc b/ui/events/event_processor_unittest.cc
index 2428a24..f3a617d 100644
--- a/ui/events/event_processor_unittest.cc
+++ b/ui/events/event_processor_unittest.cc
@@ -38,7 +38,7 @@
   }
 
   TestEventTarget* root() {
-    return static_cast<TestEventTarget*>(processor_.GetRootTarget());
+    return static_cast<TestEventTarget*>(processor_.GetRoot());
   }
 
   TestEventProcessor* processor() {
diff --git a/ui/events/test/test_event_processor.cc b/ui/events/test/test_event_processor.cc
index f5fbf89..dd83c4c 100644
--- a/ui/events/test/test_event_processor.cc
+++ b/ui/events/test/test_event_processor.cc
@@ -19,6 +19,10 @@
 
 TestEventProcessor::~TestEventProcessor() {}
 
+EventTarget* TestEventProcessor::GetRoot() {
+  return root_.get();
+}
+
 void TestEventProcessor::SetRoot(std::unique_ptr<EventTarget> root) {
   root_ = std::move(root);
 }
@@ -33,10 +37,14 @@
   return true;
 }
 
-EventTarget* TestEventProcessor::GetRootTarget() {
+EventTarget* TestEventProcessor::GetRootForEvent(Event* event) {
   return root_.get();
 }
 
+EventTargeter* TestEventProcessor::GetDefaultEventTargeter() {
+  return root_->GetEventTargeter();
+}
+
 EventDispatchDetails TestEventProcessor::OnEventFromSource(Event* event) {
   return EventProcessor::OnEventFromSource(event);
 }
diff --git a/ui/events/test/test_event_processor.h b/ui/events/test/test_event_processor.h
index 9b71282..1e484a45 100644
--- a/ui/events/test/test_event_processor.h
+++ b/ui/events/test/test_event_processor.h
@@ -30,12 +30,14 @@
     should_processing_occur_ = occur;
   }
 
+  EventTarget* GetRoot();
   void SetRoot(std::unique_ptr<EventTarget> root);
   void Reset();
 
   // EventProcessor:
   bool CanDispatchToTarget(EventTarget* target) override;
-  EventTarget* GetRootTarget() override;
+  EventTarget* GetRootForEvent(Event* event) override;
+  EventTargeter* GetDefaultEventTargeter() override;
   EventDispatchDetails OnEventFromSource(Event* event) override;
   void OnEventProcessingStarted(Event* event) override;
   void OnEventProcessingFinished(Event* event) override;
diff --git a/ui/views/bubble/bubble_window_targeter_unittest.cc b/ui/views/bubble/bubble_window_targeter_unittest.cc
index 3533ad2..975d68e 100644
--- a/ui/views/bubble/bubble_window_targeter_unittest.cc
+++ b/ui/views/bubble/bubble_window_targeter_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/macros.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/events/event_utils.h"
 #include "ui/views/bubble/bubble_border.h"
 #include "ui/views/bubble/bubble_dialog_delegate.h"
@@ -87,8 +88,9 @@
 };
 
 TEST_F(BubbleWindowTargeterTest, HitTest) {
-  ui::EventTarget* root = bubble_widget()->GetNativeWindow()->GetRootWindow();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = bubble_widget()->GetNativeWindow()->GetRootWindow();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
   aura::Window* bubble_window = bubble_widget()->GetNativeWindow();
   gfx::Rect bubble_bounds = bubble_window->GetBoundsInRootWindow();
 
diff --git a/ui/views/test/event_generator_delegate_mac.mm b/ui/views/test/event_generator_delegate_mac.mm
index 6fe8fb3..925401e 100644
--- a/ui/views/test/event_generator_delegate_mac.mm
+++ b/ui/views/test/event_generator_delegate_mac.mm
@@ -265,7 +265,10 @@
   ui::EventProcessor* GetEventProcessor() override { return this; }
 
   // Overridden from ui::EventProcessor:
-  ui::EventTarget* GetRootTarget() override { return this; }
+  ui::EventTarget* GetRootForEvent(ui::Event* event) override { return this; }
+  ui::EventTargeter* GetDefaultEventTargeter() override {
+    return this->GetEventTargeter();
+  }
 
   // Overridden from ui::EventDispatcherDelegate (via ui::EventProcessor):
   bool CanDispatchToTarget(EventTarget* target) override { return true; }
diff --git a/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
index 83de784..4743062 100644
--- a/ui/views/touchui/touch_selection_controller_impl_unittest.cc
+++ b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -10,6 +10,8 @@
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/test/test_cursor_client.h"
 #include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/touch/touch_editing_controller.h"
 #include "ui/base/ui_base_switches.h"
@@ -794,8 +796,9 @@
   if (IsMus())
     return;
 
-  ui::EventTarget* root = GetContext();
-  ui::EventTargeter* targeter = root->GetEventTargeter();
+  aura::Window* root = GetContext();
+  ui::EventTargeter* targeter =
+      root->GetHost()->dispatcher()->GetDefaultEventTargeter();
 
   // Create the first window containing a Views::Textfield.
   CreateTextfield();
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index cbb47b8..639f239 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -246,10 +246,14 @@
 ////////////////////////////////////////////////////////////////////////////////
 // RootView, ui::EventProcessor overrides:
 
-ui::EventTarget* RootView::GetRootTarget() {
+ui::EventTarget* RootView::GetRootForEvent(ui::Event* event) {
   return this;
 }
 
+ui::EventTargeter* RootView::GetDefaultEventTargeter() {
+  return this->GetEventTargeter();
+}
+
 void RootView::OnEventProcessingStarted(ui::Event* event) {
   if (!event->IsGestureEvent())
     return;
diff --git a/ui/views/widget/root_view.h b/ui/views/widget/root_view.h
index 18b0021b..d8212a24 100644
--- a/ui/views/widget/root_view.h
+++ b/ui/views/widget/root_view.h
@@ -97,7 +97,8 @@
   View* GetFocusTraversableParentView() override;
 
   // Overridden from ui::EventProcessor:
-  ui::EventTarget* GetRootTarget() override;
+  ui::EventTarget* GetRootForEvent(ui::Event* event) override;
+  ui::EventTargeter* GetDefaultEventTargeter() override;
   void OnEventProcessingStarted(ui::Event* event) override;
   void OnEventProcessingFinished(ui::Event* event) override;