Invert the ownership relationship between WindowEventDispatcher and WindowTreeHost.

Prior to this change, WindowEventDispatcher owns WindowTreeHost. Code wishing to own an aura::Window hierarchy must create a WindowEventDispatcher, which will either create a default WTH implementation or use the one supplied by the caller.

This relationship made more sense long ago in the days when WED was called RootWindow, and served a purpose broader than just event dispatch bookkeeping. Those days are gone. For code using Aura, it makes more sense for them to create the WTH directly. I predict this may permit some simplification of shutdown code in some situations, since I think it is more intuitive to think of the destruction cascade initiating at the object that most closely binds to the platform accelerated widget. Today, ownership of the window tree sits with WED, which must destroy the window tree and the host.

This CL attempts to make as few changes as possible to invert the ownership. The effect of this is that there is a bunch of code left that probably only needs a WTH but instead has a WED. I will get around to cleaning these up in a future CL.

http://crbug.com/308843
[email protected]

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254071 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ui/aura/bench/bench_main.cc b/ui/aura/bench/bench_main.cc
index 7692633..43092a83 100644
--- a/ui/aura/bench/bench_main.cc
+++ b/ui/aura/bench/bench_main.cc
@@ -19,7 +19,7 @@
 #include "ui/aura/test/test_focus_client.h"
 #include "ui/aura/test/test_screen.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_observer.h"
@@ -300,20 +300,20 @@
   scoped_ptr<aura::TestScreen> test_screen(
       aura::TestScreen::CreateFullscreen());
   gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
-  scoped_ptr<aura::WindowEventDispatcher> dispatcher(
-      test_screen->CreateRootWindowForPrimaryDisplay());
+  scoped_ptr<aura::WindowTreeHost> host(
+      test_screen->CreateHostForPrimaryDisplay());
   aura::client::SetCaptureClient(
-      dispatcher->window(),
-      new aura::client::DefaultCaptureClient(dispatcher->window()));
+      host->window(),
+      new aura::client::DefaultCaptureClient(host->window()));
 
   scoped_ptr<aura::client::FocusClient> focus_client(
       new aura::test::TestFocusClient);
-  aura::client::SetFocusClient(dispatcher->window(), focus_client.get());
+  aura::client::SetFocusClient(host->window(), focus_client.get());
 
   // add layers
   ColoredLayer background(SK_ColorRED);
-  background.SetBounds(dispatcher->window()->bounds());
-  dispatcher->window()->layer()->Add(&background);
+  background.SetBounds(host->window()->bounds());
+  host->window()->layer()->Add(&background);
 
   ColoredLayer window(SK_ColorBLUE);
   window.SetBounds(gfx::Rect(background.bounds().size()));
@@ -338,22 +338,22 @@
 
   if (command_line->HasSwitch("bench-software-scroll")) {
     bench.reset(new SoftwareScrollBench(&page_background,
-                                        dispatcher->host()->compositor(),
+                                        host->compositor(),
                                         frames));
   } else {
     bench.reset(new WebGLBench(&page_background,
-                               dispatcher->host()->compositor(),
+                               host->compositor(),
                                frames));
   }
 
 #ifndef NDEBUG
-  ui::PrintLayerHierarchy(dispatcher->window()->layer(), gfx::Point(100, 100));
+  ui::PrintLayerHierarchy(host->window()->layer(), gfx::Point(100, 100));
 #endif
 
-  dispatcher->host()->Show();
+  host->Show();
   base::MessageLoopForUI::current()->Run();
   focus_client.reset();
-  dispatcher.reset();
+  host.reset();
 
   return 0;
 }
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index b818663a..40de256f 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -15,7 +15,7 @@
 #include "ui/aura/test/test_screen.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
-#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
 #include "ui/compositor/test/context_factories_for_test.h"
 #include "ui/events/event.h"
@@ -118,12 +118,12 @@
   aura::Env::CreateInstance();
   scoped_ptr<aura::TestScreen> test_screen(aura::TestScreen::Create());
   gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
