[go: nahoru, domu]

Reland "X11 and Ozone: Make DWTHX11 subclass DWTHPlatform and use PWD."

This is a reland of a1b5aec5523fc23c24c8b9a9547304043f15ccd0

Fix: initialize state_ in X11Window and fix component build by adding
//ui/platform_window into deps in chrome/browser/ui/BUILD.gn

Original change's description:
> X11 and Ozone: Make DWTHX11 subclass DWTHPlatform and use PWD.
>
> This CL makes the DWTHX11 subclass the DWTHPlatform and use
> the X11Window, which subclasses the XWindow. Also, DWTHX11
> uses PlatformWindowDelegate instead of ui::XWindow::Delegate now.
>
> That is, to migrate X11 to Ozone, we need to make sure DWTHPlatform
> is mature enough. To avoid code duplicate, it was decided to
> make DWTHX11 subclass DWTHPlatform and move its code to DWTHPlatform
> step by step ensuring nothing is broken.
>
> However, it was not enough to just make DWTHX11 a subclass of DWTHPlatform.
> The way how we communicate with XWindow has had to be changed as well.
>
> The plan is to move all the code to DWTHPlatform and make the
> WTHPlatform create the X11Window. However, there are many intermediate
> steps to be done before doing it. As described before, first, DWTHX11
> subclasses the DWTHPlatform and starts to receive messages and
> events from the XWindow through the PlatformWindowDelegate.
>
> It was ensured that the DWTHX11 intercepts all the calls to DWTH,
> WTH and PWD and does everything as it was doing previously. In the
> follow up CLs, I will start to move the code slowly to DWTHPlatform
> and WTHPlatform so that DWTHX11 no longer implements PDW and DWTH
> methods and the DWTHPlatform manages everything on its own
> for both Ozone and non-Ozone builds.
>
> Bug: 990756
> Change-Id: If45b05d09609cf8aa826cc4894ec559f210dc0b7
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1771397
> Reviewed-by: Scott Violet <sky@chromium.org>
> Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
> Commit-Queue: Maksim Sisov <msisov@igalia.com>
> Cr-Commit-Position: refs/heads/master@{#691944}

TBR=sky@chromium.org

Bug: 990756
Change-Id: I6d029491d0ba7408dd1613edc6a547e2d070715c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1774637
Commit-Queue: Maksim Sisov <msisov@igalia.com>
Auto-Submit: Maksim Sisov <msisov@igalia.com>
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#692626}
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index c483dc6..07101cd 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -2300,6 +2300,7 @@
     "//base:i18n",
     "//base/test:test_support",
     "//cc:test_support",
+    "//ui/platform_window/common",
 
     # TODO(https://crbug.com/644336): Make CrasAudioHandler Chrome or Ash only.
     "//chromeos/audio",
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 8cf21e6..435183f 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -55,7 +55,6 @@
 #include "ui/aura/window.h"
 #include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/material_design/material_design_controller.h"
-#include "ui/base/platform_window_defaults.h"
 #include "ui/base/ui_base_switches_util.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/compositor/test/test_context_factories.h"
@@ -64,6 +63,7 @@
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 #include "ui/display/test/display_manager_test_api.h"
+#include "ui/platform_window/common/platform_window_defaults.h"
 #include "ui/wm/core/capture_controller.h"
 #include "ui/wm/core/cursor_manager.h"
 #include "ui/wm/core/wm_state.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a72290f9..7c43cf0 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2479,6 +2479,7 @@
         "views/frame/browser_desktop_window_tree_host_platform.h",
         "views/frame/native_browser_frame_factory_ozone.cc",
       ]
+      deps += [ "//ui/platform_window" ]
     }
     if (use_gtk) {
       # This is the only component that can interact with gtk.
diff --git a/components/viz/demo/demo_main.cc b/components/viz/demo/demo_main.cc
index c12b97b..f5785dc 100644
--- a/components/viz/demo/demo_main.cc
+++ b/components/viz/demo/demo_main.cc
@@ -31,7 +31,7 @@
 #endif
 
 #if defined(USE_X11)
-#include "ui/platform_window/x11/x11_window.h"
+#include "ui/platform_window/x11/x11_window.h"  // nogncheck
 #endif
 
 namespace {
@@ -119,7 +119,9 @@
 #elif defined(OS_WIN)
     return std::make_unique<ui::WinWindow>(this, props.bounds);
 #elif defined(USE_X11)
-    return std::make_unique<ui::X11Window>(this, props.bounds);
+    auto x11_window = std::make_unique<ui::X11Window>(this, nullptr);
+    x11_window->Initialize(std::move(props));
+    return x11_window;
 #else
     NOTIMPLEMENTED();
     return nullptr;
diff --git a/content/public/test/DEPS b/content/public/test/DEPS
index 75250ec5..ad1434c 100644
--- a/content/public/test/DEPS
+++ b/content/public/test/DEPS
@@ -16,6 +16,7 @@
   "+ui/ozone/public",
   "+ui/views/test",
   "+v8/include/v8.h",
+  "+ui/platform_window/common/platform_window_defaults.h",
 ]
 
 # Ensure we don't leak internal content headers through public headers.
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index ba65b011..3546123 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -64,12 +64,15 @@
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/tracing/public/cpp/trace_startup.h"
-#include "ui/base/platform_window_defaults.h"
 #include "ui/compositor/compositor_switches.h"
 #include "ui/display/display_switches.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_switches.h"
 
+#if defined(OS_LINUX)
+#include "ui/platform_window/common/platform_window_defaults.h"  // nogncheck
+#endif
+
 #if defined(OS_ANDROID)
 #include "base/android/task_scheduler/post_task_android.h"
 #include "components/discardable_memory/service/discardable_shared_memory_manager.h"  // nogncheck
@@ -173,7 +176,9 @@
       enable_pixel_output_(false),
       use_software_compositing_(false),
       set_up_called_(false) {
+#if defined(OS_LINUX)
   ui::test::EnableTestConfigForPlatformWindows();
+#endif
 
 #if defined(OS_POSIX)
   handle_sigterm_ = true;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index fb449d8..2b8672f6 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -583,6 +583,10 @@
       "//ui/accelerated_widget_mac",
     ]
   }
+
+  if (is_linux) {
+    deps += [ "//ui/platform_window/common" ]
+  }
 }
 
 # browsertest_support can be used by targets that run content_shell based
diff --git a/gpu/vulkan/demo/vulkan_demo.cc b/gpu/vulkan/demo/vulkan_demo.cc
index 12bd91e..2e2bc6b 100644
--- a/gpu/vulkan/demo/vulkan_demo.cc
+++ b/gpu/vulkan/demo/vulkan_demo.cc
@@ -19,6 +19,7 @@
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "ui/events/platform/platform_event_source.h"
+#include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/platform_window/x11/x11_window.h"
 
 namespace gpu {
@@ -41,13 +42,17 @@
 
   event_source_ = ui::PlatformEventSource::CreateDefault();
 
-  gfx::Size size(800, 600);
-  window_ = std::make_unique<ui::X11Window>(
-      this, gfx::Rect(gfx::Point(100, 100), size));
+  ui::PlatformWindowInitProperties properties;
+  properties.bounds = gfx::Rect(100, 100, 800, 600);
+  auto x11_window = std::make_unique<ui::X11Window>(this, nullptr);
+  x11_window->Initialize(std::move(properties));
+
+  window_ = std::move(x11_window);
   window_->Show();
 
   // Sync up size between |window_| and |vulkan_surface_|
-  vulkan_surface_->Reshape(size, gfx::OVERLAY_TRANSFORM_NONE);
+  vulkan_surface_->Reshape(window_->GetBounds().size(),
+                           gfx::OVERLAY_TRANSFORM_NONE);
   sk_surfaces_.resize(vulkan_surface_->swap_chain()->num_images());
 }
 
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index bc50666..355a279 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -251,6 +251,10 @@
     }
     sources += [ "test/ui_controls_factory_ozone.cc" ]
   }
+
+  if (is_linux) {
+    deps += [ "//ui/platform_window/common" ]
+  }
 }
 
 executable("aura_demo") {
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc
index 3a2e00b..d17f4de 100644
--- a/ui/aura/test/aura_test_helper.cc
+++ b/ui/aura/test/aura_test_helper.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
+#include "build/build_config.h"
 #include "ui/aura/client/default_capture_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/env.h"
@@ -21,13 +22,16 @@
 #include "ui/aura/window_targeter.h"
 #include "ui/base/ime/init/input_method_factory.h"
 #include "ui/base/ime/init/input_method_initializer.h"
-#include "ui/base/platform_window_defaults.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/layer_animator.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/screen.h"
 #include "ui/wm/core/wm_state.h"
 
+#if defined(OS_LINUX)
+#include "ui/platform_window/common/platform_window_defaults.h"  // nogncheck
+#endif
+
 #if defined(USE_X11)
 #include "ui/base/x/x11_util.h"  // nogncheck
 #endif
@@ -47,7 +51,9 @@
   // Disable animations during tests.
   zero_duration_mode_ = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+#if defined(OS_LINUX)
   ui::test::EnableTestConfigForPlatformWindows();
+#endif
 }
 
 AuraTestHelper::~AuraTestHelper() {
diff --git a/ui/aura/window_tree_host_platform.cc b/ui/aura/window_tree_host_platform.cc
index fe8e2ba..fe1dc9ac 100644
--- a/ui/aura/window_tree_host_platform.cc
+++ b/ui/aura/window_tree_host_platform.cc
@@ -34,7 +34,7 @@
 #endif
 
 #if defined(USE_X11)
-#include "ui/platform_window/x11/x11_window.h"
+#include "ui/platform_window/x11/x11_window.h"  // nogncheck
 #endif
 
 namespace aura {
@@ -72,9 +72,11 @@
   platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow(
       this, std::move(properties));
 #elif defined(OS_WIN)
-  platform_window_ = std::make_unique<ui::WinWindow>(this, properties.bounds);
+  platform_window_.reset(new ui::WinWindow(this, properties.bounds));
 #elif defined(USE_X11)
-  platform_window_ = std::make_unique<ui::X11Window>(this, properties.bounds);
+  auto x11_window = std::make_unique<ui::X11Window>(this, nullptr);
+  x11_window->Initialize(std::move(properties));
+  SetPlatformWindow(std::move(x11_window));
 #else
   NOTIMPLEMENTED();
 #endif
@@ -269,7 +271,6 @@
   widget_ = gfx::kNullAcceleratedWidget;
 }
 
-void WindowTreeHostPlatform::OnActivationChanged(bool active) {
-}
+void WindowTreeHostPlatform::OnActivationChanged(bool active) {}
 
 }  // namespace aura
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 234227d..0a3994c 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -218,8 +218,6 @@
     "nine_image_painter_factory.h",
     "page_transition_types.cc",
     "page_transition_types.h",
-    "platform_window_defaults.cc",
-    "platform_window_defaults.h",
     "resource/resource_bundle.cc",
     "resource/resource_bundle.h",
     "resource/resource_bundle_android.cc",
diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn
index f0175b4..d94dae6 100644
--- a/ui/base/x/BUILD.gn
+++ b/ui/base/x/BUILD.gn
@@ -47,5 +47,6 @@
     "//ui/events/x:x",
     "//ui/gfx",
     "//ui/gfx/x",
+    "//ui/platform_window/common",
   ]
 }
diff --git a/ui/base/x/DEPS b/ui/base/x/DEPS
new file mode 100644
index 0000000..edeb0030
--- /dev/null
+++ b/ui/base/x/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+ui/platform_window/common/platform_window_defaults.h",
+]
diff --git a/ui/base/x/x11_window.cc b/ui/base/x/x11_window.cc
index fb188e0..1bb97da 100644
--- a/ui/base/x/x11_window.cc
+++ b/ui/base/x/x11_window.cc
@@ -26,6 +26,7 @@
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/platform_window/common/platform_window_defaults.h"
 
 namespace ui {
 
@@ -104,11 +105,9 @@
 
 XWindow::Configuration::~Configuration() = default;
 
-XWindow::XWindow(Delegate* delegate)
-    : delegate_(delegate),
-      xdisplay_(gfx::GetXDisplay()),
+XWindow::XWindow()
+    : xdisplay_(gfx::GetXDisplay()),
       x_root_window_(DefaultRootWindow(xdisplay_)) {
-  DCHECK(delegate_);
   DCHECK(xdisplay_);
   DCHECK_NE(x_root_window_, x11::None);
 }
@@ -153,6 +152,21 @@
   if (!activatable_)
     swa.override_redirect = x11::True;
 
+#if !defined(USE_X11)
+  // It seems like there is a difference how tests are instantiated in case of
+  // non-Ozone X11 and Ozone. See more details in
+  // EnableTestConfigForPlatformWindows. The reason why this must be here is
+  // that we removed X11WindowBase in favor of the XWindow. The X11WindowBase
+  // was only used with PlatformWindow, which meant non-Ozone X11 did not use it
+  // and set override_redirect based only on |activatable_| variable or
+  // WindowType. But now as XWindow is subclassed by X11Window, which is also a
+  // PlatformWindow, and non-Ozone X11 uses it, we have to add this workaround
+  // here. Otherwise, tests for non-Ozone X11 fail.
+  // TODO(msisov): figure out usage of this for non-Ozone X11.
+  if (UseTestConfigForPlatformWindows())
+    swa.override_redirect = true;
+#endif
+
   override_redirect_ = swa.override_redirect == x11::True;
   if (override_redirect_)
     attribute_mask |= CWOverrideRedirect;
@@ -197,8 +211,7 @@
                            bounds_in_pixels_.height(),
                            0,  // border width
                            depth, InputOutput, visual, attribute_mask, &swa);
-
-  delegate_->OnXWindowCreated();
+  OnXWindowCreated();
 
   // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL().
 
@@ -753,7 +766,7 @@
     workspace_ = base::nullopt;
 
   if (workspace_ != old_workspace)
-    delegate_->OnXWindowWorkspaceChanged();
+    OnXWindowWorkspaceChanged();
 }
 
 void XWindow::SetAlwaysOnTop(bool always_on_top) {
@@ -782,21 +795,22 @@
 }
 
 void XWindow::UpdateMinAndMaxSize() {
-  gfx::Size minimum_in_pixels = delegate_->GetMinimumSizeForXWindow();
-  gfx::Size maximum_in_pixels = delegate_->GetMaximumSizeForXWindow();
-  if (min_size_in_pixels_ == minimum_in_pixels &&
-      max_size_in_pixels_ == maximum_in_pixels)
+  base::Optional<gfx::Size> minimum_in_pixels = GetMinimumSizeForXWindow();
+  base::Optional<gfx::Size> maximum_in_pixels = GetMaximumSizeForXWindow();
+  if ((!minimum_in_pixels ||
+       min_size_in_pixels_ == minimum_in_pixels.value()) &&
+      (!maximum_in_pixels || max_size_in_pixels_ == maximum_in_pixels.value()))
     return;
 
-  min_size_in_pixels_ = minimum_in_pixels;
-  max_size_in_pixels_ = maximum_in_pixels;
+  min_size_in_pixels_ = minimum_in_pixels.value();
+  max_size_in_pixels_ = maximum_in_pixels.value();
 
   XSizeHints hints;
   hints.flags = 0;
   long supplied_return;
   XGetWMNormalHints(xdisplay_, xwindow_, &hints, &supplied_return);
 
-  if (minimum_in_pixels.IsEmpty()) {
+  if (min_size_in_pixels_.IsEmpty()) {
     hints.flags &= ~PMinSize;
   } else {
     hints.flags |= PMinSize;
@@ -804,7 +818,7 @@
     hints.min_height = min_size_in_pixels_.height();
   }
 
-  if (maximum_in_pixels.IsEmpty()) {
+  if (max_size_in_pixels_.IsEmpty()) {
     hints.flags &= ~PMaxSize;
   } else {
     hints.flags |= PMaxSize;
@@ -824,19 +838,19 @@
 
 void XWindow::AfterActivationStateChanged() {
   if (had_pointer_grab_ && !has_pointer_grab_)
-    delegate_->OnXWindowLostPointerGrab();
+    OnXWindowLostPointerGrab();
 
   bool had_pointer_capture = had_pointer_ || had_pointer_grab_;
   bool has_pointer_capture = has_pointer_ || has_pointer_grab_;
   if (had_pointer_capture && !has_pointer_capture)
-    delegate_->OnXWindowLostCapture();
+    OnXWindowLostCapture();
 
   bool is_active = IsActive();
   if (!was_active_ && is_active)
     FlashFrame(false);
 
   if (was_active_ != is_active)
-    delegate_->OnXWindowIsActiveChanged(is_active);
+    OnXWindowIsActiveChanged(is_active);
 }
 
 void XWindow::SetUseNativeFrame(bool use_native_frame) {
@@ -1036,7 +1050,7 @@
     gfx::Point window_origin = gfx::Point() + (root_point - window_point);
     if (bounds_in_pixels_.origin() != window_origin) {
       bounds_in_pixels_.set_origin(window_origin);
-      delegate_->OnXWindowMoved(window_origin);
+      OnXWindowBoundsChanged(bounds_in_pixels_);
     }
   }
 
@@ -1045,11 +1059,16 @@
   switch (xev->type) {
     case EnterNotify:
     case LeaveNotify: {
+#if defined(USE_X11)
       // Ignore EventNotify and LeaveNotify events from children of |xwindow_|.
       // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
       if (xev->xcrossing.detail != NotifyInferior) {
-        delegate_->OnXWindowChildCrossingEvent(xev);
-      } else {
+        DCHECK(xev);
+        ui::MouseEvent mouse_event(xev);
+        OnXWindowEvent(&mouse_event);
+      } else
+#endif
+      {
         bool is_enter = xev->type == EnterNotify;
         OnCrossingEvent(is_enter, xev->xcrossing.focus, xev->xcrossing.mode,
                         xev->xcrossing.detail);
@@ -1059,13 +1078,13 @@
     case Expose: {
       gfx::Rect damage_rect_in_pixels(xev->xexpose.x, xev->xexpose.y,
                                       xev->xexpose.width, xev->xexpose.height);
-      delegate_->OnXWindowDamageEvent(damage_rect_in_pixels);
+      OnXWindowDamageEvent(damage_rect_in_pixels);
       break;
     }
 #if !defined(USE_OZONE)
     case KeyPress:
     case KeyRelease:
-      delegate_->OnXWindowRawKeyEvent(xev);
+      OnXWindowRawKeyEvent(xev);
       break;
     case ButtonPress:
     case ButtonRelease: {
@@ -1073,13 +1092,13 @@
       switch (event_type) {
         case ui::ET_MOUSEWHEEL: {
           ui::MouseWheelEvent mouseev(xev);
-          delegate_->OnXWindowMouseEvent(&mouseev);
+          OnXWindowEvent(&mouseev);
           break;
         }
         case ui::ET_MOUSE_PRESSED:
         case ui::ET_MOUSE_RELEASED: {
           ui::MouseEvent mouseev(xev);
-          delegate_->OnXWindowMouseEvent(&mouseev);
+          OnXWindowEvent(&mouseev);
           break;
         }
         case ui::ET_UNKNOWN:
@@ -1137,7 +1156,7 @@
         case ui::ET_TOUCH_PRESSED:
         case ui::ET_TOUCH_RELEASED: {
           ui::TouchEvent touchev(xev);
-          delegate_->OnXWindowTouchEvent(&touchev);
+          OnXWindowEvent(&touchev);
           break;
         }
         case ui::ET_MOUSE_MOVED:
@@ -1162,12 +1181,12 @@
           // DT_CMT_SCROLL_ data. See more discussion in
           // https://crrev.com/c/853953
           if (mouseev.type() != ui::ET_UNKNOWN)
-            delegate_->OnXWindowMouseEvent(&mouseev);
+            OnXWindowEvent(&mouseev);
           break;
         }
         case ui::ET_MOUSEWHEEL: {
           ui::MouseWheelEvent mouseev(xev);
-          delegate_->OnXWindowMouseEvent(&mouseev);
+          OnXWindowEvent(&mouseev);
           break;
         }
         case ui::ET_SCROLL_FLING_START:
@@ -1179,13 +1198,13 @@
           // event and we need delta to determine which element to scroll on
           // phaseBegan.
           if (scrollev.x_offset() != 0.0 || scrollev.y_offset() != 0.0)
-            delegate_->OnXWindowScrollEvent(&scrollev);
+            OnXWindowEvent(&scrollev);
           break;
         }
         case ui::ET_KEY_PRESSED:
         case ui::ET_KEY_RELEASED: {
           ui::KeyEvent key_event(xev);
-          delegate_->OnXWindowKeyEvent(&key_event);
+          OnXWindowEvent(&key_event);
           break;
         }
         case ui::ET_UNKNOWN:
@@ -1211,7 +1230,7 @@
       has_pointer_grab_ = false;
       has_pointer_focus_ = false;
       has_window_focus_ = false;
-      delegate_->OnXWindowUnmapped();
+      OnXWindowUnmapped();
       break;
     }
     case ClientMessage: {
@@ -1220,7 +1239,7 @@
         Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]);
         if (protocol == gfx::GetAtom("WM_DELETE_WINDOW")) {
           // We have received a close message from the window manager.
-          delegate_->OnXWindowCloseRequested();
+          OnXWindowCloseRequested();
         } else if (protocol == gfx::GetAtom("_NET_WM_PING")) {
           XEvent reply_event = *xev;
           reply_event.xclient.window = x_root_window_;
@@ -1235,7 +1254,7 @@
           pending_counter_value_is_extended_ = xev->xclient.data.l[4] != 0;
         }
       } else {
-        delegate_->OnXWindowDragDropEvent(xev);
+        OnXWindowDragDropEvent(xev);
       }
       break;
     }
@@ -1274,7 +1293,7 @@
       }
 
       ui::MouseEvent mouseev(xev);
-      delegate_->OnXWindowMouseEvent(&mouseev);
+      OnXWindowEvent(&mouseev);
       break;
     }
 #endif
@@ -1290,7 +1309,7 @@
       break;
     }
     case SelectionNotify: {
-      delegate_->OnXWindowSelectionEvent(xev);
+      OnXWindowSelectionEvent(xev);
       break;
     }
   }