-  scoped_ptr<aura::WindowEventDispatcher> dispatcher(
-      test_screen->CreateRootWindowForPrimaryDisplay());
-  scoped_ptr<DemoWindowTreeClient> window_tree_client(new DemoWindowTreeClient(
-      dispatcher->window()));
+  scoped_ptr<aura::WindowTreeHost> host(
+      test_screen->CreateHostForPrimaryDisplay());
+  scoped_ptr<DemoWindowTreeClient> window_tree_client(
+      new DemoWindowTreeClient(host->window()));
   aura::test::TestFocusClient focus_client;
-  aura::client::SetFocusClient(dispatcher->window(), &focus_client);
+  aura::client::SetFocusClient(host->window(), &focus_client);
 
   // Create a hierarchy of test windows.
   DemoWindowDelegate window_delegate1(SK_ColorBLUE);
@@ -132,8 +132,7 @@
   window1.Init(aura::WINDOW_LAYER_TEXTURED);
   window1.SetBounds(gfx::Rect(100, 100, 400, 400));
   window1.Show();
-  aura::client::ParentWindowWithContext(
-      &window1, dispatcher->window(), gfx::Rect());
+  aura::client::ParentWindowWithContext(&window1, host->window(), gfx::Rect());
 
   DemoWindowDelegate window_delegate2(SK_ColorRED);
   aura::Window window2(&window_delegate2);
@@ -141,8 +140,7 @@
   window2.Init(aura::WINDOW_LAYER_TEXTURED);
   window2.SetBounds(gfx::Rect(200, 200, 350, 350));
   window2.Show();
-  aura::client::ParentWindowWithContext(
-      &window2, dispatcher->window(), gfx::Rect());
+  aura::client::ParentWindowWithContext(&window2, host->window(), gfx::Rect());
 
   DemoWindowDelegate window_delegate3(SK_ColorGREEN);
   aura::Window window3(&window_delegate3);
@@ -152,7 +150,7 @@
   window3.Show();
   window2.AddChild(&window3);
 
-  dispatcher->host()->Show();
+  host->Show();
   base::MessageLoopForUI::current()->Run();
 
   return 0;
diff --git a/ui/aura/remote_window_tree_host_win.cc b/ui/aura/remote_window_tree_host_win.cc
index 1eae586..3fe87b7 100644
--- a/ui/aura/remote_window_tree_host_win.cc
+++ b/ui/aura/remote_window_tree_host_win.cc
@@ -173,6 +173,7 @@
 
 RemoteWindowTreeHostWin::~RemoteWindowTreeHostWin() {
   DestroyCompositor();
+  DestroyDispatcher();
   g_instance = NULL;
 }
 
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index 70f3025c..02d36e44 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -35,7 +35,7 @@
 AuraTestHelper::AuraTestHelper(base::MessageLoopForUI* message_loop)
     : setup_called_(false),
       teardown_called_(false),