@@ -1314,7 +1333,7 @@
 
 void XWindow::OnWindowMapped() {
   window_mapped_in_server_ = true;
-  delegate_->OnXWindowMapped();
+  OnXWindowMapped();
   // Some WMs only respect maximize hints after the window has been mapped.
   // Check whether we need to re-do a maximization.
   if (should_maximize_after_map_) {
@@ -1353,11 +1372,10 @@
   previous_bounds_in_pixels_ = bounds_in_pixels_;
   bounds_in_pixels_ = bounds_in_pixels;
 
-  if (origin_changed)
-    delegate_->OnXWindowMoved(bounds_in_pixels_.origin());
-
   if (size_changed)
-    delegate_->OnXWindowSizeChanged(bounds_in_pixels_.size());
+    DispatchResize();
+  else if (origin_changed)
+    OnXWindowBoundsChanged(bounds_in_pixels_);
 }
 
 void XWindow::SetWMSpecState(bool enabled, XAtom state1, XAtom state2) {
@@ -1403,8 +1421,7 @@
 
   is_always_on_top_ = ui::HasWMSpecProperty(
       window_properties_, gfx::GetAtom("_NET_WM_STATE_ABOVE"));
-
-  delegate_->OnXWindowStateChanged();
+  OnXWindowStateChanged();
 }
 
 void XWindow::OnFrameExtentsUpdated() {
@@ -1448,7 +1465,7 @@
     // compositor.
     delayed_resize_task_.Reset(base::BindOnce(&XWindow::DelayedResize,
                                               weak_factory_.GetWeakPtr(),
-                                              bounds_in_pixels_.size()));
+                                              bounds_in_pixels_));
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, delayed_resize_task_.callback());
     return;
@@ -1465,10 +1482,10 @@
   // If _NET_WM_SYNC_REQUEST is used to synchronize with compositor during
   // resizing, the compositor will not resize the window, until last resize is
   // handled, so we don't need accumulate resize events.
-  DelayedResize(bounds_in_pixels_.size());
+  DelayedResize(bounds_in_pixels_);
 }
 
-void XWindow::DelayedResize(const gfx::Size& size_in_pixels) {
+void XWindow::DelayedResize(const gfx::Rect& bounds_in_pixels) {
   if (configure_counter_value_is_extended_ &&
       (current_counter_value_ % 2) == 0) {
     // Increase the |extended_update_counter_|, so the compositor will know we
@@ -1478,7 +1495,7 @@
     SyncSetCounter(xdisplay_, extended_update_counter_,
                    ++current_counter_value_);
   }
-  delegate_->OnXWindowSizeChanged(size_in_pixels);
+  OnXWindowBoundsChanged(bounds_in_pixels);
   CancelResize();
 }
 
@@ -1525,43 +1542,4 @@
   has_pointer_barriers_ = false;
 }
 
-// Empty/stub implementation of XWindow::Delegate methods, which are considered
-// optional for ui::XWindow users, making it possible to handle only events of
-// interest.
-void XWindow::Delegate::OnXWindowMapped() {}
-
-void XWindow::Delegate::OnXWindowUnmapped() {}
-
-void XWindow::Delegate::OnXWindowMoved(const gfx::Point&) {}
-
-void XWindow::Delegate::OnXWindowWorkspaceChanged() {}
-
-void XWindow::Delegate::OnXWindowLostPointerGrab() {}
-
-void XWindow::Delegate::OnXWindowLostCapture() {}
-
-void XWindow::Delegate::OnXWindowKeyEvent(ui::KeyEvent*) {}
-
-void XWindow::Delegate::OnXWindowMouseEvent(ui::MouseEvent*) {}
-
-void XWindow::Delegate::OnXWindowTouchEvent(ui::TouchEvent*) {}
-
-void XWindow::Delegate::OnXWindowScrollEvent(ui::ScrollEvent*) {}
-
-void XWindow::Delegate::OnXWindowSelectionEvent(XEvent*) {}
-
-void XWindow::Delegate::OnXWindowDragDropEvent(XEvent*) {}
-
-void XWindow::Delegate::OnXWindowChildCrossingEvent(XEvent*) {}
-
-void XWindow::Delegate::OnXWindowRawKeyEvent(XEvent*) {}
-
-gfx::Size XWindow::Delegate::GetMinimumSizeForXWindow() {
-  return gfx::Size();
-}
-
-gfx::Size XWindow::Delegate::GetMaximumSizeForXWindow() {
-  return gfx::Size();
-}
-
 }  // namespace ui
diff --git a/ui/base/x/x11_window.h b/ui/base/x/x11_window.h
index 8d2e1384..9db97d2f 100644
--- a/ui/base/x/x11_window.h
+++ b/ui/base/x/x11_window.h
@@ -29,10 +29,7 @@
 
 namespace ui {
 
-class KeyEvent;
-class MouseEvent;
-class TouchEvent;
-class ScrollEvent;
+class Event;
 class XScopedEventSelector;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -88,7 +85,7 @@
     std::string wm_role_name;
   };
 
-  explicit XWindow(Delegate* delegate);
+  XWindow();
   virtual ~XWindow();
 
   void Init(const Configuration& config);
@@ -188,7 +185,7 @@
   // Handle the state change since BeforeActivationStateChanged().
   void AfterActivationStateChanged();
 
-  void DelayedResize(const gfx::Size& size_in_pixels);
+  void DelayedResize(const gfx::Rect& bounds_in_pixels);
 
   // Updates |xwindow_|'s _NET_WM_USER_TIME if |xwindow_| is active.
   void UpdateWMUserTime(XEvent* event);
@@ -209,7 +206,25 @@
 
   void UnconfineCursor();
 
-  Delegate* delegate_;
+  // Interface that must be used by a class that inherits the XWindow to receive
+  // different messages from X Server.
+  virtual void OnXWindowCreated() = 0;
+  virtual void OnXWindowStateChanged() = 0;
+  virtual void OnXWindowDamageEvent(const gfx::Rect& damage_rect) = 0;
+  virtual void OnXWindowBoundsChanged(const gfx::Rect& size) = 0;
+  virtual void OnXWindowCloseRequested() = 0;
+  virtual void OnXWindowIsActiveChanged(bool active) = 0;
+  virtual void OnXWindowMapped() = 0;
+  virtual void OnXWindowUnmapped() = 0;
+  virtual void OnXWindowWorkspaceChanged() = 0;
+  virtual void OnXWindowLostPointerGrab() = 0;
+  virtual void OnXWindowLostCapture() = 0;
+  virtual void OnXWindowEvent(ui::Event* event) = 0;
+  virtual void OnXWindowSelectionEvent(XEvent* xev) = 0;
+  virtual void OnXWindowDragDropEvent(XEvent* xev) = 0;
+  virtual void OnXWindowRawKeyEvent(XEvent* xev) = 0;
+  virtual base::Optional<gfx::Size> GetMinimumSizeForXWindow() = 0;
+  virtual base::Optional<gfx::Size> GetMaximumSizeForXWindow() = 0;
 
   // The display and the native X window hosting the root window.
   XDisplay* xdisplay_ = nullptr;
@@ -347,44 +362,6 @@
   DISALLOW_COPY_AND_ASSIGN(XWindow);
 };
 
-// Delegate interface used to communicate the XWindow API client about events
-// of interest and request information which depends on external components.
-class COMPONENT_EXPORT(UI_BASE_X) XWindow::Delegate {
- public:
-  virtual void OnXWindowCreated() = 0;
-  virtual void OnXWindowStateChanged() = 0;
-  virtual void OnXWindowDamageEvent(const gfx::Rect& damage_rect) = 0;
-  virtual void OnXWindowSizeChanged(const gfx::Size& size) = 0;
-  virtual void OnXWindowCloseRequested() = 0;
-  virtual void OnXWindowIsActiveChanged(bool active) = 0;
-
-  // Optional Hooks
-  virtual void OnXWindowMapped();
-  virtual void OnXWindowUnmapped();
-  virtual void OnXWindowMoved(const gfx::Point& window_origin);
-  virtual void OnXWindowWorkspaceChanged();
-  virtual void OnXWindowLostPointerGrab();
-  virtual void OnXWindowLostCapture();
-
-  // TODO(crbug.com/981606): Consider unifying event handling functions
-  virtual void OnXWindowKeyEvent(ui::KeyEvent* key_event);
-  virtual void OnXWindowMouseEvent(ui::MouseEvent* event);
-  virtual void OnXWindowTouchEvent(ui::TouchEvent* event);
-  virtual void OnXWindowScrollEvent(ui::ScrollEvent* event);
-
-  virtual void OnXWindowSelectionEvent(XEvent* xev);
-  virtual void OnXWindowDragDropEvent(XEvent* xev);
-  virtual void OnXWindowChildCrossingEvent(XEvent* xev);
-
-  // TODO(crbug.com/981606): DesktopWindowTreeHostX11 forward raw |XEvent|s to
-  // ATK components that currently live in views layer.  Remove once ATK code
-  // is reworked to be reusable.
-  virtual void OnXWindowRawKeyEvent(XEvent* xev);
-
-  virtual gfx::Size GetMinimumSizeForXWindow();
-  virtual gfx::Size GetMaximumSizeForXWindow();
-};
-
 }  // namespace ui
 
 #endif  // UI_BASE_X_X11_WINDOW_H_
diff --git a/ui/events/platform/x11/x11_event_source.h b/ui/events/platform/x11/x11_event_source.h
index e44fb018..a655cc82 100644
--- a/ui/events/platform/x11/x11_event_source.h
+++ b/ui/events/platform/x11/x11_event_source.h
@@ -160,8 +160,8 @@
 
   // State necessary for UpdateLastSeenServerTime
   bool dummy_initialized_;
-  XWindow dummy_window_;
-  XAtom dummy_atom_;
+  ::XWindow dummy_window_;
+  ::XAtom dummy_atom_;
   std::unique_ptr<XScopedEventSelector> dummy_window_events_;
 
   // Keeps track of whether this source should continue to dispatch all the
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index fa26af6..4657246 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -474,6 +474,10 @@
     "//ui/base",
   ]
 
+  if (is_linux) {
+    deps += [ "//ui/platform_window/common" ]
+  }
+
   if (use_x11) {
     configs += [ "//build/config/linux:x11" ]
     deps += [ "//ui/platform_window/x11" ]
diff --git a/ui/gl/test/DEPS b/ui/gl/test/DEPS
index 8330a13..0349f94 100644
--- a/ui/gl/test/DEPS
+++ b/ui/gl/test/DEPS
@@ -5,4 +5,5 @@
   "+mojo/core/embedder",
   "+services/service_manager/public",
   "+services/viz/public",
+  "+ui/platform_window/common/platform_window_defaults.h",
 ]
diff --git a/ui/gl/test/gl_surface_test_support.cc b/ui/gl/test/gl_surface_test_support.cc
index b2e456b..0b446da 100644
--- a/ui/gl/test/gl_surface_test_support.cc
+++ b/ui/gl/test/gl_surface_test_support.cc
@@ -9,12 +9,15 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "build/build_config.h"
-#include "ui/base/platform_window_defaults.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/init/gl_factory.h"
 
+#if defined(OS_LINUX)
+#include "ui/platform_window/common/platform_window_defaults.h"  // nogncheck
+#endif
+
 #if defined(USE_OZONE)
 #include "ui/ozone/public/ozone_platform.h"
 #endif
@@ -40,7 +43,9 @@
   ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
 #endif
 
+#if defined(OS_LINUX)
   ui::test::EnableTestConfigForPlatformWindows();
+#endif
 
   bool use_software_gl = true;
 
diff --git a/ui/ozone/platform/cast/platform_window_cast.cc b/ui/ozone/platform/cast/platform_window_cast.cc
index 697a3e3..84b68c8 100644
--- a/ui/ozone/platform/cast/platform_window_cast.cc
+++ b/ui/ozone/platform/cast/platform_window_cast.cc
@@ -10,7 +10,6 @@
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/cast/platform_window_cast.h b/ui/ozone/platform/cast/platform_window_cast.h
index 500a5bf8..35fb374 100644
--- a/ui/ozone/platform/cast/platform_window_cast.h
+++ b/ui/ozone/platform/cast/platform_window_cast.h
@@ -7,12 +7,11 @@
 
 #include "base/macros.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/stub/stub_window.h"
 
 namespace ui {
 
-class PlatformWindowDelegate;
-
 class PlatformWindowCast : public StubWindow, public PlatformEventDispatcher {
  public:
   PlatformWindowCast(PlatformWindowDelegate* delegate, const gfx::Rect& bounds);
diff --git a/ui/ozone/platform/drm/host/drm_window_host.cc b/ui/ozone/platform/drm/host/drm_window_host.cc
index e76d4d4..4c5a1b2 100644
--- a/ui/ozone/platform/drm/host/drm_window_host.cc
+++ b/ui/ozone/platform/drm/host/drm_window_host.cc
@@ -17,7 +17,6 @@
 #include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
 #include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
 #include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/drm/host/drm_window_host.h b/ui/ozone/platform/drm/host/drm_window_host.h
index b437497..2524f21 100644
--- a/ui/ozone/platform/drm/host/drm_window_host.h
+++ b/ui/ozone/platform/drm/host/drm_window_host.h
@@ -16,6 +16,7 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
 #include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
@@ -25,7 +26,6 @@
 class DrmWindowHostManager;
 class EventFactoryEvdev;
 class GpuThreadAdapter;
-class PlatformWindowDelegate;
 
 // Implementation of the platform window. This object and its handle |widget_|
 // uniquely identify a window. Since the DRI/GBM platform is split into 2
diff --git a/ui/ozone/platform/headless/headless_window.cc b/ui/ozone/platform/headless/headless_window.cc
index 3e38770..d4444e3 100644
--- a/ui/ozone/platform/headless/headless_window.cc
+++ b/ui/ozone/platform/headless/headless_window.cc
@@ -9,7 +9,6 @@
 #include "build/build_config.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/ozone/platform/headless/headless_window_manager.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/headless/headless_window.h b/ui/ozone/platform/headless/headless_window.h
index 0690480..d13c5c7 100644
--- a/ui/ozone/platform/headless/headless_window.h
+++ b/ui/ozone/platform/headless/headless_window.h
@@ -8,11 +8,11 @@
 #include "base/macros.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/stub/stub_window.h"
 
 namespace ui {
 
-class PlatformWindowDelegate;
 class HeadlessWindowManager;
 
 class HeadlessWindow : public StubWindow {
diff --git a/ui/ozone/platform/magma/magma_window.cc b/ui/ozone/platform/magma/magma_window.cc
index 4b7d841..3e63cd6 100644
--- a/ui/ozone/platform/magma/magma_window.cc
+++ b/ui/ozone/platform/magma/magma_window.cc
@@ -9,7 +9,6 @@
 #include "build/build_config.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/ozone/platform/magma/magma_window_manager.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/magma/magma_window.h b/ui/ozone/platform/magma/magma_window.h
index 94847f99..fc7186f 100644
--- a/ui/ozone/platform/magma/magma_window.h
+++ b/ui/ozone/platform/magma/magma_window.h
@@ -8,11 +8,11 @@
 #include "base/macros.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/stub/stub_window.h"
 
 namespace ui {
 
-class PlatformWindowDelegate;
 class MagmaWindowManager;
 
 class MagmaWindow : public StubWindow {
diff --git a/ui/ozone/platform/scenic/scenic_window.cc b/ui/ozone/platform/scenic/scenic_window.cc
index 2599ee7..b89d38b 100644
--- a/ui/ozone/platform/scenic/scenic_window.cc
+++ b/ui/ozone/platform/scenic/scenic_window.cc
@@ -18,7 +18,6 @@
 #include "ui/events/ozone/events_ozone.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/ozone/platform/scenic/scenic_window_manager.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/scenic/scenic_window.h b/ui/ozone/platform/scenic/scenic_window.h
index e8f85db5..9376a08 100644
--- a/ui/ozone/platform/scenic/scenic_window.h
+++ b/ui/ozone/platform/scenic/scenic_window.h
@@ -22,11 +22,11 @@
 #include "ui/gfx/geometry/size_f.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
 class ScenicWindowManager;
-class PlatformWindowDelegate;
 
 class COMPONENT_EXPORT(OZONE) ScenicWindow
     : public PlatformWindow,
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
index 4909a5d..6d5533a 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -166,6 +166,10 @@
       is_tooltip_ = true;
       break;
     case ui::PlatformWindowType::kWindow:
+    case ui::PlatformWindowType::kBubble:
+    case ui::PlatformWindowType::kDrag:
+      // TODO(msisov): Figure out what kind of surface we need to create for
+      // bubble and drag windows.
       CreateXdgSurface();
       break;
   }
diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h
index c5f4e55..0548cbc 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.h
+++ b/ui/ozone/platform/wayland/host/wayland_window.h
@@ -31,7 +31,6 @@
 
 class BitmapCursorOzone;
 class OSExchangeData;
-class PlatformWindowDelegate;
 class WaylandConnection;
 class XDGPopupWrapper;
 class XDGSurfaceWrapper;
diff --git a/ui/ozone/platform/windows/windows_window.cc b/ui/ozone/platform/windows/windows_window.cc
index 8da06d17..1e0ecdc 100644
--- a/ui/ozone/platform/windows/windows_window.cc
+++ b/ui/ozone/platform/windows/windows_window.cc
@@ -9,7 +9,6 @@
 #include "build/build_config.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/ozone/platform/windows/windows_window_manager.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
 namespace ui {
 
diff --git a/ui/ozone/platform/windows/windows_window.h b/ui/ozone/platform/windows/windows_window.h
index 87935e2c..fe5049d 100644
--- a/ui/ozone/platform/windows/windows_window.h
+++ b/ui/ozone/platform/windows/windows_window.h
@@ -8,12 +8,11 @@
 #include "base/macros.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/win/win_window.h"
 
 namespace ui {
 
-class PlatformWindowDelegate;
-
 class WindowsWindow : public WinWindow {
  public:
   WindowsWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds);
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
index 470673d..ed98346 100644
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -83,8 +83,9 @@
   std::unique_ptr<PlatformWindow> CreatePlatformWindow(
       PlatformWindowDelegate* delegate,
       PlatformWindowInitProperties properties) override {
-    std::unique_ptr<X11WindowOzone> window = std::make_unique<X11WindowOzone>(
-        delegate, properties, window_manager_.get());
+    std::unique_ptr<X11WindowOzone> window =
+        std::make_unique<X11WindowOzone>(delegate, window_manager_.get());
+    window->Initialize(std::move(properties));
     window->SetTitle(base::ASCIIToUTF16("Ozone X11"));
     return std::move(window);
   }
diff --git a/ui/ozone/platform/x11/x11_screen_ozone.cc b/ui/ozone/platform/x11/x11_screen_ozone.cc
index d3b1f25..54a8a076 100644
--- a/ui/ozone/platform/x11/x11_screen_ozone.cc
+++ b/ui/ozone/platform/x11/x11_screen_ozone.cc
@@ -88,7 +88,7 @@
   if (!window_bounds.Contains(screen_point_in_pixels_))
     return false;
 
-  ::Region shape = window->GetShape();
+  ::Region shape = window->shape();
   if (!shape)
     return true;
 
diff --git a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
index b1bfba5b..2a4b035 100644
--- a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
+++ b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
@@ -103,8 +103,10 @@
     EXPECT_CALL(*delegate, OnAcceleratedWidgetAvailable(_))
         .WillOnce(StoreWidget(widget));
     PlatformWindowInitProperties init_params(bounds);
-    return std::make_unique<X11WindowOzone>(delegate, init_params,
-                                            window_manager_.get());
+    auto window =
+        std::make_unique<X11WindowOzone>(delegate, window_manager_.get());
+    window->Initialize(std::move(init_params));
+    return window;
   }
 
   MockDisplayObserver display_observer_;
diff --git a/ui/ozone/platform/x11/x11_window_ozone.cc b/ui/ozone/platform/x11/x11_window_ozone.cc
index 5f2b621..f62b39e 100644
--- a/ui/ozone/platform/x11/x11_window_ozone.cc
+++ b/ui/ozone/platform/x11/x11_window_ozone.cc
@@ -10,7 +10,6 @@
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "ui/base/platform_window_defaults.h"
 #include "ui/base/x/x11_util.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
@@ -24,71 +23,14 @@
 
 namespace ui {
 
-namespace {
-
-ui::XWindow::Configuration ConvertInitPropertiesToXWindowConfig(
-    const PlatformWindowInitProperties& properties) {
-  using WindowType = ui::XWindow::WindowType;
-  using WindowOpacity = ui::XWindow::WindowOpacity;
-  ui::XWindow::Configuration config;
-
-  switch (properties.type) {
-    case PlatformWindowType::kWindow:
-      config.type = WindowType::kWindow;
-      break;
-    case PlatformWindowType::kMenu:
-      config.type = WindowType::kMenu;
-      break;
-    case PlatformWindowType::kTooltip:
-      config.type = WindowType::kTooltip;
-      break;
-    case PlatformWindowType::kPopup:
-      config.type = WindowType::kPopup;
-      break;
-  }
-
-  switch (properties.opacity) {
-    case PlatformWindowOpacity::kInferOpacity:
-      config.opacity = WindowOpacity::kInferOpacity;
-      break;
-    case PlatformWindowOpacity::kOpaqueWindow:
-      config.opacity = WindowOpacity::kOpaqueWindow;
-      break;
-    case PlatformWindowOpacity::kTranslucentWindow:
-      config.opacity = WindowOpacity::kTranslucentWindow;
-      break;
-  }
-
-  config.bounds = properties.bounds;
-  config.force_show_in_taskbar = properties.force_show_in_taskbar;
-  config.keep_on_top = properties.keep_on_top;
-  config.visible_on_all_workspaces = properties.visible_on_all_workspaces;
-  config.remove_standard_frame = properties.remove_standard_frame;
-  config.workspace = properties.workspace;
-  config.wm_class_name = properties.wm_class_name;
-  config.wm_class_class = properties.wm_class_class;
-  config.wm_role_name = properties.wm_role_name;
-
-  // TODO(nickdiego): {Use,Enable}TestConfigForPlatformWindows are used by test
-  // infra to disable platform windows activation. Figure out another way to do
-  // this in case Widget::InitParams::activation is needed in the future.
-  config.activatable =
-      properties.activatable && !UseTestConfigForPlatformWindows();
-
-  return config;
-}
-
-}  // namespace
-
 X11WindowOzone::X11WindowOzone(PlatformWindowDelegate* delegate,
-                               const PlatformWindowInitProperties& properties,
                                X11WindowManagerOzone* window_manager)
-    : delegate_(delegate),
-      window_manager_(window_manager),
-      x11_window_(std::make_unique<ui::XWindow>(this)) {
-  DCHECK(delegate_);
+    : X11Window(delegate, nullptr), window_manager_(window_manager) {
   DCHECK(window_manager_);
-  Init(properties);
+
+  // Set a class property key, which allows |this| to be used for interactive
+  // events, e.g. move or resize.
+  SetWmMoveResizeHandler(this, static_cast<WmMoveResizeHandler*>(this));
 }
 
 X11WindowOzone::~X11WindowOzone() {
@@ -96,21 +38,8 @@
   Close();
 }
 
-void X11WindowOzone::Init(const PlatformWindowInitProperties& params) {
-  XWindow::Configuration config = ConvertInitPropertiesToXWindowConfig(params);
-  x11_window_->Init(config);
-
-  // Set a class property key, which allows |this| to be used for interactive
-  // events, e.g. move or resize.
-  SetWmMoveResizeHandler(this, static_cast<WmMoveResizeHandler*>(this));
-}
-
-void X11WindowOzone::Show() {
-  x11_window_->Map();
-}
-
-void X11WindowOzone::Hide() {
-  x11_window_->Hide();
+void X11WindowOzone::OnLostCapture() {
+  X11Window::OnXWindowLostCapture();
 }
 
 void X11WindowOzone::Close() {
@@ -121,39 +50,14 @@
   RemoveFromWindowManager();
   SetWidget(x11::None);
 
-  x11_window_->Close();
-  delegate_->OnClosed();
-}
-
-void X11WindowOzone::SetBounds(const gfx::Rect& bounds) {
-  DCHECK(!bounds.size().IsEmpty());
-
-  // Assume that the resize will go through as requested, which should be the
-  // case if we're running without a window manager.  If there's a window
-  // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
-  // (possibly synthetic) ConfigureNotify about the actual size and correct
-  // |bounds_| later.
-  x11_window_->SetBounds(bounds);
-
-  // Even if the pixel bounds didn't change this call to the delegate should
-  // still happen. The device scale factor may have changed which effectively
-  // changes the bounds.
-  delegate_->OnBoundsChanged(bounds);
-}
-
-gfx::Rect X11WindowOzone::GetBounds() {
-  return x11_window_->bounds();
-}
-
-void X11WindowOzone::SetTitle(const base::string16& title) {
-  x11_window_->SetTitle(title);
+  X11Window::Close();
 }
 
 void X11WindowOzone::SetCapture() {
   if (HasCapture())
     return;
 
-  x11_window_->GrabPointer();
+  X11Window::SetCapture();
   window_manager_->GrabEvents(this);
 }
 
@@ -161,90 +65,13 @@
   if (!HasCapture())
     return;
 
-  x11_window_->ReleasePointerGrab();
+  X11Window::ReleasePointerGrab();
   window_manager_->UngrabEvents(this);
 }
 
 bool X11WindowOzone::HasCapture() const {
   return window_manager_->event_grabber() == this;
 }
-
-void X11WindowOzone::OnLostCapture() {
-  delegate_->OnLostCapture();
-}
-
-void X11WindowOzone::ToggleFullscreen() {
-  bool is_fullscreen = state_ == PlatformWindowState::kFullScreen;
-  x11_window_->SetFullscreen(!is_fullscreen);
-}
-
-void X11WindowOzone::Maximize() {
-  if (state_ == PlatformWindowState::kFullScreen)
-    ToggleFullscreen();
-
-  x11_window_->Maximize();
-}
-
-void X11WindowOzone::Minimize() {
-  x11_window_->Minimize();
-}
-
-void X11WindowOzone::Restore() {
-  if (state_ == PlatformWindowState::kFullScreen)
-    ToggleFullscreen();
-
-  if (state_ == PlatformWindowState::kMaximized) {
-    x11_window_->Unmaximize();
-  }
-}
-
-PlatformWindowState X11WindowOzone::GetPlatformWindowState() const {
-  return state_;
-}
-
-void X11WindowOzone::Activate() {
-  x11_window_->Activate();
-}
-
-void X11WindowOzone::Deactivate() {
-  x11_window_->Deactivate();
-}
-
-void X11WindowOzone::SetUseNativeFrame(bool use_native_frame) {
-  x11_window_->SetUseNativeFrame(use_native_frame);
-}
-
-void X11WindowOzone::MoveCursorTo(const gfx::Point& location) {
-  x11_window_->MoveCursorTo(location);
-}
-
-void X11WindowOzone::ConfineCursorToBounds(const gfx::Rect& bounds) {
-  x11_window_->ConfineCursorTo(bounds);
-}
-
-void X11WindowOzone::SetRestoredBoundsInPixels(const gfx::Rect& bounds) {
-  // TODO(crbug.com/848131): Restore bounds on restart
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-gfx::Rect X11WindowOzone::GetRestoredBoundsInPixels() const {
-  // TODO(crbug.com/848131): Restore bounds on restart
-  NOTIMPLEMENTED_LOG_ONCE();
-  return gfx::Rect();
-}
-
-bool X11WindowOzone::IsVisible() const {
-  return x11_window_->IsVisible();
-}
-
-gfx::Rect X11WindowOzone::GetOutterBounds() const {
-  return x11_window_->GetOutterBounds();
-}
-
-::Region X11WindowOzone::GetShape() const {
-  return x11_window_->shape();
-}
-
 void X11WindowOzone::PrepareForShutdown() {
   DCHECK(X11EventSource::GetInstance());
   X11EventSource::GetInstance()->RemoveXEventDispatcher(this);
@@ -252,7 +79,7 @@
 
 void X11WindowOzone::SetCursor(PlatformCursor cursor) {
   X11CursorOzone* cursor_ozone = static_cast<X11CursorOzone*>(cursor);
-  x11_window_->SetCursor(cursor_ozone->xcursor());
+  XWindow::SetCursor(cursor_ozone->xcursor());
 }
 
 void X11WindowOzone::RemoveFromWindowManager() {
@@ -271,7 +98,7 @@
   if (is_shutting_down_)
     return;
 
-  handle_next_event_ = x11_window_->IsTargetedBy(*xev);
+  handle_next_event_ = XWindow::IsTargetedBy(*xev);
 }
 
 void X11WindowOzone::PlatformEventDispatchFinished() {
@@ -283,20 +110,20 @@
 }
 
 bool X11WindowOzone::DispatchXEvent(XEvent* xev) {
-  if (!x11_window_->IsTargetedBy(*xev))
+  if (!XWindow::IsTargetedBy(*xev))
     return false;
 
-  x11_window_->ProcessEvent(xev);
+  XWindow::ProcessEvent(xev);
   return true;
 }
 
 bool X11WindowOzone::CanDispatchEvent(const PlatformEvent& event) {
-  DCHECK_NE(x11_window_->window(), x11::None);
+  DCHECK_NE(XWindow::window(), x11::None);
   return handle_next_event_;
 }
 
 uint32_t X11WindowOzone::DispatchEvent(const PlatformEvent& event) {
-  DCHECK_NE(x11_window_->window(), x11::None);
+  DCHECK_NE(XWindow::window(), x11::None);
 
   if (!window_manager_->event_grabber() ||
       window_manager_->event_grabber() == this) {
@@ -304,7 +131,7 @@
     // (eg. double click) are broken.
     DispatchEventFromNativeUiEvent(
         event, base::BindOnce(&PlatformWindowDelegate::DispatchEvent,
-                              base::Unretained(delegate_)));
+                              base::Unretained(platform_window_delegate())));
     return POST_DISPATCH_STOP_PROPAGATION;
   }
 
@@ -321,7 +148,7 @@
 void X11WindowOzone::DispatchHostWindowDragMovement(
     int hittest,
     const gfx::Point& pointer_location) {
-  x11_window_->WmMoveResize(hittest, pointer_location);
+  XWindow::WmMoveResize(hittest, pointer_location);
 }
 
 void X11WindowOzone::SetWidget(XID xid) {
@@ -330,58 +157,19 @@
   // than 32 bits values on the wire (see https://crbug.com/607014 for more
   // details). So, It's safe to use static_cast here.
   widget_ = static_cast<gfx::AcceleratedWidget>(xid);
-  if (widget_ != gfx::kNullAcceleratedWidget)
-    delegate_->OnAcceleratedWidgetAvailable(widget_);
 }
 
 void X11WindowOzone::OnXWindowCreated() {
-  DCHECK_NE(x11_window_->window(), x11::None);
-  SetWidget(x11_window_->window());
+  DCHECK_NE(XWindow::window(), x11::None);
+  SetWidget(XWindow::window());
 
   window_manager_->AddWindow(this);
+  X11Window::OnXWindowCreated();
+}
 
+void X11WindowOzone::SetPlatformEventDispatcher() {
   DCHECK(X11EventSource::GetInstance());
   X11EventSource::GetInstance()->AddXEventDispatcher(this);
 }
 
-void X11WindowOzone::OnXWindowStateChanged() {
-  // Propagate the window state information to the client. Note that the order
-  // of checks is important here, because window can have several proprties at
-  // the same time.
-  PlatformWindowState old_state = state_;
-  if (x11_window_->IsMinimized()) {
-    state_ = PlatformWindowState::kMinimized;
-  } else if (x11_window_->IsFullscreen()) {
-    state_ = PlatformWindowState::kFullScreen;
-  } else if (x11_window_->IsMaximized()) {
-    state_ = PlatformWindowState::kMaximized;
-  } else {
-    state_ = PlatformWindowState::kNormal;
-  }
-
-  if (old_state != state_)
-    delegate_->OnWindowStateChanged(state_);
-}
-
-void X11WindowOzone::OnXWindowDamageEvent(
-    const gfx::Rect& damage_rect_in_pixels) {
-  delegate_->OnDamageRect(damage_rect_in_pixels);
-}
-
-void X11WindowOzone::OnXWindowSizeChanged(const gfx::Size&) {
-  delegate_->OnBoundsChanged(x11_window_->bounds());
-}
-
-void X11WindowOzone::OnXWindowCloseRequested() {
-  delegate_->OnCloseRequest();
-}
-
-void X11WindowOzone::OnXWindowLostCapture() {
-  OnLostCapture();
-}
-
-void X11WindowOzone::OnXWindowIsActiveChanged(bool active) {
-  delegate_->OnActivationChanged(active);
-}
-
 }  // namespace ui
diff --git a/ui/ozone/platform/x11/x11_window_ozone.h b/ui/ozone/platform/x11/x11_window_ozone.h
index 33e60a8..8b66d6ef 100644
--- a/ui/ozone/platform/x11/x11_window_ozone.h
+++ b/ui/ozone/platform/x11/x11_window_ozone.h
@@ -16,8 +16,8 @@
 #include "ui/events/x/x11_window_event_manager.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/x/x11_types.h"
-#include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
+#include "ui/platform_window/x11/x11_window.h"
 
 namespace ui {
 
@@ -25,44 +25,21 @@
 struct PlatformWindowInitProperties;
 
 // PlatformWindow implementation for X11 Ozone. PlatformEvents are ui::Events.
-class X11WindowOzone : public PlatformWindow,
-                       public PlatformEventDispatcher,
+class X11WindowOzone : public X11Window,
                        public WmMoveResizeHandler,
-                       public XEventDispatcher,
-                       public XWindow::Delegate {
+                       public XEventDispatcher {
  public:
   X11WindowOzone(PlatformWindowDelegate* delegate,
-                 const PlatformWindowInitProperties& properties,
                  X11WindowManagerOzone* window_manager);
   ~X11WindowOzone() override;
 
   gfx::AcceleratedWidget widget() const { return widget_; }
-  bool IsVisible() const;
-  gfx::Rect GetOutterBounds() const;
-  ::Region GetShape() const;
 
   // Called by |window_manager_| once capture is set to another X11WindowOzone.
   void OnLostCapture();
 
   // Overridden from PlatformWindow:
-  void Show() override;
-  void Hide() override;
   void Close() override;
-  void SetBounds(const gfx::Rect& bounds) override;
-  gfx::Rect GetBounds() override;
-  void SetTitle(const base::string16& title) override;
-  void ToggleFullscreen() override;
-  void Maximize() override;
-  void Minimize() override;
-  void Restore() override;
-  void Activate() override;
-  void Deactivate() override;
-  void SetUseNativeFrame(bool use_native_frame) override;
-  PlatformWindowState GetPlatformWindowState() const override;
-  void MoveCursorTo(const gfx::Point& location) override;
-  void ConfineCursorToBounds(const gfx::Rect& bounds) override;
-  void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
-  gfx::Rect GetRestoredBoundsInPixels() const override;
   void PrepareForShutdown() override;
   void SetCapture() override;
   void ReleaseCapture() override;
@@ -76,14 +53,11 @@
   bool DispatchXEvent(XEvent* event) override;
 
  private:
-  // Overridden from ui::XWindow::Delegate
+  // XWindow overrides:
   void OnXWindowCreated() override;
-  void OnXWindowStateChanged() override;
-  void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override;
-  void OnXWindowSizeChanged(const gfx::Size& size) override;
-  void OnXWindowCloseRequested() override;
-  void OnXWindowLostCapture() override;
-  void OnXWindowIsActiveChanged(bool active) override;
+
+  // X11Window overrides:
+  void SetPlatformEventDispatcher() override;
 
   // PlatformEventDispatcher:
   bool CanDispatchEvent(const PlatformEvent& event) override;
@@ -98,14 +72,10 @@
   void SetWidget(XID xwindow);
   void RemoveFromWindowManager();
 
-  PlatformWindowDelegate* const delegate_;
   X11WindowManagerOzone* const window_manager_;
 
-  PlatformWindowState state_ = PlatformWindowState::kUnknown;
   gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
 
-  std::unique_ptr<ui::XWindow> x11_window_;
-
   bool is_shutting_down_ = false;
 
   // Tells if this dispatcher can process next translated event based on a
diff --git a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
index edbc7738..0d11004 100644
--- a/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
+++ b/ui/ozone/platform/x11/x11_window_ozone_unittest.cc
@@ -61,8 +61,9 @@
     EXPECT_CALL(*delegate, OnAcceleratedWidgetAvailable(_))
         .WillOnce(StoreWidget(widget));
     PlatformWindowInitProperties init_params(bounds);
-    auto window = std::make_unique<X11WindowOzone>(delegate, init_params,
-                                                   window_manager_.get());
+    auto window =
+        std::make_unique<X11WindowOzone>(delegate, window_manager_.get());
+    window->Initialize(std::move(init_params));
     return std::move(window);
   }
 
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index c345533..0e9d076 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -14,6 +14,7 @@
 #include "base/message_loop/message_pump_type.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "ui/gfx/buffer_types.h"
+#include "ui/platform_window/platform_window_delegate.h"
 
 namespace display {
 class NativeDisplayDelegate;
@@ -31,7 +32,6 @@
 class OverlayManagerOzone;
 class PlatformScreen;
 class PlatformWindow;
-class PlatformWindowDelegate;
 class SurfaceFactoryOzone;
 class SystemInputInjector;
 class PlatformClipboard;
diff --git a/ui/platform_window/BUILD.gn b/ui/platform_window/BUILD.gn
index 21f48b5..dea6ac2 100644
--- a/ui/platform_window/BUILD.gn
+++ b/ui/platform_window/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "platform_window.h",
     "platform_window_delegate.h",
+    "platform_window_delegate_base.cc",
+    "platform_window_delegate_base.h",
     "platform_window_init_properties.cc",
     "platform_window_init_properties.h",
   ]
@@ -30,6 +32,13 @@
       "//third_party/fuchsia-sdk/sdk:ui_views",
     ]
   }
+
+  if (is_linux) {
+    sources += [
+      "platform_window_delegate_linux.cc",
+      "platform_window_delegate_linux.h",
+    ]
+  }
 }
 
 group("platform_impls") {
diff --git a/ui/platform_window/common/BUILD.gn b/ui/platform_window/common/BUILD.gn
new file mode 100644
index 0000000..ce68072a
--- /dev/null
+++ b/ui/platform_window/common/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2019 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.
+
+import("//build/config/ui.gni")
+
+source_set("common") {
+  sources = [
+    "platform_window_defaults.cc",
+    "platform_window_defaults.h",
+  ]
+}
diff --git a/ui/base/platform_window_defaults.cc b/ui/platform_window/common/platform_window_defaults.cc
similarity index 87%
rename from ui/base/platform_window_defaults.cc
rename to ui/platform_window/common/platform_window_defaults.cc
index 6f87bf7e..59208f4 100644
--- a/ui/base/platform_window_defaults.cc
+++ b/ui/platform_window/common/platform_window_defaults.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/base/platform_window_defaults.h"
+#include "ui/platform_window/common/platform_window_defaults.h"
 
 namespace ui {
 namespace {
diff --git a/ui/base/platform_window_defaults.h b/ui/platform_window/common/platform_window_defaults.h
similarity index 76%
rename from ui/base/platform_window_defaults.h
rename to ui/platform_window/common/platform_window_defaults.h
index 7e4dedf..fdb4a1c2 100644
--- a/ui/base/platform_window_defaults.h
+++ b/ui/platform_window/common/platform_window_defaults.h
@@ -2,17 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_BASE_PLATFORM_WINDOW_DEFAULTS_H_
-#define UI_BASE_PLATFORM_WINDOW_DEFAULTS_H_
-
-#include "ui/base/ui_base_export.h"
+#ifndef UI_PLATFORM_WINDOW_COMMON_PLATFORM_WINDOW_DEFAULTS_H_
+#define UI_PLATFORM_WINDOW_COMMON_PLATFORM_WINDOW_DEFAULTS_H_
 
 namespace ui {
 
 // Returns true if PlatformWindow should use test configuration. Will return
 // false by default, unless test::EnableTestConfigForPlatformWindows() has been
 // called, then it will return true.
-UI_BASE_EXPORT bool UseTestConfigForPlatformWindows();
+bool UseTestConfigForPlatformWindows();
 
 namespace test {
 
@@ -24,9 +22,9 @@
 // various tests, otherwise the call to Show() blocks because it never receives
 // the MapNotify event. It is unclear why this is necessary, but might be
 // related to calls to XInitThreads().
-UI_BASE_EXPORT void EnableTestConfigForPlatformWindows();
+void EnableTestConfigForPlatformWindows();
 
 }  // namespace test
 }  // namespace ui
 
-#endif  // UI_BASE_PLATFORM_WINDOW_DEFAULTS_H_
+#endif  // UI_PLATFORM_WINDOW_COMMON_PLATFORM_WINDOW_DEFAULTS_H_
diff --git a/ui/platform_window/platform_window_delegate.h b/ui/platform_window/platform_window_delegate.h
index 0b6bdb8..fe4059ff 100644
--- a/ui/platform_window/platform_window_delegate.h
+++ b/ui/platform_window/platform_window_delegate.h
@@ -5,53 +5,23 @@
 #ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_
 #define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_H_
 
-#include "ui/gfx/native_widget_types.h"
+#include "build/build_config.h"
 
-namespace gfx {
-class Rect;
-}
+// By default, PlatformWindowDelegateBase is used. However, different platforms
+// should specify what delegate they would like to use if needed.
+#if defined(OS_LINUX)
+#include "ui/platform_window/platform_window_delegate_linux.h"
+#else
+#include "ui/platform_window/platform_window_delegate_base.h"
+#endif
 
 namespace ui {
 
-class Event;
-
-enum class PlatformWindowState {
-  kUnknown,
-  kMaximized,
-  kMinimized,
-  kNormal,
-  kFullScreen,
-};
-
-class PlatformWindowDelegate {
- public:
-  virtual ~PlatformWindowDelegate() {}
-
-  // Note that |new_bounds| is in physical screen coordinates.
-  virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0;
-
-  // Note that |damaged_region| is in the platform-window's coordinates, in
-  // physical pixels.
-  virtual void OnDamageRect(const gfx::Rect& damaged_region) = 0;
-
-  virtual void DispatchEvent(Event* event) = 0;
-
-  virtual void OnCloseRequest() = 0;
-  virtual void OnClosed() = 0;
-
-  virtual void OnWindowStateChanged(PlatformWindowState new_state) = 0;
-
-  virtual void OnLostCapture() = 0;
-
-  virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0;
-
-  // Notifies the delegate that the widget cannot be used anymore until
-  // a new widget is made available through OnAcceleratedWidgetAvailable().
-  // Must not be called when the PlatformWindow is being destroyed.
-  virtual void OnAcceleratedWidgetDestroyed() = 0;
-
-  virtual void OnActivationChanged(bool active) = 0;
-};
+#if defined(OS_LINUX)
+using PlatformWindowDelegate = PlatformWindowDelegateLinux;
+#else
+using PlatformWindowDelegate = PlatformWindowDelegateBase;
+#endif
 
 }  // namespace ui
 
diff --git a/ui/platform_window/platform_window_delegate_base.cc b/ui/platform_window/platform_window_delegate_base.cc
new file mode 100644
index 0000000..cb3a992
--- /dev/null
+++ b/ui/platform_window/platform_window_delegate_base.cc
@@ -0,0 +1,25 @@
+// Copyright 2019 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/platform_window/platform_window_delegate_base.h"
+
+#include "ui/gfx/geometry/size.h"
+
+namespace ui {
+
+PlatformWindowDelegateBase::PlatformWindowDelegateBase() = default;
+
+PlatformWindowDelegateBase::~PlatformWindowDelegateBase() = default;
+
+base::Optional<gfx::Size>
+PlatformWindowDelegateBase::GetMinimumSizeForWindow() {
+  return base::nullopt;
+}
+
+base::Optional<gfx::Size>
+PlatformWindowDelegateBase::GetMaximumSizeForWindow() {
+  return base::nullopt;
+}
+
+}  // namespace ui
diff --git a/ui/platform_window/platform_window_delegate_base.h b/ui/platform_window/platform_window_delegate_base.h
new file mode 100644
index 0000000..e76ae56
--- /dev/null
+++ b/ui/platform_window/platform_window_delegate_base.h
@@ -0,0 +1,68 @@
+// Copyright 2019 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_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_
+#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_
+
+#include "base/optional.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Rect;
+class Size;
+}  // namespace gfx
+
+namespace ui {
+
+class Event;
+
+enum class PlatformWindowState {
+  kUnknown,
+  kMaximized,
+  kMinimized,
+  kNormal,
+  kFullScreen,
+};
+
+// This is the bare minimum for PlatformWindowDeelegate, but some platforms may
+// require more, and should do so in a subclass. Please refer to
+// PlatformWindowDelegateLinux for an example.
+class PlatformWindowDelegateBase {
+ public:
+  PlatformWindowDelegateBase();
+  virtual ~PlatformWindowDelegateBase();
+
+  // Note that |new_bounds| is in physical screen coordinates.
+  virtual void OnBoundsChanged(const gfx::Rect& new_bounds) = 0;
+
+  // Note that |damaged_region| is in the platform-window's coordinates, in
+  // physical pixels.
+  virtual void OnDamageRect(const gfx::Rect& damaged_region) = 0;
+
+  virtual void DispatchEvent(Event* event) = 0;
+
+  virtual void OnCloseRequest() = 0;
+  virtual void OnClosed() = 0;
+
+  virtual void OnWindowStateChanged(PlatformWindowState new_state) = 0;
+
+  virtual void OnLostCapture() = 0;
+
+  virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0;
+
+  // Notifies the delegate that the widget cannot be used anymore until
+  // a new widget is made available through OnAcceleratedWidgetAvailable().
+  // Must not be called when the PlatformWindow is being destroyed.
+  virtual void OnAcceleratedWidgetDestroyed() = 0;
+
+  virtual void OnActivationChanged(bool active) = 0;
+
+  // Requests size constraints for the PlatformWindow.
+  virtual base::Optional<gfx::Size> GetMinimumSizeForWindow();
+  virtual base::Optional<gfx::Size> GetMaximumSizeForWindow();
+};
+
+}  // namespace ui
+
+#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_BASE_H_
diff --git a/ui/platform_window/platform_window_delegate_linux.cc b/ui/platform_window/platform_window_delegate_linux.cc
new file mode 100644
index 0000000..c66e2ca
--- /dev/null
+++ b/ui/platform_window/platform_window_delegate_linux.cc
@@ -0,0 +1,31 @@
+// Copyright 2019 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/platform_window/platform_window_delegate_linux.h"
+
+#include "base/logging.h"
+
+namespace ui {
+
+PlatformWindowDelegateLinux::PlatformWindowDelegateLinux() = default;
+
+PlatformWindowDelegateLinux::~PlatformWindowDelegateLinux() = default;
+
+void PlatformWindowDelegateLinux::OnXWindowMapped() {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void PlatformWindowDelegateLinux::OnXWindowUnmapped() {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void PlatformWindowDelegateLinux::OnLostMouseGrab() {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void PlatformWindowDelegateLinux::OnWorkspaceChanged() {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+}  // namespace ui
diff --git a/ui/platform_window/platform_window_delegate_linux.h b/ui/platform_window/platform_window_delegate_linux.h
new file mode 100644
index 0000000..6290c69
--- /dev/null
+++ b/ui/platform_window/platform_window_delegate_linux.h
@@ -0,0 +1,39 @@
+// Copyright 2019 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_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
+#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
+
+#include "ui/platform_window/platform_window_delegate_base.h"
+
+namespace ui {
+
+// This is an optional linux delegate interface, which should be implemented by
+// linux-based platforms. It contains both Wayland and X11 specific and common
+// interfaces.
+class PlatformWindowDelegateLinux : public PlatformWindowDelegateBase {
+ public:
+  PlatformWindowDelegateLinux();
+  ~PlatformWindowDelegateLinux() override;
+
+  // Notifies the delegate that the window got mapped in the X server. Wayland
+  // does not support this interface.
+  virtual void OnXWindowMapped();
+  virtual void OnXWindowUnmapped();
+
+  // Notifies if the PlatformWindow looses a mouse grab. This can be useful for
+  // Wayland or X11. Both of them provide pointer enter and leave notifications,
+  // which non-ozone X11 (just an example) use to be using to notify about lost
+  // pointer grab along with explicit grabs. Wayland also has this technique.
+  // However, explicit grab is available only for popup (menu) windows.
+  virtual void OnLostMouseGrab();
+
+  // Notifies the delegate if the PlatformWindow has changed the workspace it is
+  // located in.
+  virtual void OnWorkspaceChanged();
+};
+
+}  // namespace ui
+
+#endif  // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_DELEGATE_LINUX_H_
diff --git a/ui/platform_window/platform_window_init_properties.h b/ui/platform_window/platform_window_init_properties.h
index 46af9ec..38e5382 100644
--- a/ui/platform_window/platform_window_init_properties.h
+++ b/ui/platform_window/platform_window_init_properties.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/optional.h"
 #include "build/build_config.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
@@ -16,6 +17,10 @@
 #include <lib/ui/scenic/cpp/view_ref_pair.h>
 #endif
 
+namespace gfx {
+class ImageSkia;
+}
+
 namespace ui {
 
 enum class PlatformWindowType {
@@ -23,6 +28,8 @@
   kPopup,
   kMenu,
   kTooltip,
+  kDrag,
+  kBubble,
 };
 
 enum class PlatformWindowOpacity {
@@ -66,7 +73,13 @@
   bool remove_standard_frame = false;
   std::string workspace;
 
-  // Only used by X11. Specifies the res_name and res_class fields,
+#if defined(USE_X11)
+  // Only used by X11:
+  bool prefer_dark_theme = false;
+  gfx::ImageSkia* icon = nullptr;
+  base::Optional<int> background_color;
+#endif
+  // Specifies the res_name and res_class fields,
   // respectively, of the WM_CLASS window property. Controls window grouping
   // and desktop file matching in Linux window managers.
   std::string wm_role_name;
diff --git a/ui/platform_window/stub/stub_window.h b/ui/platform_window/stub/stub_window.h
index 0593f4db..0574b19 100644
--- a/ui/platform_window/stub/stub_window.h
+++ b/ui/platform_window/stub/stub_window.h
@@ -9,12 +9,11 @@
 #include "base/macros.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/stub/stub_window_export.h"
 
 namespace ui {
 
-class PlatformWindowDelegate;
-
 // StubWindow is useful for tests, as well as implementations that only care
 // about bounds.
 class STUB_WINDOW_EXPORT StubWindow : public PlatformWindow {
diff --git a/ui/platform_window/win/win_window.cc b/ui/platform_window/win/win_window.cc
index 8cd1ce8..548f56a1 100644
--- a/ui/platform_window/win/win_window.cc
+++ b/ui/platform_window/win/win_window.cc
@@ -11,7 +11,6 @@
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
 #include "ui/gfx/win/msg_util.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
 #include <windows.h>
 
diff --git a/ui/platform_window/win/win_window.h b/ui/platform_window/win/win_window.h
index 1e4bd938..f74cddb0 100644
--- a/ui/platform_window/win/win_window.h
+++ b/ui/platform_window/win/win_window.h
@@ -10,14 +10,13 @@
 #include "base/memory/weak_ptr.h"
 #include "ui/gfx/win/window_impl.h"
 #include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/win/win_window_export.h"
 
 #include <windows.h>
 
 namespace ui {
 
-class PlatformWindowDelegate;
-
 class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
                                     public gfx::WindowImpl {
  public:
diff --git a/ui/platform_window/x11/BUILD.gn b/ui/platform_window/x11/BUILD.gn
index f0d40e73..64259a6 100644
--- a/ui/platform_window/x11/BUILD.gn
+++ b/ui/platform_window/x11/BUILD.gn
@@ -30,15 +30,8 @@
   defines = [ "X11_WINDOW_IMPLEMENTATION" ]
 
   sources = [
-    "x11_window_base.cc",
-    "x11_window_base.h",
+    "x11_window.cc",
+    "x11_window.h",
     "x11_window_export.h",
   ]
-
-  if (use_x11) {
-    sources += [
-      "x11_window.cc",
-      "x11_window.h",
-    ]
-  }
 }
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc
index c466ef0e..b0a7365 100644
--- a/ui/platform_window/x11/x11_window.cc
+++ b/ui/platform_window/x11/x11_window.cc
@@ -4,146 +4,326 @@
 
 #include "ui/platform_window/x11/x11_window.h"
 
+#include "base/trace_event/trace_event.h"
 #include "ui/events/devices/x11/touch_factory_x11.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/events/platform/x11/x11_event_source.h"
 #include "ui/gfx/x/x11.h"
-#include "ui/platform_window/platform_window_delegate.h"
+#include "ui/platform_window/platform_window_delegate_linux.h"
 
 namespace ui {
 
-X11Window::X11Window(PlatformWindowDelegate* delegate, const gfx::Rect& bounds)
-    : X11WindowBase(delegate, bounds) {
-  DCHECK(PlatformEventSource::GetInstance());
-  PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
+namespace {
+
+ui::XWindow::Configuration ConvertInitPropertiesToXWindowConfig(
+    const PlatformWindowInitProperties& properties) {
+  using WindowType = ui::XWindow::WindowType;
+  using WindowOpacity = ui::XWindow::WindowOpacity;
+  ui::XWindow::Configuration config;
+
+  switch (properties.type) {
+    case PlatformWindowType::kWindow:
+      config.type = WindowType::kWindow;
+      break;
+    case PlatformWindowType::kMenu:
+      config.type = WindowType::kMenu;
+      break;
+    case PlatformWindowType::kTooltip:
+      config.type = WindowType::kTooltip;
+      break;
+    case PlatformWindowType::kPopup:
+      config.type = WindowType::kPopup;
+      break;
+    case PlatformWindowType::kDrag:
+      config.type = WindowType::kDrag;
+      break;
+    case PlatformWindowType::kBubble:
+      config.type = WindowType::kBubble;
+      break;
+  }
+
+  switch (properties.opacity) {
+    case PlatformWindowOpacity::kInferOpacity:
+      config.opacity = WindowOpacity::kInferOpacity;
+      break;
+    case PlatformWindowOpacity::kOpaqueWindow:
+      config.opacity = WindowOpacity::kOpaqueWindow;
+      break;
+    case PlatformWindowOpacity::kTranslucentWindow:
+      config.opacity = WindowOpacity::kTranslucentWindow;
+      break;
+  }
+
+  config.bounds = properties.bounds;
+  config.force_show_in_taskbar = properties.force_show_in_taskbar;
+  config.keep_on_top = properties.keep_on_top;
+  config.visible_on_all_workspaces = properties.visible_on_all_workspaces;
+  config.remove_standard_frame = properties.remove_standard_frame;
+  config.workspace = properties.workspace;
+  config.wm_class_name = properties.wm_class_name;
+  config.wm_class_class = properties.wm_class_class;
+  config.wm_role_name = properties.wm_role_name;
+  config.activatable = properties.activatable;
+  return config;
 }
 
+}  // namespace
+
+X11Window::X11Window(PlatformWindowDelegateLinux* platform_window_delegate,
+                     XEventDelegate* x_event_delegate)
+    : platform_window_delegate_(platform_window_delegate),
+      x_event_delegate_(x_event_delegate) {}
+
 X11Window::~X11Window() {
-  X11Window::PrepareForShutdown();
+  PrepareForShutdown();
+  Close();
+}
+
+void X11Window::Initialize(PlatformWindowInitProperties properties) {
+  XWindow::Configuration config =
+      ConvertInitPropertiesToXWindowConfig(properties);
+  Init(config);
+}
+
+void X11Window::Show() {
+  // TODO(msisov): pass inactivity to PlatformWindow::Show.
+  XWindow::Map(false /* inactive */);
+}
+
+void X11Window::Hide() {
+  XWindow::Hide();
+}
+
+void X11Window::Close() {
+  if (is_shutting_down_)
+    return;
+
+  is_shutting_down_ = true;
+  XWindow::Close();
+  platform_window_delegate_->OnClosed();
 }
 
 void X11Window::PrepareForShutdown() {
   PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
 }
 
-void X11Window::SetUseNativeFrame(bool use_native_frame) {
+void X11Window::SetBounds(const gfx::Rect& bounds) {
+  // Assume that the resize will go through as requested, which should be the
+  // case if we're running without a window manager.  If there's a window
+  // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
+  // (possibly synthetic) ConfigureNotify about the actual size and correct
+  // |bounds_| later.
+  XWindow::SetBounds(bounds);
+
+  // Even if the pixel bounds didn't change this call to the delegate should
+  // still happen. The device scale factor may have changed which effectively
+  // changes the bounds.
+  platform_window_delegate_->OnBoundsChanged(bounds);
+}
+
+gfx::Rect X11Window::GetBounds() {
+  return XWindow::bounds();
+}
+
+void X11Window::SetTitle(const base::string16& title) {
+  XWindow::SetTitle(title);
+}
+
+void X11Window::SetCapture() {
+  XWindow::GrabPointer();
+}
+
+void X11Window::ReleaseCapture() {
+  XWindow::ReleasePointerGrab();
+}
+
+bool X11Window::HasCapture() const {
   NOTIMPLEMENTED_LOG_ONCE();
+  return false;
+}
+
+void X11Window::ToggleFullscreen() {
+  bool is_fullscreen = IsFullscreen();
+  SetFullscreen(!is_fullscreen);
+}
+
+void X11Window::Maximize() {
+  if (IsFullscreen())
+    SetFullscreen(false);
+  XWindow::Maximize();
+}
+
+void X11Window::Minimize() {
+  XWindow::Minimize();
+}
+
+void X11Window::Restore() {
+  if (IsFullscreen())
+    ToggleFullscreen();
+  if (IsMaximized())
+    Unmaximize();
+}
+
+PlatformWindowState X11Window::GetPlatformWindowState() const {
+  return state_;
+}
+
+void X11Window::Activate() {
+  XWindow::Activate();
+}
+
+void X11Window::Deactivate() {
+  XWindow::Deactivate();
+}
+
+void X11Window::SetUseNativeFrame(bool use_native_frame) {
+  XWindow::SetUseNativeFrame(use_native_frame);
 }
 
 void X11Window::SetCursor(PlatformCursor cursor) {
-  XDefineCursor(xdisplay(), xwindow(), cursor);
+  // X11PlatformWindowOzone has different type of PlatformCursor. Thus, use this
+  // only for X11 and Ozone will manage this by itself.
+#if defined(USE_X11)
+  XWindow::SetCursor(cursor);
+#endif
 }
 
-void X11Window::ProcessXInput2Event(XEvent* xev) {
-  if (!TouchFactory::GetInstance()->ShouldProcessXI2Event(xev))
-    return;
-  EventType event_type = EventTypeFromNative(xev);
-  switch (event_type) {
-    case ET_KEY_PRESSED:
-    case ET_KEY_RELEASED: {
-      KeyEvent key_event(xev);
-      delegate()->DispatchEvent(&key_event);
-      break;
-    }
-    case ET_MOUSE_PRESSED:
-    case ET_MOUSE_MOVED:
-    case ET_MOUSE_DRAGGED:
-    case ET_MOUSE_RELEASED: {
-      MouseEvent mouse_event(xev);
-      delegate()->DispatchEvent(&mouse_event);
-      break;
-    }
-    case ET_MOUSEWHEEL: {
-      MouseWheelEvent wheel_event(xev);
-      delegate()->DispatchEvent(&wheel_event);
-      break;
-    }
-    case ET_SCROLL_FLING_START:
-    case ET_SCROLL_FLING_CANCEL:
-    case ET_SCROLL: {
-      ScrollEvent scroll_event(xev);
-      delegate()->DispatchEvent(&scroll_event);
-      break;
-    }
-    case ET_TOUCH_MOVED:
-    case ET_TOUCH_PRESSED:
-    case ET_TOUCH_CANCELLED:
-    case ET_TOUCH_RELEASED: {
-      TouchEvent touch_event(xev);
-      delegate()->DispatchEvent(&touch_event);
-      break;
-    }
-    default:
-      break;
-  }
+void X11Window::MoveCursorTo(const gfx::Point& location) {
+  XWindow::MoveCursorTo(location);
+}
+
+void X11Window::ConfineCursorToBounds(const gfx::Rect& bounds) {
+  XWindow::ConfineCursorTo(bounds);
+}
+
+void X11Window::SetRestoredBoundsInPixels(const gfx::Rect& bounds) {
+  // TODO(crbug.com/848131): Restore bounds on restart
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+gfx::Rect X11Window::GetRestoredBoundsInPixels() const {
+  // TODO(crbug.com/848131): Restore bounds on restart
+  NOTIMPLEMENTED_LOG_ONCE();
+  return gfx::Rect();
+}
+
+void X11Window::SetPlatformEventDispatcher() {
+  DCHECK(PlatformEventSource::GetInstance());
+  PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
 }
 
 bool X11Window::CanDispatchEvent(const PlatformEvent& xev) {
-  return IsEventForXWindow(*xev);
+#if defined(USE_X11)
+  return XWindow::IsTargetedBy(*xev);
+#else
+  NOTREACHED() << "Ozone must use own dispatcher as it has different type of "
+                  "PlatformEvent";
+  return false;
+#endif
 }
 
 uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
-  XEvent* xev = event;
-  switch (xev->type) {
-    case EnterNotify: {
-      MouseEvent mouse_event(xev);
-      CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type());
-      delegate()->DispatchEvent(&mouse_event);
-      break;
-    }
-    case LeaveNotify: {
-      MouseEvent mouse_event(xev);
-      delegate()->DispatchEvent(&mouse_event);
-      break;
-    }
+#if defined(USE_X11)
+  TRACE_EVENT1("views", "X11PlatformWindow::Dispatch", "event->type",
+               event->type);
 
-    case KeyPress:
-    case KeyRelease: {
-      KeyEvent key_event(xev);
-      delegate()->DispatchEvent(&key_event);
-      break;
-    }
-
-    case ButtonPress:
-    case ButtonRelease: {
-      switch (EventTypeFromNative(xev)) {
-        case ET_MOUSEWHEEL: {
-          MouseWheelEvent mouseev(xev);
-          delegate()->DispatchEvent(&mouseev);
-          break;
-        }
-        case ET_MOUSE_PRESSED:
-        case ET_MOUSE_RELEASED: {
-          MouseEvent mouseev(xev);
-          delegate()->DispatchEvent(&mouseev);
-          break;
-        }
-        case ET_UNKNOWN:
-          // No event is created for X11-release events for mouse-wheel
-          // buttons.
-          break;
-        default:
-          NOTREACHED();
-      }
-      break;
-    }
-
-    case Expose:
-    case x11::FocusOut:
-    case ConfigureNotify:
-    case ClientMessage: {
-      ProcessXWindowEvent(xev);
-      break;
-    }
-
-    case GenericEvent: {
-      ProcessXInput2Event(xev);
-      break;
-    }
-  }
+  ProcessEvent(event);
   return POST_DISPATCH_STOP_PROPAGATION;
+#else
+  NOTREACHED() << "Ozone must use own dispatcher as it has different type of "
+                  "PlatformEvent";
+  return false;
+#endif
+}
+
+void X11Window::OnXWindowCreated() {
+  // X11WindowOzone overrides this method and manages events by itself.
+  SetPlatformEventDispatcher();
+  platform_window_delegate_->OnAcceleratedWidgetAvailable(window());
+}
+
+void X11Window::OnXWindowStateChanged() {
+  // Propagate the window state information to the client. Note that the order
+  // of checks is important here, because window can have several properties
+  // at the same time.
+  PlatformWindowState old_state = state_;
+  if (IsMinimized()) {
+    state_ = PlatformWindowState::kMinimized;
+  } else if (IsFullscreen()) {
+    state_ = PlatformWindowState::kFullScreen;
+  } else if (IsMaximized()) {
+    state_ = PlatformWindowState::kMaximized;
+  } else {
+    state_ = PlatformWindowState::kNormal;
+  }
+
+  if (old_state != state_)
+    platform_window_delegate_->OnWindowStateChanged(state_);
+}
+
+void X11Window::OnXWindowDamageEvent(const gfx::Rect& damage_rect) {
+  platform_window_delegate_->OnDamageRect(damage_rect);
+}
+
+void X11Window::OnXWindowBoundsChanged(const gfx::Rect& bounds) {
+  platform_window_delegate_->OnBoundsChanged(bounds);
+}
+
+void X11Window::OnXWindowCloseRequested() {
+  platform_window_delegate_->OnCloseRequest();
+}
+
+void X11Window::OnXWindowIsActiveChanged(bool active) {
+  platform_window_delegate_->OnActivationChanged(active);
+}
+
+void X11Window::OnXWindowMapped() {
+  platform_window_delegate_->OnXWindowMapped();
+}
+
+void X11Window::OnXWindowUnmapped() {
+  platform_window_delegate_->OnXWindowUnmapped();
+}
+
+void X11Window::OnXWindowWorkspaceChanged() {
+  platform_window_delegate_->OnWorkspaceChanged();
+}
+
+void X11Window::OnXWindowLostPointerGrab() {
+  platform_window_delegate_->OnLostMouseGrab();
+}
+
+void X11Window::OnXWindowLostCapture() {
+  platform_window_delegate_->OnLostCapture();
+}
+
+void X11Window::OnXWindowEvent(ui::Event* event) {
+  platform_window_delegate_->DispatchEvent(event);
+}
+
+void X11Window::OnXWindowSelectionEvent(XEvent* xev) {
+  if (x_event_delegate_)
+    x_event_delegate_->OnXWindowSelectionEvent(xev);
+}
+
+void X11Window::OnXWindowDragDropEvent(XEvent* xev) {
+  if (x_event_delegate_)
+    x_event_delegate_->OnXWindowDragDropEvent(xev);
+}
+
+void X11Window::OnXWindowRawKeyEvent(XEvent* xev) {
+  if (x_event_delegate_)
+    x_event_delegate_->OnXWindowRawKeyEvent(xev);
+}
+
+base::Optional<gfx::Size> X11Window::GetMinimumSizeForXWindow() {
+  return platform_window_delegate_->GetMinimumSizeForWindow();
+}
+
+base::Optional<gfx::Size> X11Window::GetMaximumSizeForXWindow() {
+  return platform_window_delegate_->GetMaximumSizeForWindow();
 }
 
 }  // namespace ui
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h
index 2b91e5c..62ae8fb 100644
--- a/ui/platform_window/x11/x11_window.h
+++ b/ui/platform_window/x11/x11_window.h
@@ -6,23 +6,77 @@
 #define UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_
 
 #include "base/macros.h"
+#include "ui/base/x/x11_window.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/platform_window/x11/x11_window_base.h"
+#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/platform_window/x11/x11_window_export.h"
 
 namespace ui {
 
+class PlatformWindowDelegateLinux;
+
+// Delegate interface used to communicate the X11PlatformWindow API client about
+// XEvents of interest.
+class X11_WINDOW_EXPORT XEventDelegate {
+ public:
+  virtual ~XEventDelegate() {}
+
+  // TODO(crbug.com/990756): We need to implement/reuse ozone interface for
+  // these.
+  virtual void OnXWindowSelectionEvent(XEvent* xev) = 0;
+  virtual void OnXWindowDragDropEvent(XEvent* xev) = 0;
+
+  // TODO(crbug.com/981606): DesktopWindowTreeHostX11 forward raw |XEvent|s to
+  // ATK components that currently live in views layer.  Remove once ATK code
+  // is reworked to be reusable.
+  virtual void OnXWindowRawKeyEvent(XEvent* xev) = 0;
+};
+
 // PlatformWindow implementation for X11. PlatformEvents are XEvents.
-class X11_WINDOW_EXPORT X11Window : public X11WindowBase,
+class X11_WINDOW_EXPORT X11Window : public PlatformWindow,
+                                    public XWindow,
                                     public PlatformEventDispatcher {
  public:
-  X11Window(PlatformWindowDelegate* delegate, const gfx::Rect& bounds);
+  X11Window(PlatformWindowDelegateLinux* platform_window_delegate,
+            XEventDelegate* x_event_delegate);
   ~X11Window() override;
 
+  void Initialize(PlatformWindowInitProperties properties);
+
   // PlatformWindow:
+  void Show() override;
+  void Hide() override;
+  void Close() override;
   void PrepareForShutdown() override;
+  void SetBounds(const gfx::Rect& bounds) override;
+  gfx::Rect GetBounds() override;
+  void SetTitle(const base::string16& title) override;
+  void SetCapture() override;
+  void ReleaseCapture() override;
+  bool HasCapture() const override;
+  void ToggleFullscreen() override;
+  void Maximize() override;
+  void Minimize() override;
+  void Restore() override;
+  PlatformWindowState GetPlatformWindowState() const override;
+  void Activate() override;
+  void Deactivate() override;
   void SetUseNativeFrame(bool use_native_frame) override;
   void SetCursor(PlatformCursor cursor) override;
+  void MoveCursorTo(const gfx::Point& location) override;
+  void ConfineCursorToBounds(const gfx::Rect& bounds) override;
+  void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
+  gfx::Rect GetRestoredBoundsInPixels() const override;
+
+ protected:
+  PlatformWindowDelegateLinux* platform_window_delegate() const {
+    return platform_window_delegate_;
+  }
+
+  // XWindow:
+  void OnXWindowCreated() override;
+  void OnXWindowLostCapture() override;
 
  private:
   void ProcessXInput2Event(XEvent* xev);
@@ -31,6 +85,36 @@
   bool CanDispatchEvent(const PlatformEvent& event) override;
   uint32_t DispatchEvent(const PlatformEvent& event) override;
 
+  // XWindow:
+  void OnXWindowStateChanged() override;
+  void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override;
+  void OnXWindowBoundsChanged(const gfx::Rect& size) override;
+  void OnXWindowCloseRequested() override;
+  void OnXWindowIsActiveChanged(bool active) override;
+  void OnXWindowMapped() override;
+  void OnXWindowUnmapped() override;
+  void OnXWindowWorkspaceChanged() override;
+  void OnXWindowLostPointerGrab() override;
+  void OnXWindowEvent(ui::Event* event) override;
+  void OnXWindowSelectionEvent(XEvent* xev) override;
+  void OnXWindowDragDropEvent(XEvent* xev) override;
+  void OnXWindowRawKeyEvent(XEvent* xev) override;
+  base::Optional<gfx::Size> GetMinimumSizeForXWindow() override;
+  base::Optional<gfx::Size> GetMaximumSizeForXWindow() override;
+
+  // X11WindowOzone sets own event dispatcher now.
+  virtual void SetPlatformEventDispatcher();
+
+  // Stores current state of this window.
+  PlatformWindowState state_ = PlatformWindowState::kUnknown;
+
+  PlatformWindowDelegateLinux* const platform_window_delegate_;
+
+  XEventDelegate* const x_event_delegate_;
+
+  // Tells if the window got a ::Close call.
+  bool is_shutting_down_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(X11Window);
 };
 
diff --git a/ui/platform_window/x11/x11_window_base.cc b/ui/platform_window/x11/x11_window_base.cc
deleted file mode 100644
index 221ad511..0000000
--- a/ui/platform_window/x11/x11_window_base.cc
+++ /dev/null
@@ -1,437 +0,0 @@
-// Copyright 2016 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/platform_window/x11/x11_window_base.h"
-
-#include <string>
-
-#include "base/strings/utf_string_conversions.h"
-#include "ui/base/platform_window_defaults.h"
-#include "ui/base/x/x11_util.h"
-#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/events/platform/x11/x11_event_source.h"
-#include "ui/events/x/x11_window_event_manager.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "ui/platform_window/platform_window_delegate.h"
-
-namespace ui {
-
-namespace {
-
-XID FindXEventTarget(const XEvent& xev) {
-  XID target = xev.xany.window;
-  if (xev.type == GenericEvent)
-    target = static_cast<XIDeviceEvent*>(xev.xcookie.data)->event;
-  return target;
-}
-
-}  // namespace
-
-X11WindowBase::X11WindowBase(PlatformWindowDelegate* delegate,
-                             const gfx::Rect& bounds)
-    : delegate_(delegate),
-      xdisplay_(gfx::GetXDisplay()),
-      xroot_window_(DefaultRootWindow(xdisplay_)),
-      bounds_(bounds),
-      state_(PlatformWindowState::kUnknown) {
-  DCHECK(delegate_);
-  Create();
-  pointer_barriers_.fill(x11::None);
-}
-
-X11WindowBase::~X11WindowBase() {
-  UnConfineCursor();
-  Destroy();
-}
-
-void X11WindowBase::Destroy() {
-  if (xwindow_ == x11::None)
-    return;
-
-  // Stop processing events.
-  XID xwindow = xwindow_;
-  XDisplay* xdisplay = xdisplay_;
-  xwindow_ = x11::None;
-  delegate_->OnClosed();
-  // |this| might be deleted because of the above call.
-
-  XDestroyWindow(xdisplay, xwindow);
-}
-
-void X11WindowBase::Create() {
-  DCHECK(!bounds_.size().IsEmpty());
-
-  XSetWindowAttributes swa;
-  memset(&swa, 0, sizeof(swa));
-  swa.background_pixmap = x11::None;
-  swa.bit_gravity = NorthWestGravity;
-  swa.override_redirect = UseTestConfigForPlatformWindows();
-  xwindow_ =
-      XCreateWindow(xdisplay_, xroot_window_, bounds_.x(), bounds_.y(),
-                    bounds_.width(), bounds_.height(),
-                    0,               // border width
-                    CopyFromParent,  // depth
-                    InputOutput,
-                    CopyFromParent,  // visual
-                    CWBackPixmap | CWBitGravity | CWOverrideRedirect, &swa);
-
-  // Setup XInput event mask.
-  long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
-                    KeyPressMask | KeyReleaseMask | EnterWindowMask |
-                    LeaveWindowMask | ExposureMask | VisibilityChangeMask |
-                    StructureNotifyMask | PropertyChangeMask |
-                    PointerMotionMask;
-  xwindow_events_ =
-      std::make_unique<ui::XScopedEventSelector>(xwindow_, event_mask);
-
-  // Setup XInput2 event mask.
-  unsigned char mask[XIMaskLen(XI_LASTEVENT)];
-  memset(mask, 0, sizeof(mask));
-
-  XISetMask(mask, XI_TouchBegin);
-  XISetMask(mask, XI_TouchUpdate);
-  XISetMask(mask, XI_TouchEnd);
-  XISetMask(mask, XI_ButtonPress);
-  XISetMask(mask, XI_ButtonRelease);
-  XISetMask(mask, XI_Motion);
-  XISetMask(mask, XI_KeyPress);
-  XISetMask(mask, XI_KeyRelease);
-  XISetMask(mask, XI_HierarchyChanged);
-
-  XIEventMask evmask;
-  evmask.deviceid = XIAllDevices;
-  evmask.mask_len = sizeof(mask);
-  evmask.mask = mask;
-  XISelectEvents(xdisplay_, xwindow_, &evmask, 1);
-  XFlush(xdisplay_);
-
-  ::Atom protocols[2];
-  protocols[0] = gfx::GetAtom("WM_DELETE_WINDOW");
-  protocols[1] = gfx::GetAtom("_NET_WM_PING");
-  XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
-
-  // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
-  // the desktop environment.
-  XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
-
-  // Likewise, the X server needs to know this window's pid so it knows which
-  // program to kill if the window hangs.
-  // XChangeProperty() expects "pid" to be long.
-  static_assert(sizeof(long) >= sizeof(pid_t),
-                "pid_t should not be larger than long");
-  long pid = getpid();
-  XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_PID"), XA_CARDINAL,
-                  32, PropModeReplace, reinterpret_cast<unsigned char*>(&pid),
-                  1);
-  // Before we map the window, set size hints. Otherwise, some window managers
-  // will ignore toplevel XMoveWindow commands.
-  XSizeHints size_hints;
-  size_hints.flags = PPosition | PWinGravity;
-  size_hints.x = bounds_.x();
-  size_hints.y = bounds_.y();
-  // Set StaticGravity so that the window position is not affected by the
-  // frame width when running with window manager.
-  size_hints.win_gravity = StaticGravity;
-  XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
-
-  delegate_->OnAcceleratedWidgetAvailable(xwindow_);
-}
-
-void X11WindowBase::Show() {
-  if (window_mapped_)
-    return;
-
-  XMapWindow(xdisplay_, xwindow_);
-  // TODO(thomasanderson): Find out why this flush is necessary.
-  XFlush(xdisplay_);
-  window_mapped_ = true;
-}
-
-void X11WindowBase::Hide() {
-  if (!window_mapped_)
-    return;
-
-  XWithdrawWindow(xdisplay_, xwindow_, 0);
-  window_mapped_ = false;
-}
-
-void X11WindowBase::Close() {
-  Destroy();
-}
-
-void X11WindowBase::SetBounds(const gfx::Rect& bounds) {
-  DCHECK(!bounds.size().IsEmpty());
-
-  if (xwindow_ != x11::None) {
-    XWindowChanges changes = {0};
-    unsigned value_mask = 0;
-
-    if (bounds_.size() != bounds.size()) {
-      changes.width = bounds.width();
-      changes.height = bounds.height();
-      value_mask |= CWHeight | CWWidth;
-    }
-
-    if (bounds_.origin() != bounds.origin()) {
-      changes.x = bounds.x();
-      changes.y = bounds.y();
-      value_mask |= CWX | CWY;
-    }
-
-    if (value_mask)
-      XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
-  }
-
-  // Assume that the resize will go through as requested, which should be the
-  // case if we're running without a window manager.  If there's a window
-  // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
-  // (possibly synthetic) ConfigureNotify about the actual size and correct
-  // |bounds_| later.
-  bounds_ = bounds;
-
-  // Even if the pixel bounds didn't change this call to the delegate should
-  // still happen. The device scale factor may have changed which effectively
-  // changes the bounds.
-  delegate_->OnBoundsChanged(bounds_);
-}
-
-gfx::Rect X11WindowBase::GetBounds() {
-  return bounds_;
-}
-
-void X11WindowBase::SetTitle(const base::string16& title) {
-  if (window_title_ == title)
-    return;
-  window_title_ = title;
-  std::string utf8str = base::UTF16ToUTF8(title);
-  XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_NAME"),
-                  gfx::GetAtom("UTF8_STRING"), 8, PropModeReplace,
-                  reinterpret_cast<const unsigned char*>(utf8str.c_str()),
-                  utf8str.size());
-  XTextProperty xtp;
-  char* c_utf8_str = const_cast<char*>(utf8str.c_str());
-  if (Xutf8TextListToTextProperty(xdisplay_, &c_utf8_str, 1, XUTF8StringStyle,
-                                  &xtp) == x11::Success) {
-    XSetWMName(xdisplay_, xwindow_, &xtp);
-    XFree(xtp.value);
-  }
-}
-
-void X11WindowBase::SetCapture() {}
-
-void X11WindowBase::ReleaseCapture() {}
-
-bool X11WindowBase::HasCapture() const {
-  return false;
-}
-
-void X11WindowBase::ToggleFullscreen() {
-  ui::SetWMSpecState(xwindow_, !IsFullscreen(),
-                     gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"), x11::None);
-}
-
-void X11WindowBase::Maximize() {
-  if (IsFullscreen())
-    ToggleFullscreen();
-
-  ui::SetWMSpecState(xwindow_, true,
-                     gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
-                     gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
-}
-
-void X11WindowBase::Minimize() {
-  XIconifyWindow(xdisplay_, xwindow_, 0);
-}
-
-void X11WindowBase::Restore() {
-  if (IsFullscreen())
-    ToggleFullscreen();
-
-  if (IsMaximized()) {
-    ui::SetWMSpecState(xwindow_, false,
-                       gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
-                       gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
-  }
-}
-
-PlatformWindowState X11WindowBase::GetPlatformWindowState() const {
-  return state_;
-}
-
-void X11WindowBase::Activate() {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void X11WindowBase::Deactivate() {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void X11WindowBase::MoveCursorTo(const gfx::Point& location) {
-  XWarpPointer(xdisplay_, x11::None, xroot_window_, 0, 0, 0, 0,
-               bounds_.x() + location.x(), bounds_.y() + location.y());
-}
-
-void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) {
-  UnConfineCursor();
-
-  if (bounds.IsEmpty())
-    return;
-
-  gfx::Rect barrier = bounds + bounds_.OffsetFromOrigin();
-
-  // Top horizontal barrier.
-  pointer_barriers_[0] = XFixesCreatePointerBarrier(
-      xdisplay_, xroot_window_, barrier.x(), barrier.y(), barrier.right(),
-      barrier.y(), BarrierPositiveY, 0, XIAllDevices);
-  // Bottom horizontal barrier.
-  pointer_barriers_[1] = XFixesCreatePointerBarrier(
-      xdisplay_, xroot_window_, barrier.x(), barrier.bottom(), barrier.right(),
-      barrier.bottom(), BarrierNegativeY, 0, XIAllDevices);
-  // Left vertical barrier.
-  pointer_barriers_[2] = XFixesCreatePointerBarrier(
-      xdisplay_, xroot_window_, barrier.x(), barrier.y(), barrier.x(),
-      barrier.bottom(), BarrierPositiveX, 0, XIAllDevices);
-  // Right vertical barrier.
-  pointer_barriers_[3] = XFixesCreatePointerBarrier(
-      xdisplay_, xroot_window_, barrier.right(), barrier.y(), barrier.right(),
-      barrier.bottom(), BarrierNegativeX, 0, XIAllDevices);
-
-  has_pointer_barriers_ = true;
-}
-
-void X11WindowBase::SetRestoredBoundsInPixels(const gfx::Rect& bounds) {
-  // TODO: https://crbug.com/848131
-  NOTIMPLEMENTED();
-}
-
-gfx::Rect X11WindowBase::GetRestoredBoundsInPixels() const {
-  // TODO: https://crbug.com/848131
-  NOTIMPLEMENTED();
-  return gfx::Rect();
-}
-
-void X11WindowBase::UnConfineCursor() {
-  if (!has_pointer_barriers_)
-    return;
-
-  for (XID pointer_barrier : pointer_barriers_)
-    XFixesDestroyPointerBarrier(xdisplay_, pointer_barrier);
-  pointer_barriers_.fill(x11::None);
-
-  has_pointer_barriers_ = false;
-}
-
-bool X11WindowBase::IsEventForXWindow(const XEvent& xev) const {
-  return xwindow_ != x11::None && FindXEventTarget(xev) == xwindow_;
-}
-
-void X11WindowBase::ProcessXWindowEvent(XEvent* xev) {
-  switch (xev->type) {
-    case Expose: {
-      gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, xev->xexpose.width,
-                            xev->xexpose.height);
-      delegate_->OnDamageRect(damage_rect);
-      break;
-    }
-
-    case x11::FocusOut:
-      if (xev->xfocus.mode != NotifyGrab)
-        delegate_->OnLostCapture();
-      break;
-
-    case ConfigureNotify: {
-      DCHECK_EQ(xwindow_, xev->xconfigure.event);
-      DCHECK_EQ(xwindow_, xev->xconfigure.window);
-      // It's possible that the X window may be resized by some other means than
-      // from within aura (e.g. the X window manager can change the size). Make
-      // sure the root window size is maintained properly.
-      int translated_x_in_pixels = xev->xconfigure.x;
-      int translated_y_in_pixels = xev->xconfigure.y;
-      if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) {
-        Window unused;
-        XTranslateCoordinates(xdisplay_, xwindow_, xroot_window_, 0, 0,
-                              &translated_x_in_pixels, &translated_y_in_pixels,
-                              &unused);
-      }
-      gfx::Rect bounds(translated_x_in_pixels, translated_y_in_pixels,
-                       xev->xconfigure.width, xev->xconfigure.height);
-      if (bounds_ != bounds) {
-        bounds_ = bounds;
-        delegate_->OnBoundsChanged(bounds_);
-      }
-      break;
-    }
-
-    case ClientMessage: {
-      Atom message = static_cast<Atom>(xev->xclient.data.l[0]);
-      if (message == gfx::GetAtom("WM_DELETE_WINDOW")) {
-        delegate_->OnCloseRequest();
-      } else if (message == gfx::GetAtom("_NET_WM_PING")) {
-        XEvent reply_event = *xev;
-        reply_event.xclient.window = xroot_window_;
-
-        XSendEvent(xdisplay_, reply_event.xclient.window, x11::False,
-                   SubstructureRedirectMask | SubstructureNotifyMask,
-                   &reply_event);
-        XFlush(xdisplay_);
-      }
-      break;
-    }
-    case PropertyNotify: {
-      ::Atom changed_atom = xev->xproperty.atom;
-      if (changed_atom == gfx::GetAtom("_NET_WM_STATE"))
-        OnWMStateUpdated();
-      break;
-    }
-  }
-}
-
-void X11WindowBase::OnWMStateUpdated() {
-  std::vector<::Atom> atom_list;
-  // Ignore the return value of ui::GetAtomArrayProperty(). Fluxbox removes the
-  // _NET_WM_STATE property when no _NET_WM_STATE atoms are set.
-  ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list);
-
-  window_properties_.clear();
-  std::copy(atom_list.begin(), atom_list.end(),
-            inserter(window_properties_, window_properties_.begin()));
-
-  // Propagate the window state information to the client.
-  // Note that the order of checks is important here, because window can have
-  // several proprties at the same time.
-  PlatformWindowState old_state = state_;
-  if (ui::HasWMSpecProperty(window_properties_,
-                            gfx::GetAtom("_NET_WM_STATE_HIDDEN"))) {
-    state_ = PlatformWindowState::kMinimized;
-  } else if (ui::HasWMSpecProperty(window_properties_,
-                                   gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"))) {
-    state_ = PlatformWindowState::kFullScreen;
-  } else if (ui::HasWMSpecProperty(
-                 window_properties_,
-                 gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) &&
-             ui::HasWMSpecProperty(
-                 window_properties_,
-                 gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"))) {
-    state_ = PlatformWindowState::kMaximized;
-  } else {
-    state_ = PlatformWindowState::kNormal;
-  }
-
-  if (old_state != state_)
-    delegate_->OnWindowStateChanged(state_);
-}
-
-bool X11WindowBase::IsMaximized() const {
-  return state_ == PlatformWindowState::kMaximized;
-}
-
-bool X11WindowBase::IsFullscreen() const {
-  return state_ == PlatformWindowState::kFullScreen;
-}
-
-}  // namespace ui
diff --git a/ui/platform_window/x11/x11_window_base.h b/ui/platform_window/x11/x11_window_base.h
deleted file mode 100644
index 05b8dd1..0000000
--- a/ui/platform_window/x11/x11_window_base.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2016 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_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_
-#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_
-
-#include <stdint.h>
-
-#include <array>
-
-#include "base/callback.h"
-#include "base/containers/flat_set.h"
-#include "base/macros.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/x/x11.h"
-#include "ui/gfx/x/x11_types.h"
-#include "ui/platform_window/platform_window.h"
-#include "ui/platform_window/platform_window_delegate.h"
-#include "ui/platform_window/x11/x11_window_export.h"
-
-namespace ui {
-
-class XScopedEventSelector;
-
-// Abstract base implementation for a X11 based PlatformWindow. Methods that
-// are platform specific are left unimplemented.
-class X11_WINDOW_EXPORT X11WindowBase : public PlatformWindow {
- public:
-  X11WindowBase(PlatformWindowDelegate* delegate, const gfx::Rect& bounds);
-  ~X11WindowBase() override;
-
-  // PlatformWindow:
-  void Show() override;
-  void Hide() override;
-  void Close() override;
-  void SetBounds(const gfx::Rect& bounds) override;
-  gfx::Rect GetBounds() override;
-  void SetTitle(const base::string16& title) override;
-  void SetCapture() override;
-  void ReleaseCapture() override;
-  bool HasCapture() const override;
-  void ToggleFullscreen() override;
-  void Maximize() override;
-  void Minimize() override;
-  void Restore() override;
-  PlatformWindowState GetPlatformWindowState() const override;
-  void Activate() override;
-  void Deactivate() override;
-  void MoveCursorTo(const gfx::Point& location) override;
-  void ConfineCursorToBounds(const gfx::Rect& bounds) override;
-  void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override;
-  gfx::Rect GetRestoredBoundsInPixels() const override;
-
- protected:
-  // Creates new underlying XWindow. Does not map XWindow.
-  void Create();
-
-  void Destroy();
-
-  PlatformWindowDelegate* delegate() { return delegate_; }
-  XDisplay* xdisplay() { return xdisplay_; }
-  XID xwindow() const { return xwindow_; }
-
-  void UnConfineCursor();
-
-  // Checks if XEvent is for this XWindow.
-  bool IsEventForXWindow(const XEvent& xev) const;
-
-  // Processes events for this XWindow.
-  void ProcessXWindowEvent(XEvent* xev);
-
- private:
-  // Called when WM_STATE property is changed.
-  void OnWMStateUpdated();
-
-  bool IsMaximized() const;
-  bool IsFullscreen() const;
-
-  PlatformWindowDelegate* const delegate_;
-
-  XDisplay* xdisplay_;
-  XID xwindow_ = x11::None;
-  XID xroot_window_;
-  std::unique_ptr<ui::XScopedEventSelector> xwindow_events_;
-
-  base::string16 window_title_;
-
-  // The bounds of |xwindow_|.
-  gfx::Rect bounds_;
-
-  // The window manager state bits.
-  base::flat_set<::Atom> window_properties_;
-
-  // Stores current state of this window.
-  PlatformWindowState state_;
-
-  // Keep track of barriers to confine cursor.
-  bool has_pointer_barriers_ = false;
-  std::array<XID, 4> pointer_barriers_;
-
-  bool window_mapped_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(X11WindowBase);
-};
-
-}  // namespace ui
-
-#endif  // UI_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index e585e00..7872cc6 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -707,6 +707,7 @@
         "widget/desktop_aura/desktop_window_tree_host.cc",
       ]
       if (use_x11) {
+        deps += [ "//ui/platform_window/x11" ]
         public += [
           "widget/desktop_aura/desktop_drag_drop_client_aurax11.h",
           "widget/desktop_aura/desktop_screen_x11.h",
@@ -762,7 +763,7 @@
         ]
         deps += [ "//ui/base:hit_test" ]
       }
-      if ((is_linux && !use_x11) || is_fuchsia) {
+      if (is_linux || is_fuchsia) {
         public += [ "widget/desktop_aura/desktop_window_tree_host_platform.h" ]
         sources +=
             [ "widget/desktop_aura/desktop_window_tree_host_platform.cc" ]
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index 4331c2a..f494d1f 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -26,62 +26,6 @@
 
 namespace views {
 
-namespace {
-
-ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
-    const Widget::InitParams& params) {
-  ui::PlatformWindowInitProperties properties;
-
-  switch (params.type) {
-    case Widget::InitParams::TYPE_WINDOW:
-      properties.type = ui::PlatformWindowType::kWindow;
-      break;
-
-    case Widget::InitParams::TYPE_MENU:
-      properties.type = ui::PlatformWindowType::kMenu;
-      break;
-
-    case Widget::InitParams::TYPE_TOOLTIP:
-      properties.type = ui::PlatformWindowType::kTooltip;
-      break;
-
-    default:
-      properties.type = ui::PlatformWindowType::kPopup;
-      break;
-  }
-
-  properties.bounds = params.bounds;
-  properties.activatable =
-      params.activatable == Widget::InitParams::ACTIVATABLE_YES;
-  properties.force_show_in_taskbar = params.force_show_in_taskbar;
-  properties.keep_on_top =
-      params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal;
-  properties.visible_on_all_workspaces = params.visible_on_all_workspaces;
-  properties.remove_standard_frame = params.remove_standard_frame;
-  properties.workspace = params.workspace;
-  properties.wm_class_name = params.wm_class_name;
-  properties.wm_class_class = params.wm_class_class;
-  properties.wm_role_name = params.wm_role_name;
-
-  if (params.parent && params.parent->GetHost())
-    properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget();
-
-  switch (params.opacity) {
-    case Widget::InitParams::WindowOpacity::INFER_OPACITY:
-      properties.opacity = ui::PlatformWindowOpacity::kInferOpacity;
-      break;
-    case Widget::InitParams::WindowOpacity::OPAQUE_WINDOW:
-      properties.opacity = ui::PlatformWindowOpacity::kOpaqueWindow;
-      break;
-    case Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW:
-      properties.opacity = ui::PlatformWindowOpacity::kTranslucentWindow;
-      break;
-  }
-
-  return properties;
-}
-
-}  // namespace
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHostPlatform:
 
@@ -92,9 +36,13 @@
       desktop_native_widget_aura_(desktop_native_widget_aura) {}
 
 DesktopWindowTreeHostPlatform::~DesktopWindowTreeHostPlatform() {
+// TODO(msisov): Once destruction goes from DWTHX11 to DWTHPlatform, remove this
+// guard.
+#if !defined(USE_X11)
   DCHECK(got_on_closed_);
   desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
   DestroyDispatcher();
+#endif
 }
 
 void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) {
@@ -138,6 +86,18 @@
 
 void DesktopWindowTreeHostPlatform::OnActiveWindowChanged(bool active) {}
 
+base::Optional<gfx::Size>
+DesktopWindowTreeHostPlatform::GetMinimumSizeForWindow() {
+  return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMinimumSize()))
+      .size();
+}
+
+base::Optional<gfx::Size>
+DesktopWindowTreeHostPlatform::GetMaximumSizeForWindow() {
+  return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMaximumSize()))
+      .size();
+}
+
 std::unique_ptr<corewm::Tooltip>
 DesktopWindowTreeHostPlatform::CreateTooltip() {
   return std::make_unique<corewm::TooltipAura>();
@@ -146,6 +106,7 @@
 std::unique_ptr<aura::client::DragDropClient>
 DesktopWindowTreeHostPlatform::CreateDragDropClient(
     DesktopNativeCursorManager* cursor_manager) {
+#if !defined(USE_X11)
   ui::WmDragHandler* drag_handler = ui::GetWmDragHandler(*(platform_window()));
   std::unique_ptr<DesktopDragDropClientOzone> drag_drop_client =
       std::make_unique<DesktopDragDropClientOzone>(window(), cursor_manager,
@@ -154,6 +115,11 @@
   // drop action.
   SetWmDropHandler(platform_window(), drag_drop_client.get());
   return std::move(drag_drop_client);
+#else
+  // TODO(https://crbug.com/990756): Move the X11 initialization of dnd here.
+  NOTIMPLEMENTED_LOG_ONCE();
+  return nullptr;
+#endif
 }
 
 void DesktopWindowTreeHostPlatform::Close() {
@@ -571,6 +537,72 @@
   desktop_native_widget_aura_->HandleActivationChanged(active);
 }
 
+ui::PlatformWindowInitProperties
+DesktopWindowTreeHostPlatform::ConvertWidgetInitParamsToInitProperties(
+    const Widget::InitParams& params) {
+  ui::PlatformWindowInitProperties properties;
+
+  switch (params.type) {
+    case Widget::InitParams::TYPE_WINDOW:
+      properties.type = ui::PlatformWindowType::kWindow;
+      break;
+
+    case Widget::InitParams::TYPE_MENU:
+      properties.type = ui::PlatformWindowType::kMenu;
+      break;
+
+    case Widget::InitParams::TYPE_TOOLTIP:
+      properties.type = ui::PlatformWindowType::kTooltip;
+      break;
+
+    case Widget::InitParams::TYPE_DRAG:
+      properties.type = ui::PlatformWindowType::kDrag;
+      break;
+
+    case Widget::InitParams::TYPE_BUBBLE:
+      properties.type = ui::PlatformWindowType::kBubble;
+      break;
+
+    default:
+      properties.type = ui::PlatformWindowType::kPopup;
+      break;
+  }
+
+  properties.bounds = params.bounds;
+  properties.activatable =
+      params.activatable == Widget::InitParams::ACTIVATABLE_YES;
+  properties.force_show_in_taskbar = params.force_show_in_taskbar;
+  properties.keep_on_top =
+      params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal;
+  properties.visible_on_all_workspaces = params.visible_on_all_workspaces;
+  properties.remove_standard_frame = params.remove_standard_frame;
+  properties.workspace = params.workspace;
+  properties.wm_class_name = params.wm_class_name;
+  properties.wm_class_class = params.wm_class_class;
+  properties.wm_role_name = params.wm_role_name;
+
+  if (params.parent && params.parent->GetHost())
+    properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget();
+
+  switch (params.opacity) {
+    case Widget::InitParams::WindowOpacity::INFER_OPACITY:
+      properties.opacity = ui::PlatformWindowOpacity::kInferOpacity;
+      break;
+    case Widget::InitParams::WindowOpacity::OPAQUE_WINDOW:
+      properties.opacity = ui::PlatformWindowOpacity::kOpaqueWindow;
+      break;
+    case Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW:
+      properties.opacity = ui::PlatformWindowOpacity::kTranslucentWindow;
+      break;
+  }
+
+  return properties;
+}
+
+aura::Window* DesktopWindowTreeHostPlatform::content_window() {
+  return desktop_native_widget_aura_->content_window();
+}
+
 void DesktopWindowTreeHostPlatform::Relayout() {
   Widget* widget = native_widget_delegate_->AsWidget();
   NonClientView* non_client_view = widget->non_client_view();
@@ -612,6 +644,11 @@
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHost:
 
+// As DWTHX11 subclasses DWTHPlatform now (during transition period. see
+// https://crbug.com/990756), we need to guard this factory method.
+// TODO(msisov): remove this guard once DWTHX11 is finally merged into
+// DWTHPlatform.
+#if !defined(USE_X11)
 // static
 DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
     internal::NativeWidgetDelegate* native_widget_delegate,
@@ -619,5 +656,6 @@
   return new DesktopWindowTreeHostPlatform(native_widget_delegate,
                                            desktop_native_widget_aura);
 }
+#endif
 
 }  // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
index d826f85..f3f9ace 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -90,12 +90,29 @@
   bool ShouldUseDesktopNativeCursorManager() const override;
   bool ShouldCreateVisibilityController() const override;
 
-  // WindowTreeHostPlatform:
+  // PlatformWindowDelegateBase:
   void DispatchEvent(ui::Event* event) override;
   void OnClosed() override;
   void OnWindowStateChanged(ui::PlatformWindowState new_state) override;
   void OnCloseRequest() override;
   void OnActivationChanged(bool active) override;
+  base::Optional<gfx::Size> GetMinimumSizeForWindow() override;
+  base::Optional<gfx::Size> GetMaximumSizeForWindow() override;
+
+ protected:
+  // TODO(https://crbug.com/990756): move this back to unnamed namespace, when
+  // DWTHX11 stops initialization of the PlatformWindow. Also, remove these
+  // accessor methods.
+  ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
+      const Widget::InitParams& params);
+  internal::NativeWidgetDelegate* native_widget_delegate() {
+    return native_widget_delegate_;
+  }
+  DesktopNativeWidgetAura* desktop_native_widget_aura() {
+    return desktop_native_widget_aura_;
+  }
+  // Accessor for DesktopNativeWidgetAura::content_window().
+  aura::Window* content_window();
 
  private:
   FRIEND_TEST_ALL_PREFIXES(DesktopWindowTreeHostPlatformTest, HitTest);
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index d47565e..312df3e9 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -22,7 +22,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
@@ -54,6 +53,7 @@
 #include "ui/gfx/path_x11.h"
 #include "ui/gfx/x/x11.h"
 #include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/platform_window/x11/x11_window.h"
 #include "ui/views/corewm/tooltip_aura.h"
 #include "ui/views/linux_ui/linux_ui.h"
 #include "ui/views/views_delegate.h"
@@ -88,61 +88,6 @@
 
 namespace {
 
-ui::XWindow::Configuration ConvertInitParamsToX11WindowConfig(
-    const Widget::InitParams& params) {
-  using WindowType = ui::XWindow::WindowType;
-  using WindowOpacity = ui::XWindow::WindowOpacity;
-  ui::XWindow::Configuration config;
-
-  switch (params.type) {
-    case Widget::InitParams::TYPE_WINDOW:
-      config.type = WindowType::kWindow;
-      break;
-    case Widget::InitParams::TYPE_MENU:
-      config.type = WindowType::kMenu;
-      break;
-    case Widget::InitParams::TYPE_TOOLTIP:
-      config.type = WindowType::kTooltip;
-      break;
-    case Widget::InitParams::TYPE_DRAG:
-      config.type = WindowType::kDrag;
-      break;
-    case Widget::InitParams::TYPE_BUBBLE:
-      config.type = WindowType::kBubble;
-      break;
-    default:
-      config.type = WindowType::kPopup;
-      break;
-  }
-
-  switch (params.opacity) {
-    case Widget::InitParams::WindowOpacity::INFER_OPACITY:
-      config.opacity = WindowOpacity::kInferOpacity;
-      break;
-    case Widget::InitParams::WindowOpacity::OPAQUE_WINDOW:
-      config.opacity = WindowOpacity::kOpaqueWindow;
-      break;
-    case Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW:
-      config.opacity = WindowOpacity::kTranslucentWindow;
-      break;
-  }
-
-  config.activatable =
-      params.activatable == Widget::InitParams::ACTIVATABLE_YES;
-  config.force_show_in_taskbar = params.force_show_in_taskbar;
-  config.keep_on_top =
-      params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal;
-  config.visible_on_all_workspaces = params.visible_on_all_workspaces;
-  config.remove_standard_frame = params.remove_standard_frame;
-
-  config.workspace = params.workspace;
-  config.wm_class_name = params.wm_class_name;
-  config.wm_class_class = params.wm_class_class;
-  config.wm_role_name = params.wm_role_name;
-
-  return config;
-}
-
 // Returns the whole path from |window| to the root.
 std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) {
   ::Window parent_win, root_win;
@@ -152,8 +97,8 @@
 
   while (window) {
     result.push_back(window);
-    if (!XQueryTree(xdisplay, window,
-                    &root_win, &parent_win, &child_windows, &num_child_windows))
+    if (!XQueryTree(xdisplay, window, &root_win, &parent_win, &child_windows,
+                    &num_child_windows))
       break;
     if (child_windows)
       XFree(child_windows);
@@ -210,14 +155,14 @@
 DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
     internal::NativeWidgetDelegate* native_widget_delegate,
     DesktopNativeWidgetAura* desktop_native_widget_aura)
-    : native_widget_delegate_(native_widget_delegate),
-      desktop_native_widget_aura_(desktop_native_widget_aura),
-      x11_window_(std::make_unique<ui::XWindow>(this)) {}
+    : DesktopWindowTreeHostPlatform(native_widget_delegate,
+                                    desktop_native_widget_aura),
+      x11_window_(std::make_unique<ui::X11Window>(this, this)) {}
 
 DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
   window()->ClearProperty(kHostForRootWindow);
   wm::SetWindowMoveClient(window(), nullptr);
-  desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
+  desktop_native_widget_aura()->OnDesktopWindowTreeHostDestroyed(this);
   DestroyDispatcher();
 }
 
@@ -238,9 +183,7 @@
 // static
 std::vector<aura::Window*> DesktopWindowTreeHostX11::GetAllOpenWindows() {
   std::vector<aura::Window*> windows(open_windows().size());
-  std::transform(open_windows().begin(),
-                 open_windows().end(),
-                 windows.begin(),
+  std::transform(open_windows().begin(), open_windows().end(), windows.begin(),
                  GetContentWindowForXID);
   return windows;
 }
@@ -327,7 +270,7 @@
 
   SetWindowTransparency();
 
-  native_widget_delegate_->OnNativeWidgetCreated();
+  native_widget_delegate()->OnNativeWidgetCreated();
 }
 
 void DesktopWindowTreeHostX11::OnWidgetInitDone() {}
@@ -367,10 +310,11 @@
 void DesktopWindowTreeHostX11::CloseNow() {
   if (x11_window_->window() == x11::None)
     return;
+  x11_window_->PrepareForShutdown();
 
   ReleaseCapture();
   RemoveNonClientEventFilter();
-  native_widget_delegate_->OnNativeWidgetDestroying();
+  native_widget_delegate()->OnNativeWidgetDestroying();
 
   // If we have children, close them. Use a copy for iteration because they'll
   // remove themselves.
@@ -391,12 +335,8 @@
   DestroyCompositor();
 
   open_windows().remove(x11_window_->window());
-  // Actually free our native resources.
-  if (auto* source = ui::PlatformEventSource::GetInstance())
-    source->RemovePlatformEventDispatcher(this);
 
   x11_window_->Close();
-  desktop_native_widget_aura_->OnHostClosed();
 }
 
 aura::WindowTreeHost* DesktopWindowTreeHostX11::AsWindowTreeHost() {
@@ -430,7 +370,7 @@
       break;
   }
 
-  native_widget_delegate_->AsWidget()->SetInitialFocus(show_state);
+  native_widget_delegate()->AsWidget()->SetInitialFocus(show_state);
 
   content_window()->Show();
 }
@@ -695,7 +635,7 @@
   if (compositor())
     compositor()->SetVisible(visible);
 
-  native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
+  native_widget_delegate()->OnNativeWidgetVisibilityChanged(visible);
 }
 
 void DesktopWindowTreeHostX11::SetVisibleOnAllWorkspaces(bool always_visible) {
@@ -707,7 +647,9 @@
 }
 
 bool DesktopWindowTreeHostX11::SetWindowTitle(const base::string16& title) {
-  return x11_window_->SetTitle(title);
+  auto* x_window = static_cast<ui::XWindow*>(x11_window_.get());
+  DCHECK(x_window);
+  return x_window->SetTitle(title);
 }
 
 void DesktopWindowTreeHostX11::ClearNativeFocus() {
@@ -748,7 +690,7 @@
 
 NonClientFrameView* DesktopWindowTreeHostX11::CreateNonClientFrameView() {
   return ShouldUseNativeFrame()
-             ? new NativeFrameView(native_widget_delegate_->AsWidget())
+             ? new NativeFrameView(native_widget_delegate()->AsWidget())
              : nullptr;
 }
 
@@ -762,7 +704,7 @@
 
 void DesktopWindowTreeHostX11::FrameTypeChanged() {
   Widget::FrameType new_type =
-      native_widget_delegate_->AsWidget()->frame_type();
+      native_widget_delegate()->AsWidget()->frame_type();
   if (new_type == Widget::FrameType::kDefault) {
     // The default is determined by Widget::InitParams::remove_standard_frame
     // and does not change.
@@ -841,8 +783,8 @@
   x11_window_->SetAspectRatio(aspect_ratio);
 }
 
-void DesktopWindowTreeHostX11::SetWindowIcons(
-    const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
+void DesktopWindowTreeHostX11::SetWindowIcons(const gfx::ImageSkia& window_icon,
+                                              const gfx::ImageSkia& app_icon) {
   x11_window_->SetWindowIcons(window_icon, app_icon);
 }
 
@@ -918,7 +860,9 @@
 }
 
 void DesktopWindowTreeHostX11::HideImpl() {
-  if (x11_window_->Hide())
+  auto* x_window = static_cast<ui::XWindow*>(x11_window_.get());
+  DCHECK(x_window);
+  if (x_window->Hide())
     SetVisible(false);
 }
 
@@ -932,7 +876,6 @@
   gfx::Rect bounds_in_pixels(requested_bounds_in_pixel.origin(),
                              AdjustSize(requested_bounds_in_pixel.size()));
 
-  bool origin_changed = bounds.origin() != bounds_in_pixels.origin();
   bool size_changed = bounds.size() != bounds_in_pixels.size();
 
   if (size_changed) {
@@ -942,14 +885,6 @@
   }
 
   x11_window_->SetBounds(bounds_in_pixels);
-
-  if (origin_changed)
-    native_widget_delegate_->AsWidget()->OnNativeWidgetMove();
-
-  if (size_changed) {
-    OnHostResizedInPixels(bounds_in_pixels.size());
-    ResetWindowRegion();
-  }
 }
 
 gfx::Point DesktopWindowTreeHostX11::GetLocationOnScreenInPixels() const {
@@ -1046,204 +981,16 @@
   }
 }
 
-void DesktopWindowTreeHostX11::OnXWindowCreated() {
-  if (auto* source = ui::PlatformEventSource::GetInstance())
-    source->AddPlatformEventDispatcher(this);
-
-  open_windows().push_front(x11_window_->window());
-}
-
-void DesktopWindowTreeHostX11::OnXWindowMapped() {
-  for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
-    observer.OnWindowMapped(x11_window_->window());
-}
-
-void DesktopWindowTreeHostX11::OnXWindowUnmapped() {
-  for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
-    observer.OnWindowUnmapped(x11_window_->window());
-}
-
-void DesktopWindowTreeHostX11::OnXWindowStateChanged() {
-  bool was_minimized = x11_window_->was_minimized();
-  bool is_minimized = IsMinimized();
-
-  // Propagate the window minimization information to the content window, so
-  // the render side can update its visibility properly. OnWMStateUpdated() is
-  // called by PropertyNofify event from DispatchEvent() when the browser is
-  // minimized or shown from minimized state. On Windows, this is realized by
-  // calling OnHostResizedInPixels() with an empty size. In particular,
-  // HWNDMessageHandler::GetClientAreaBounds() returns an empty size when the
-  // window is minimized. On Linux, returning empty size in GetBounds() or
-  // SetBoundsInPixels() does not work.
-  // We also propagate the minimization to the compositor, to makes sure that we
-  // don't draw any 'blank' frames that could be noticed in applications such as
-  // window manager previews, which show content even when a window is
-  // minimized.
-  if (is_minimized != was_minimized) {
-    if (is_minimized) {
-      SetVisible(false);
-      content_window()->Hide();
-    } else {
-      content_window()->Show();
-      SetVisible(true);
-    }
-  }
-
-  if (restored_bounds_in_pixels_.IsEmpty()) {
-    if (IsMaximized()) {
-      // The request that we become maximized originated from a different
-      // process. |bounds_in_pixels_| already contains our maximized bounds. Do
-      // a best effort attempt to get restored bounds by setting it to our
-      // previously set bounds (and if we get this wrong, we aren't any worse
-      // off since we'd otherwise be returning our maximized bounds).
-      restored_bounds_in_pixels_ = x11_window_->previous_bounds();
-    }
-  } else if (!IsMaximized() && !IsFullscreen()) {
-    // If we have restored bounds, but WM_STATE no longer claims to be
-    // maximized or fullscreen, we should clear our restored bounds.
-    restored_bounds_in_pixels_ = gfx::Rect();
-  }
-
-  // Now that we have different window properties, we may need to relayout the
-  // window. (The windows code doesn't need this because their window change is
-  // synchronous.)
-  Relayout();
-  ResetWindowRegion();
-}
-
-void DesktopWindowTreeHostX11::OnXWindowWorkspaceChanged() {
-  OnHostWorkspaceChanged();
-}
-
-void DesktopWindowTreeHostX11::OnXWindowDamageEvent(
-    const gfx::Rect& damage_rect_in_pixels) {
-  compositor()->ScheduleRedrawRect(damage_rect_in_pixels);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowKeyEvent(ui::KeyEvent* key_event) {
-  DispatchKeyEvent(key_event);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowMouseEvent(ui::MouseEvent* mouseev) {
-  DispatchMouseEvent(mouseev);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowTouchEvent(
-    ui::TouchEvent* touch_event) {
-  DispatchTouchEvent(touch_event);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowScrollEvent(
-    ui::ScrollEvent* scroll_event) {
-  SendEventToSink(scroll_event);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowSelectionEvent(XEvent* xev) {
-  DCHECK(xev);
-  DCHECK(drag_drop_client_);
-  drag_drop_client_->OnSelectionNotify(xev->xselection);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowDragDropEvent(XEvent* xev) {
-  DCHECK(xev);
-  DCHECK(drag_drop_client_);
-
-  ::Atom message_type = xev->xclient.message_type;
-  if (message_type == gfx::GetAtom("XdndEnter")) {
-    drag_drop_client_->OnXdndEnter(xev->xclient);
-  } else if (message_type == gfx::GetAtom("XdndLeave")) {
-    drag_drop_client_->OnXdndLeave(xev->xclient);
-  } else if (message_type == gfx::GetAtom("XdndPosition")) {
-    drag_drop_client_->OnXdndPosition(xev->xclient);
-  } else if (message_type == gfx::GetAtom("XdndStatus")) {
-    drag_drop_client_->OnXdndStatus(xev->xclient);
-  } else if (message_type == gfx::GetAtom("XdndFinished")) {
-    drag_drop_client_->OnXdndFinished(xev->xclient);
-  } else if (message_type == gfx::GetAtom("XdndDrop")) {
-    drag_drop_client_->OnXdndDrop(xev->xclient);
-  }
-}
-
-void DesktopWindowTreeHostX11::OnXWindowRawKeyEvent(XEvent* xev) {
-  switch (xev->type) {
-    case KeyPress:
-      if (!ShouldDiscardKeyEvent(xev)) {
-        ui::KeyEvent keydown_event(xev);
-        DispatchKeyEvent(&keydown_event);
-      }
-      break;
-    case KeyRelease:
-
-      // There is no way to deactivate a window in X11 so ignore input if
-      // window is supposed to be 'inactive'.
-      if (!IsActive() && !HasCapture())
-        break;
-
-      if (!ShouldDiscardKeyEvent(xev)) {
-        ui::KeyEvent keyup_event(xev);
-        DispatchKeyEvent(&keyup_event);
-      }
-      break;
-    default:
-      NOTREACHED() << xev->type;
-      break;
-  }
-}
-
-void DesktopWindowTreeHostX11::OnXWindowChildCrossingEvent(XEvent* xev) {
-  DCHECK(xev);
-  ui::MouseEvent mouse_event(xev);
-  DispatchMouseEvent(&mouse_event);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowSizeChanged(
-    const gfx::Size& size_in_pixels) {
-  OnHostResizedInPixels(size_in_pixels);
-  ResetWindowRegion();
-}
-
-void DesktopWindowTreeHostX11::OnXWindowCloseRequested() {
-  OnHostCloseRequested();
-}
-
-void DesktopWindowTreeHostX11::OnXWindowMoved(const gfx::Point& window_origin) {
-  OnHostMovedInPixels(window_origin);
-}
-
-void DesktopWindowTreeHostX11::OnXWindowLostPointerGrab() {
-  dispatcher()->OnHostLostMouseGrab();
-}
-
-void DesktopWindowTreeHostX11::OnXWindowLostCapture() {
-  OnHostLostWindowCapture();
-}
-
-void DesktopWindowTreeHostX11::OnXWindowIsActiveChanged(bool active) {
-  if (active) {
-    // TODO(thomasanderson): Remove this window shuffling and use XWindowCache
-    // instead.
-    ::Window xwindow = x11_window_->window();
-    open_windows().remove(xwindow);
-    open_windows().insert(open_windows().begin(), xwindow);
-  }
-  desktop_native_widget_aura_->HandleActivationChanged(active);
-  native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
-}
-
-gfx::Size DesktopWindowTreeHostX11::GetMinimumSizeForXWindow() {
-  return ToPixelRect(gfx::Rect(native_widget_delegate_->GetMinimumSize()))
-      .size();
-}
-
-gfx::Size DesktopWindowTreeHostX11::GetMaximumSizeForXWindow() {
-  return ToPixelRect(gfx::Rect(native_widget_delegate_->GetMaximumSize()))
-      .size();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHostX11, private:
 
 void DesktopWindowTreeHostX11::InitX11Window(const Widget::InitParams& params) {
+  // Disable compositing on tooltips as a workaround for
+  // https://crbug.com/442111.
+  CreateCompositor(viz::FrameSinkId(),
+                   params.force_software_compositing ||
+                       params.type == Widget::InitParams::TYPE_TOOLTIP);
+
   // Calculate initial bounds
   gfx::Rect bounds_in_pixels = ToPixelRect(params.bounds);
   gfx::Size adjusted_size = AdjustSize(bounds_in_pixels.size());
@@ -1272,20 +1019,14 @@
     background_color = theme->GetSystemColor(target_color);
   }
 
-  // Create window configuration and initialize it
-  ui::XWindow::Configuration config =
-      ConvertInitParamsToX11WindowConfig(params);
-  config.bounds = bounds_in_pixels;
-  config.background_color = background_color;
-  config.prefer_dark_theme = linux_ui && linux_ui->PreferDarkTheme();
-  config.icon = ViewsDelegate::GetInstance()->GetDefaultWindowIcon();
-  x11_window_->Init(config);
-
-  // Disable compositing on tooltips as a workaround for
-  // https://crbug.com/442111.
-  CreateCompositor(viz::FrameSinkId(),
-                   params.force_software_compositing ||
-                       params.type == Widget::InitParams::TYPE_TOOLTIP);
+  // Create PlatformWindowInitProperties and initialize it
+  ui::PlatformWindowInitProperties properties =
+      ConvertWidgetInitParamsToInitProperties(params);
+  properties.bounds = bounds_in_pixels;
+  properties.background_color = background_color;
+  properties.prefer_dark_theme = linux_ui && linux_ui->PreferDarkTheme();
+  properties.icon = ViewsDelegate::GetInstance()->GetDefaultWindowIcon();
+  x11_window_->Initialize(std::move(properties));
 
   if (ui::IsSyncExtensionAvailable()) {
     compositor_observer_ = std::make_unique<SwapWithNewSizeObserverHelper>(
@@ -1293,7 +1034,6 @@
                           &DesktopWindowTreeHostX11::OnCompleteSwapWithNewSize,
                           base::Unretained(this)));
   }
-  OnAcceleratedWidgetAvailable();
 }
 
 void DesktopWindowTreeHostX11::DispatchHostWindowDragMovement(
@@ -1388,7 +1128,7 @@
 }
 
 void DesktopWindowTreeHostX11::DispatchKeyEvent(ui::KeyEvent* event) {
-  if (native_widget_delegate_->AsWidget()->IsActive())
+  if (native_widget_delegate()->AsWidget()->IsActive())
     SendEventToSink(event);
 }
 
@@ -1396,7 +1136,7 @@
   _XRegion* xregion = nullptr;
   if (!x11_window_->use_custom_shape() && !IsMaximized() && !IsFullscreen()) {
     SkPath window_mask;
-    Widget* widget = native_widget_delegate_->AsWidget();
+    Widget* widget = native_widget_delegate()->AsWidget();
     if (widget->non_client_view()) {
       // Some frame views define a custom (non-rectangular) window mask. If
       // so, use it to define the window shape. If not, fall through.
@@ -1410,7 +1150,6 @@
   x11_window_->UpdateWindowRegion(xregion);
 }
 
-
 std::list<XID>& DesktopWindowTreeHostX11::open_windows() {
   if (!open_windows_)
     open_windows_ = new std::list<XID>();
@@ -1443,7 +1182,7 @@
 }
 
 void DesktopWindowTreeHostX11::Relayout() {
-  Widget* widget = native_widget_delegate_->AsWidget();
+  Widget* widget = native_widget_delegate()->AsWidget();
   NonClientView* non_client_view = widget->non_client_view();
   // non_client_view may be NULL, especially during creation.
   if (non_client_view) {
@@ -1453,30 +1192,14 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation:
-
-bool DesktopWindowTreeHostX11::CanDispatchEvent(
-    const ui::PlatformEvent& event) {
-  return x11_window_->IsTargetedBy(*event);
-}
-
-uint32_t DesktopWindowTreeHostX11::DispatchEvent(
-    const ui::PlatformEvent& event) {
-  XEvent* xev = event;
-
-  TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch",
-               "event->type", event->type);
-
-  x11_window_->ProcessEvent(xev);
-  return ui::POST_DISPATCH_STOP_PROPAGATION;
-}
+// DesktopWindowTreeHostX11 implementation:
 
 void DesktopWindowTreeHostX11::DelayedChangeFrameType(Widget::FrameType type) {
   SetUseNativeFrame(type == Widget::FrameType::kForceNative);
   // Replace the frame and layout the contents. Even though we don't have a
   // swappable glass frame like on Windows, we still replace the frame because
   // the button assets don't update otherwise.
-  native_widget_delegate_->AsWidget()->non_client_view()->UpdateFrame();
+  native_widget_delegate()->AsWidget()->non_client_view()->UpdateFrame();
 }
 
 gfx::Rect DesktopWindowTreeHostX11::ToDIPRect(
@@ -1513,10 +1236,6 @@
     targeter_for_modal_.reset();
 }
 
-aura::Window* DesktopWindowTreeHostX11::content_window() {
-  return desktop_native_widget_aura_->content_window();
-}
-
 void DesktopWindowTreeHostX11::OnCompleteSwapWithNewSize(
     const gfx::Size& size) {
   x11_window_->NotifySwapAfterResize();
@@ -1534,6 +1253,165 @@
   x11_window_->set_visual_id(visual_id);
 }
 
+void DesktopWindowTreeHostX11::OnBoundsChanged(const gfx::Rect& new_bounds) {
+  ResetWindowRegion();
+  WindowTreeHostPlatform::OnBoundsChanged(new_bounds);
+}
+
+void DesktopWindowTreeHostX11::DispatchEvent(ui::Event* event) {
+  if (event->IsKeyEvent())
+    DispatchKeyEvent(event->AsKeyEvent());
+  else if (event->IsMouseEvent())
+    DispatchMouseEvent(event->AsMouseEvent());
+  else if (event->IsTouchEvent())
+    DispatchTouchEvent(event->AsTouchEvent());
+  else
+    SendEventToSink(event);
+}
+
+void DesktopWindowTreeHostX11::OnClosed() {
+  desktop_native_widget_aura()->OnHostClosed();
+}
+
+void DesktopWindowTreeHostX11::OnWindowStateChanged(
+    ui::PlatformWindowState new_state) {
+  bool was_minimized = x11_window_->was_minimized();
+  bool is_minimized = IsMinimized();
+
+  // Propagate the window minimization information to the content window, so
+  // the render side can update its visibility properly. OnWMStateUpdated() is
+  // called by PropertyNofify event from DispatchEvent() when the browser is
+  // minimized or shown from minimized state. On Windows, this is realized by
+  // calling OnHostResizedInPixels() with an empty size. In particular,
+  // HWNDMessageHandler::GetClientAreaBounds() returns an empty size when the
+  // window is minimized. On Linux, returning empty size in GetBounds() or
+  // SetBoundsInPixels() does not work.
+  // We also propagate the minimization to the compositor, to makes sure that we
+  // don't draw any 'blank' frames that could be noticed in applications such as
+  // window manager previews, which show content even when a window is
+  // minimized.
+  if (is_minimized != was_minimized) {
+    if (is_minimized) {
+      SetVisible(false);
+      content_window()->Hide();
+    } else {
+      content_window()->Show();
+      SetVisible(true);
+    }
+  }
+
+  if (restored_bounds_in_pixels_.IsEmpty()) {
+    if (IsMaximized()) {
+      // The request that we become maximized originated from a different
+      // process. |bounds_in_pixels_| already contains our maximized bounds. Do
+      // a best effort attempt to get restored bounds by setting it to our
+      // previously set bounds (and if we get this wrong, we aren't any worse
+      // off since we'd otherwise be returning our maximized bounds).
+      restored_bounds_in_pixels_ = x11_window_->previous_bounds();
+    }
+  } else if (!IsMaximized() && !IsFullscreen()) {
+    // If we have restored bounds, but WM_STATE no longer claims to be
+    // maximized or fullscreen, we should clear our restored bounds.
+    restored_bounds_in_pixels_ = gfx::Rect();
+  }
+
+  // Now that we have different window properties, we may need to relayout the
+  // window. (The windows code doesn't need this because their window change is
+  // synchronous.)
+  Relayout();
+  ResetWindowRegion();
+}
+
+void DesktopWindowTreeHostX11::OnAcceleratedWidgetAvailable(
+    gfx::AcceleratedWidget widget) {
+  open_windows().push_front(x11_window_->window());
+  WindowTreeHost::OnAcceleratedWidgetAvailable();
+}
+
+void DesktopWindowTreeHostX11::OnAcceleratedWidgetDestroyed() {}
+
+void DesktopWindowTreeHostX11::OnActivationChanged(bool active) {
+  if (active) {
+    // TODO(thomasanderson): Remove this window shuffling and use XWindowCache
+    // instead.
+    ::Window xwindow = x11_window_->window();
+    open_windows().remove(xwindow);
+    open_windows().insert(open_windows().begin(), xwindow);
+  }
+  desktop_native_widget_aura()->HandleActivationChanged(active);
+  native_widget_delegate()->AsWidget()->GetRootView()->SchedulePaint();
+}
+
+void DesktopWindowTreeHostX11::OnXWindowMapped() {
+  for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
+    observer.OnWindowMapped(x11_window_->window());
+}
+
+void DesktopWindowTreeHostX11::OnXWindowUnmapped() {
+  for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
+    observer.OnWindowUnmapped(x11_window_->window());
+}
+
+void DesktopWindowTreeHostX11::OnLostMouseGrab() {
+  dispatcher()->OnHostLostMouseGrab();
+}
+
+void DesktopWindowTreeHostX11::OnWorkspaceChanged() {
+  OnHostWorkspaceChanged();
+}
+
+void DesktopWindowTreeHostX11::OnXWindowSelectionEvent(XEvent* xev) {
+  DCHECK(xev);
+  DCHECK(drag_drop_client_);
+  drag_drop_client_->OnSelectionNotify(xev->xselection);
+}
+
+void DesktopWindowTreeHostX11::OnXWindowDragDropEvent(XEvent* xev) {
+  DCHECK(xev);
+  DCHECK(drag_drop_client_);
+
+  ::Atom message_type = xev->xclient.message_type;
+  if (message_type == gfx::GetAtom("XdndEnter")) {
+    drag_drop_client_->OnXdndEnter(xev->xclient);
+  } else if (message_type == gfx::GetAtom("XdndLeave")) {
+    drag_drop_client_->OnXdndLeave(xev->xclient);
+  } else if (message_type == gfx::GetAtom("XdndPosition")) {
+    drag_drop_client_->OnXdndPosition(xev->xclient);
+  } else if (message_type == gfx::GetAtom("XdndStatus")) {
+    drag_drop_client_->OnXdndStatus(xev->xclient);
+  } else if (message_type == gfx::GetAtom("XdndFinished")) {
+    drag_drop_client_->OnXdndFinished(xev->xclient);
+  } else if (message_type == gfx::GetAtom("XdndDrop")) {
+    drag_drop_client_->OnXdndDrop(xev->xclient);
+  }
+}
+
+void DesktopWindowTreeHostX11::OnXWindowRawKeyEvent(XEvent* xev) {
+  switch (xev->type) {
+    case KeyPress:
+      if (!ShouldDiscardKeyEvent(xev)) {
+        ui::KeyEvent keydown_event(xev);
+        DispatchKeyEvent(&keydown_event);
+      }
+      break;
+    case KeyRelease:
+
+      // There is no way to deactivate a window in X11 so ignore input if
+      // window is supposed to be 'inactive'.
+      if (!IsActive() && !HasCapture())
+        break;
+
+      if (!ShouldDiscardKeyEvent(xev)) {
+        ui::KeyEvent keyup_event(xev);
+        DispatchKeyEvent(&keyup_event);
+      }
+      break;
+    default:
+      NOTREACHED() << xev->type;
+      break;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHost, public:
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index f180625..4a9949a 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -20,14 +20,14 @@
 #include "base/observer_list.h"
 #include "ui/aura/scoped_window_targeter.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/base/x/x11_window.h"
-#include "ui/events/platform/platform_event_dispatcher.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/x/x11_types.h"
+#include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
+#include "ui/platform_window/x11/x11_window.h"
 #include "ui/views/views_export.h"
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
 
 namespace gfx {
 class ImageSkia;
@@ -39,8 +39,8 @@
 class KeyEvent;
 class MouseEvent;
 class TouchEvent;
-class ScrollEvent;
-}
+class X11Window;
+}  // namespace ui
 
 namespace views {
 class DesktopDragDropClientAuraX11;
@@ -50,11 +50,9 @@
 class WindowEventFilter;
 
 class VIEWS_EXPORT DesktopWindowTreeHostX11
-    : public DesktopWindowTreeHost,
-      public aura::WindowTreeHost,
-      public ui::PlatformEventDispatcher,
+    : public DesktopWindowTreeHostPlatform,
       public ui::WmMoveResizeHandler,
-      public ui::XWindow::Delegate {
+      public ui::XEventDelegate {
  public:
   DesktopWindowTreeHostX11(
       internal::NativeWidgetDelegate* native_widget_delegate,
@@ -195,30 +193,6 @@
   void OnDisplayMetricsChanged(const display::Display& display,
                                uint32_t changed_metrics) override;
 
-  // Overridden from ui::XWindow::Delegate
-  void OnXWindowCreated() override;
-  void OnXWindowMapped() override;
-  void OnXWindowUnmapped() override;
-  void OnXWindowStateChanged() override;
-  void OnXWindowWorkspaceChanged() override;
-  void OnXWindowKeyEvent(ui::KeyEvent* key_event) override;
-  void OnXWindowMouseEvent(ui::MouseEvent* mouseev) override;
-  void OnXWindowTouchEvent(ui::TouchEvent* touch_event) override;
-  void OnXWindowScrollEvent(ui::ScrollEvent* scroll_event) override;
-  void OnXWindowSelectionEvent(XEvent* xev) override;
-  void OnXWindowDragDropEvent(XEvent* xev) override;
-  void OnXWindowChildCrossingEvent(XEvent* xev) override;
-  void OnXWindowRawKeyEvent(XEvent* xev) override;
-  void OnXWindowSizeChanged(const gfx::Size& size) override;
-  void OnXWindowCloseRequested() override;
-  void OnXWindowMoved(const gfx::Point& window_origin) override;
-  void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override;
-  void OnXWindowLostPointerGrab() override;
-  void OnXWindowLostCapture() override;
-  void OnXWindowIsActiveChanged(bool active) override;
-  gfx::Size GetMinimumSizeForXWindow() override;
-  gfx::Size GetMaximumSizeForXWindow() override;
-
  private:
   friend class DesktopWindowTreeHostX11HighDPITest;
 
@@ -270,10 +244,6 @@
   // Relayout the widget's client and non-client views.
   void Relayout();
 
-  // ui::PlatformEventDispatcher:
-  bool CanDispatchEvent(const ui::PlatformEvent& event) override;
-  uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
-
   void DelayedChangeFrameType(Widget::FrameType new_type);
 
   gfx::Rect ToDIPRect(const gfx::Rect& rect_in_pixels) const;
@@ -285,12 +255,31 @@
   // Set visibility and fire OnNativeWidgetVisibilityChanged() if it changed.
   void SetVisible(bool visible);
 
-  // Accessor for DesktopNativeWidgetAura::content_window().
-  aura::Window* content_window();
-
   // Callback for a swapbuffer after resize.
   void OnCompleteSwapWithNewSize(const gfx::Size& size);
 
+  // PlatformWindowDelegate overrides:
+  //
+  // DWTHX11 temporarily overrides the PlatformWindowDelegate methods instead of
+  // underlying DWTHPlatform and WTHPlatform. Eventually, these will be removed
+  // from here as we progress in https://crbug.com/990756.
+  void OnBoundsChanged(const gfx::Rect& new_bounds) override;
+  void DispatchEvent(ui::Event* event) override;
+  void OnClosed() override;
+  void OnWindowStateChanged(ui::PlatformWindowState new_state) override;
+  void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override;
+  void OnAcceleratedWidgetDestroyed() override;
+  void OnActivationChanged(bool active) override;
+  void OnXWindowMapped() override;
+  void OnXWindowUnmapped() override;
+  void OnLostMouseGrab() override;
+  void OnWorkspaceChanged() override;
+
+  // Overridden from ui::XEventDelegate.
+  void OnXWindowSelectionEvent(XEvent* xev) override;
+  void OnXWindowDragDropEvent(XEvent* xev) override;
+  void OnXWindowRawKeyEvent(XEvent* xev) override;
+
   // The bounds of our window before we were maximized.
   gfx::Rect restored_bounds_in_pixels_;
 
@@ -306,12 +295,6 @@
   std::unique_ptr<WindowEventFilter> non_client_event_filter_;
   std::unique_ptr<X11DesktopWindowMoveClient> x11_window_move_client_;
 
-  // TODO(beng): Consider providing an interface to DesktopNativeWidgetAura
-  //             instead of providing this route back to Widget.
-  internal::NativeWidgetDelegate* native_widget_delegate_;
-
-  DesktopNativeWidgetAura* desktop_native_widget_aura_;
-
   // We can optionally have a parent which can order us to close, or own
   // children who we're responsible for closing when we CloseNow().
   DesktopWindowTreeHostX11* window_parent_ = nullptr;
@@ -340,7 +323,7 @@
 
   std::unique_ptr<CompositorObserver> compositor_observer_;
 
-  std::unique_ptr<ui::XWindow> x11_window_;
+  std::unique_ptr<ui::X11Window> x11_window_;
 
   // The display and the native X window hosting the root window.
   base::WeakPtrFactory<DesktopWindowTreeHostX11> close_widget_factory_{this};
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc
index 5f154118..8bd27d2 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc
@@ -14,6 +14,7 @@
 #include "ui/base/x/x11_util.h"
 #include "ui/events/event_handler.h"
 #include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/events/platform/x11/x11_event_source_glib.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/x/x11.h"
 #include "ui/gfx/x/x11_atom_cache.h"
@@ -106,7 +107,8 @@
   xev.xmotion.is_hint = NotifyNormal;
   xev.xmotion.same_screen = x11::True;
 
-  static_cast<ui::PlatformEventDispatcher*>(desktop_host)->DispatchEvent(&xev);
+  static_cast<ui::X11EventSourceGlib*>(ui::PlatformEventSource::GetInstance())
+      ->ProcessXEvent(&xev);
 }
 
 }  // namespace