-      owns_dispatcher_(false) {
+      owns_host_(false) {
   DCHECK(message_loop);
   message_loop_ = message_loop;
   // Disable animations during tests.
@@ -66,7 +66,7 @@
 
   test_screen_.reset(TestScreen::Create());
   gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
-  dispatcher_.reset(test_screen_->CreateRootWindowForPrimaryDisplay());
+  host_.reset(test_screen_->CreateHostForPrimaryDisplay());
 
   focus_client_.reset(new TestFocusClient);
   client::SetFocusClient(root_window(), focus_client_.get());
@@ -92,7 +92,7 @@
   capture_client_.reset();
   focus_client_.reset();
   client::SetFocusClient(root_window(), NULL);
-  dispatcher_.reset();
+  host_.reset();
   ui::GestureRecognizer::Reset();
   test_screen_.reset();
   gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, NULL);
diff --git a/ui/aura/test/aura_test_helper.h b/ui/aura/test/aura_test_helper.h
index 6c014db..c472db8 100644
--- a/ui/aura/test/aura_test_helper.h
+++ b/ui/aura/test/aura_test_helper.h
@@ -46,8 +46,9 @@
   // Flushes message loop.
   void RunAllPendingInMessageLoop();
 
-  Window* root_window() { return dispatcher_->window(); }
-  WindowEventDispatcher* dispatcher() { return dispatcher_.get(); }
+  Window* root_window() { return host_->window(); }
+  WindowEventDispatcher* dispatcher() { return host_->dispatcher(); }
+  WindowTreeHost* host() { return host_.get(); }
 
   TestScreen* test_screen() { return test_screen_.get(); }
 
@@ -55,8 +56,8 @@
   base::MessageLoopForUI* message_loop_;
   bool setup_called_;
   bool teardown_called_;
-  bool owns_dispatcher_;
-  scoped_ptr<WindowEventDispatcher> dispatcher_;
+  bool owns_host_;
+  scoped_ptr<WindowTreeHost> host_;
   scoped_ptr<TestWindowTreeClient> stacking_client_;
   scoped_ptr<client::DefaultActivationClient> activation_client_;
   scoped_ptr<client::DefaultCaptureClient> capture_client_;
diff --git a/ui/aura/test/test_screen.cc b/ui/aura/test/test_screen.cc
index 26a2eeb..2fced68 100644
--- a/ui/aura/test/test_screen.cc
+++ b/ui/aura/test/test_screen.cc
@@ -31,27 +31,24 @@
 TestScreen::~TestScreen() {
 }
 
-WindowEventDispatcher* TestScreen::CreateRootWindowForPrimaryDisplay() {
-  DCHECK(!dispatcher_);
-  dispatcher_ = new WindowEventDispatcher(
-      WindowEventDispatcher::CreateParams(
-          gfx::Rect(display_.GetSizeInPixel())));
-  dispatcher_->window()->AddObserver(this);
-  dispatcher_->host()->InitHost();
-  return dispatcher_;
+WindowTreeHost* TestScreen::CreateHostForPrimaryDisplay() {
+  DCHECK(!host_);
+  host_ = WindowTreeHost::Create(gfx::Rect(display_.GetSizeInPixel()));
+  host_->window()->AddObserver(this);
+  host_->InitHost();
+  return host_;
 }
 
 void TestScreen::SetDeviceScaleFactor(float device_scale_factor) {
   gfx::Rect bounds_in_pixel(display_.GetSizeInPixel());
   display_.SetScaleAndBounds(device_scale_factor, bounds_in_pixel);
-  dispatcher_->host()->NotifyHostResized(bounds_in_pixel.size());
+  host_->NotifyHostResized(bounds_in_pixel.size());
 }
 
 void TestScreen::SetDisplayRotation(gfx::Display::Rotation rotation) {
   display_.set_rotation(rotation);
   // TODO(oshima|mukai): Update the display_ as well.
-  dispatcher_->host()->SetTransform(
-      GetRotationTransform() * GetUIScaleTransform());
+  host_->SetTransform(GetRotationTransform() * GetUIScaleTransform());
 }
 
 void TestScreen::SetUIScale(float ui_scale) {
@@ -60,8 +57,7 @@
   gfx::Rect new_bounds = gfx::ToNearestRect(
       gfx::ScaleRect(bounds_in_pixel, 1.0f / ui_scale));
   display_.SetScaleAndBounds(display_.device_scale_factor(), new_bounds);
-  dispatcher_->host()->SetTransform(
-      GetRotationTransform() * GetUIScaleTransform());
+  host_->SetTransform(GetRotationTransform() * GetUIScaleTransform());
 }
 
 gfx::Transform TestScreen::GetRotationTransform() const {
@@ -100,14 +96,14 @@
 
 void TestScreen::OnWindowBoundsChanged(
     Window* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) {
-  DCHECK_EQ(dispatcher_->window(), window);
+  DCHECK_EQ(host_->window(), window);
   display_.SetSize(gfx::ToFlooredSize(
       gfx::ScaleSize(new_bounds.size(), display_.device_scale_factor())));
 }
 
 void TestScreen::OnWindowDestroying(Window* window) {
-  if (dispatcher_->window() == window)
-    dispatcher_ = NULL;
+  if (host_->window() == window)
+    host_ = NULL;
 }
 
 gfx::Point TestScreen::GetCursorScreenPoint() {
@@ -119,7 +115,7 @@
 }
 
 gfx::NativeWindow TestScreen::GetWindowAtScreenPoint(const gfx::Point& point) {
-  return dispatcher_->window()->GetTopWindowContainingPoint(point);
+  return host_->window()->GetTopWindowContainingPoint(point);
 }
 
 int TestScreen::GetNumDisplays() const {
@@ -154,7 +150,7 @@
 }
 
 TestScreen::TestScreen(const gfx::Rect& screen_bounds)
-    : dispatcher_(NULL),
+    : host_(NULL),
       ui_scale_(1.0f) {
   static int64 synthesized_display_id = 2000;
   display_.set_id(synthesized_display_id++);
diff --git a/ui/aura/test/test_screen.h b/ui/aura/test/test_screen.h
index c344d3c..28351d20d 100644
--- a/ui/aura/test/test_screen.h
+++ b/ui/aura/test/test_screen.h
@@ -17,7 +17,7 @@
 
 namespace aura {
 class Window;
-class WindowEventDispatcher;
+class WindowTreeHost;
 
 // A minimal, testing Aura implementation of gfx::Screen.
 class TestScreen : public gfx::Screen,
@@ -28,9 +28,7 @@
   static TestScreen* CreateFullscreen();
   virtual ~TestScreen();
 
-  // TODO(beng): Rename to CreateHostForPrimaryDisplay() and make it return
-  //             a WTH.
-  WindowEventDispatcher* CreateRootWindowForPrimaryDisplay();
+  WindowTreeHost* CreateHostForPrimaryDisplay();
 
   void SetDeviceScaleFactor(float device_scale_fator);
   void SetDisplayRotation(gfx::Display::Rotation rotation);
@@ -67,7 +65,7 @@
  private:
   explicit TestScreen(const gfx::Rect& screen_bounds);
 
-  aura::WindowEventDispatcher* dispatcher_;
+  aura::WindowTreeHost* host_;
 
   gfx::Display display_;
 
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index 364ba2f..729def8b 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -70,14 +70,6 @@
   }
 }
 
-WindowTreeHost* CreateHost(WindowEventDispatcher* dispatcher,
-                           const WindowEventDispatcher::CreateParams& params) {
-  WindowTreeHost* host = params.host ?
-      params.host : WindowTreeHost::Create(params.initial_bounds);
-  host->set_delegate(dispatcher);
-  return host;
-}
-
 bool IsEventCandidateForHold(const ui::Event& event) {
   if (event.type() == ui::ET_TOUCH_MOVED)
     return true;
@@ -90,18 +82,12 @@
 
 }  // namespace
 
-WindowEventDispatcher::CreateParams::CreateParams(
-    const gfx::Rect& a_initial_bounds)
-    : initial_bounds(a_initial_bounds),
-      host(NULL) {
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // WindowEventDispatcher, public:
 
-WindowEventDispatcher::WindowEventDispatcher(const CreateParams& params)
+WindowEventDispatcher::WindowEventDispatcher(WindowTreeHost* host)
     : window_(new Window(NULL)),
-      host_(CreateHost(this, params)),
+      host_(host),
       touch_ids_down_(0),
       mouse_pressed_handler_(NULL),
       mouse_moved_handler_(NULL),
@@ -112,6 +98,7 @@
       dispatching_held_event_(false),
       repost_event_factory_(this),
       held_event_factory_(this) {
+  window()->Init(WINDOW_LAYER_NOT_DRAWN);
   window()->set_dispatcher(this);
   window()->SetName("RootWindow");
   window()->SetEventTargeter(
@@ -137,11 +124,6 @@
   // as GetRootWindow()) result in Window's implementation. By destroying here
   // we ensure GetRootWindow() still returns this.
   window()->RemoveOrDestroyChildren();
-
-  // Destroying/removing child windows may try to access |host_| (eg.
-  // GetAcceleratedWidget())
-  host_.reset(NULL);
-
   window()->set_dispatcher(NULL);
 }
 
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h
index 9b46581d..94ecd77 100644
--- a/ui/aura/window_event_dispatcher.h
+++ b/ui/aura/window_event_dispatcher.h
@@ -45,7 +45,6 @@
 }
 
 namespace aura {
-class WindowTreeHost;
 class RootWindowObserver;
 class TestScreen;
 class WindowTargeter;
@@ -57,19 +56,7 @@
                                           public client::CaptureDelegate,
                                           public WindowTreeHostDelegate {
  public:
-  struct AURA_EXPORT CreateParams {
-    // CreateParams with initial_bounds and default host in pixel.
-    explicit CreateParams(const gfx::Rect& initial_bounds);
-    ~CreateParams() {}
-
-    gfx::Rect initial_bounds;
-
-    // A host to use in place of the default one that RootWindow will create.
-    // NULL by default.
-    WindowTreeHost* host;
-  };
-
-  explicit WindowEventDispatcher(const CreateParams& params);
+  explicit WindowEventDispatcher(WindowTreeHost* host);
   virtual ~WindowEventDispatcher();
 
   // Returns the WindowTreeHost for the specified accelerated widget, or NULL
@@ -86,7 +73,7 @@
     return const_cast<WindowTreeHost*>(
         const_cast<const WindowEventDispatcher*>(this)->host());
   }
-  const WindowTreeHost* host() const { return host_.get(); }
+  const WindowTreeHost* host() const { return host_; }
   Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
   Window* mouse_moved_handler() { return mouse_moved_handler_; }
 
@@ -284,10 +271,10 @@
   void PreDispatchMouseEvent(Window* target, ui::MouseEvent* event);
   void PreDispatchTouchEvent(Window* target, ui::TouchEvent* event);
 
-  // TODO(beng): evaluate the ideal ownership model.
+  // TODO(beng): should be owned by WindowTreeHost.
   scoped_ptr<Window> window_;
 
-  scoped_ptr<WindowTreeHost> host_;
+  WindowTreeHost* host_;
 
   // Touch ids that are currently down.
   uint32 touch_ids_down_;
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc
index c658d4c7..87e6193 100644
--- a/ui/aura/window_event_dispatcher_unittest.cc
+++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -1321,12 +1321,11 @@
   ValidRootDuringDestructionWindowObserver observer(&got_destroying,
                                                     &has_valid_root);
   {
-    scoped_ptr<WindowEventDispatcher> dispatcher(
-        new WindowEventDispatcher(
-            WindowEventDispatcher::CreateParams(gfx::Rect(0, 0, 100, 100))));
-    dispatcher->host()->InitHost();
+    scoped_ptr<WindowTreeHost> host(
+        WindowTreeHost::Create(gfx::Rect(0, 0, 100, 100)));
+    host->InitHost();
     // Owned by WindowEventDispatcher.
-    Window* w1 = CreateNormalWindow(1, dispatcher->window(), NULL);
+    Window* w1 = CreateNormalWindow(1, host->window(), NULL);
     w1->AddObserver(&observer);
   }
   EXPECT_TRUE(got_destroying);
@@ -1392,17 +1391,16 @@
 
 namespace {
 
-// See description above DeleteDispatcherFromHeldMouseEvent for details.
-class DeleteDispatcherFromHeldMouseEventDelegate
+// See description above DeleteHostFromHeldMouseEvent for details.
+class DeleteHostFromHeldMouseEventDelegate
     : public test::TestWindowDelegate {
  public:
-  explicit DeleteDispatcherFromHeldMouseEventDelegate(
-      WindowEventDispatcher* dispatcher)
-      : dispatcher_(dispatcher),
+  explicit DeleteHostFromHeldMouseEventDelegate(WindowTreeHost* host)
+      : host_(host),
         got_mouse_event_(false),
         got_destroy_(false) {
   }
-  virtual ~DeleteDispatcherFromHeldMouseEventDelegate() {}
+  virtual ~DeleteHostFromHeldMouseEventDelegate() {}
 
   bool got_mouse_event() const { return got_mouse_event_; }
   bool got_destroy() const { return got_destroy_; }
@@ -1411,7 +1409,7 @@
   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
     if ((event->flags() & ui::EF_SHIFT_DOWN) != 0) {
       got_mouse_event_ = true;
-      delete dispatcher_;
+      delete host_;
     }
   }
   virtual void OnWindowDestroyed(Window* window) OVERRIDE {
@@ -1419,37 +1417,36 @@
   }
 
  private:
-  WindowEventDispatcher* dispatcher_;
+  WindowTreeHost* host_;
   bool got_mouse_event_;
   bool got_destroy_;
 
-  DISALLOW_COPY_AND_ASSIGN(DeleteDispatcherFromHeldMouseEventDelegate);
+  DISALLOW_COPY_AND_ASSIGN(DeleteHostFromHeldMouseEventDelegate);
 };
 
 }  // namespace
 
 #if defined(USE_OZONE)
 // Creating multiple WindowTreeHostOzone instances is broken.
-#define MAYBE_DeleteDispatcherFromHeldMouseEvent DISABLED_DeleteDispatcherFromHeldMouseEvent
+#define MAYBE_DeleteHostFromHeldMouseEvent DISABLED_DeleteHostFromHeldMouseEvent
 #else
-#define MAYBE_DeleteDispatcherFromHeldMouseEvent DeleteDispatcherFromHeldMouseEvent
+#define MAYBE_DeleteHostFromHeldMouseEvent DeleteHostFromHeldMouseEvent
 #endif
 
-// Verifies if a RootWindow is deleted from dispatching a held mouse event we
-// don't crash.
-TEST_F(WindowEventDispatcherTest, MAYBE_DeleteDispatcherFromHeldMouseEvent) {
+// Verifies if a WindowTreeHost is deleted from dispatching a held mouse event
+// we don't crash.
+TEST_F(WindowEventDispatcherTest, MAYBE_DeleteHostFromHeldMouseEvent) {
   // Should be deleted by |delegate|.
-  WindowEventDispatcher* d2 = new WindowEventDispatcher(
-      WindowEventDispatcher::CreateParams(gfx::Rect(0, 0, 100, 100)));
-  d2->host()->InitHost();
-  DeleteDispatcherFromHeldMouseEventDelegate delegate(d2);
-  // Owned by |d2|.
-  Window* w1 = CreateNormalWindow(1, d2->window(), &delegate);
+  WindowTreeHost* h2 = WindowTreeHost::Create(gfx::Rect(0, 0, 100, 100));
+  h2->InitHost();
+  DeleteHostFromHeldMouseEventDelegate delegate(h2);
+  // Owned by |h2|.
+  Window* w1 = CreateNormalWindow(1, h2->window(), &delegate);
   w1->SetBounds(gfx::Rect(0, 0, 40, 40));
   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED,
                          gfx::Point(10, 10), gfx::Point(10, 10),
                          ui::EF_SHIFT_DOWN, 0);
-  d2->RepostEvent(pressed);
+  h2->dispatcher()->RepostEvent(pressed);
   // RunAllPendingInMessageLoop() to make sure the |pressed| is run.
   RunAllPendingInMessageLoop();
   EXPECT_TRUE(delegate.got_mouse_event());
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index 4b8b69c..fd3d217 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -78,7 +78,6 @@
 }
 
 void WindowTreeHost::InitHost() {
-  window()->Init(aura::WINDOW_LAYER_NOT_DRAWN);
   InitCompositor();
   UpdateRootWindowSize(GetBounds().size());
   Env::GetInstance()->NotifyRootWindowInitialized(delegate_->AsDispatcher());
@@ -210,10 +209,19 @@
   compositor_.reset();
 }
 
+void WindowTreeHost::DestroyDispatcher() {
+  dispatcher_.reset();
+}
+
 void WindowTreeHost::CreateCompositor(
     gfx::AcceleratedWidget accelerated_widget) {
   compositor_.reset(new ui::Compositor(GetAcceleratedWidget()));
   DCHECK(compositor_.get());
+  // TODO(beng): I think this setup should probably all move to a "accelerated
+  // widget available" function.
+  if (!dispatcher())
+    dispatcher_.reset(new WindowEventDispatcher(this));
+  delegate_ = dispatcher();
 }
 
 void WindowTreeHost::NotifyHostResized(const gfx::Size& new_size) {
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h
index 6567672f..6418791 100644
--- a/ui/aura/window_tree_host.h
+++ b/ui/aura/window_tree_host.h
@@ -45,8 +45,14 @@
   void InitCompositor();
 
   // TODO(beng): these will become trivial accessors in a future CL.
-  aura::Window* window();
-  const aura::Window* window() const;
+  Window* window();
+  const Window* window() const;
+
+  WindowEventDispatcher* dispatcher() {
+    return const_cast<WindowEventDispatcher*>(
+        const_cast<const WindowTreeHost*>(this)->dispatcher());
+  }
+  const WindowEventDispatcher* dispatcher() const { return dispatcher_.get(); }
 
   ui::Compositor* compositor() { return compositor_.get(); }
 
@@ -161,6 +167,7 @@
 
   WindowTreeHost();
   void DestroyCompositor();
+  void DestroyDispatcher();
 
   void CreateCompositor(gfx::AcceleratedWidget accelerated_widget);
 
@@ -186,6 +193,8 @@
   void MoveCursorToInternal(const gfx::Point& root_location,
                             const gfx::Point& host_location);
 
+  scoped_ptr<WindowEventDispatcher> dispatcher_;
+
   scoped_ptr<ui::Compositor> compositor_;
 
   scoped_ptr<RootWindowTransformer> transformer_;
diff --git a/ui/aura/window_tree_host_mac.mm b/ui/aura/window_tree_host_mac.mm
index 82ea978..b814f038 100644
--- a/ui/aura/window_tree_host_mac.mm
+++ b/ui/aura/window_tree_host_mac.mm
@@ -21,6 +21,7 @@
 }
 
 WindowTreeHostMac::~WindowTreeHostMac() {
+  DestroyDispatcher();
 }
 
 gfx::AcceleratedWidget WindowTreeHostMac::GetAcceleratedWidget() {
diff --git a/ui/aura/window_tree_host_ozone.cc b/ui/aura/window_tree_host_ozone.cc
index 6e9c831..a2c6f3b 100644
--- a/ui/aura/window_tree_host_ozone.cc
+++ b/ui/aura/window_tree_host_ozone.cc
@@ -34,6 +34,7 @@
 WindowTreeHostOzone::~WindowTreeHostOzone() {
   base::MessagePumpOzone::Current()->RemoveDispatcherForRootWindow(0);
   DestroyCompositor();
+  DestroyDispatcher();
 }
 
 uint32_t WindowTreeHostOzone::Dispatch(const base::NativeEvent& ne) {
diff --git a/ui/aura/window_tree_host_win.cc b/ui/aura/window_tree_host_win.cc
index 9187e04..2d592e5 100644
--- a/ui/aura/window_tree_host_win.cc
+++ b/ui/aura/window_tree_host_win.cc
@@ -53,6 +53,7 @@
 
 WindowTreeHostWin::~WindowTreeHostWin() {
   DestroyCompositor();
+  DestroyDispatcher();
   DestroyWindow(hwnd());
 }
 
diff --git a/ui/aura/window_tree_host_x11.cc b/ui/aura/window_tree_host_x11.cc
index 1421542..5f0c6ac 100644
--- a/ui/aura/window_tree_host_x11.cc
+++ b/ui/aura/window_tree_host_x11.cc
@@ -348,6 +348,7 @@
   UnConfineCursor();
 
   DestroyCompositor();
+  DestroyDispatcher();
   XDestroyWindow(xdisplay_, xwindow_);
 }