diff --git a/ui/base/x/x11_window.cc b/ui/base/x/x11_window.cc
index 1bb97da344812..9cba7d4e3a7ec 100644
--- a/ui/base/x/x11_window.cc
+++ b/ui/base/x/x11_window.cc
@@ -88,6 +88,25 @@ bool SyncSetCounter(XDisplay* display, XID counter, int64_t value) {
   return XSyncSetCounter(display, counter, sync_value) == x11::True;
 }
 
+// Returns the whole path from |window| to the root.
+std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) {
+  ::Window parent_win, root_win;
+  Window* child_windows;
+  unsigned int num_child_windows;
+  std::vector<::Window> result;
+
+  while (window) {
+    result.push_back(window);
+    if (!XQueryTree(xdisplay, window, &root_win, &parent_win, &child_windows,
+                    &num_child_windows))
+      break;
+    if (child_windows)
+      XFree(child_windows);
+    window = parent_win;
+  }
+  return result;
+}
+
 }  // namespace
 
 XWindow::Configuration::Configuration()
@@ -632,7 +651,37 @@ void XWindow::ReleasePointerGrab() {
   has_pointer_grab_ = false;
 }
 
-void XWindow::StackAtTop() {
+void XWindow::StackXWindowAbove(::Window window) {
+  DCHECK(window != x11::None);
+
+  // Find all parent windows up to the root.
+  std::vector<::Window> window_below_parents =
+      GetParentsList(xdisplay_, window);
+  std::vector<::Window> window_above_parents =
+      GetParentsList(xdisplay_, xwindow_);
+
+  // Find their common ancestor.
+  auto it_below_window = window_below_parents.rbegin();
+  auto it_above_window = window_above_parents.rbegin();
+  for (; it_below_window != window_below_parents.rend() &&
+         it_above_window != window_above_parents.rend() &&
+         *it_below_window == *it_above_window;
+       ++it_below_window, ++it_above_window) {
+  }
+
+  if (it_below_window != window_below_parents.rend() &&
+      it_above_window != window_above_parents.rend()) {
+    // First stack |xwindow| below so Z-order of |window| stays the same.
+    ::Window windows[] = {*it_below_window, *it_above_window};
+    if (XRestackWindows(xdisplay_, windows, 2) == 0) {
+      // Now stack them properly.
+      std::swap(windows[0], windows[1]);
+      XRestackWindows(xdisplay_, windows, 2);
+    }
+  }
+}
+
+void XWindow::StackXWindowAtTop() {
   XRaiseWindow(xdisplay_, xwindow_);
 }
 
diff --git a/ui/base/x/x11_window.h b/ui/base/x/x11_window.h
index 9db97d2f52145..96d79b85e4b03 100644
--- a/ui/base/x/x11_window.h
+++ b/ui/base/x/x11_window.h
@@ -102,7 +102,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow {
   bool IsActive() const;
   void GrabPointer();
   void ReleasePointerGrab();
-  void StackAtTop();
+  void StackXWindowAbove(::Window window);
+  void StackXWindowAtTop();
   bool IsTargetedBy(const XEvent& xev) const;
   void WmMoveResize(int hittest, const gfx::Point& location) const;
   void ProcessEvent(XEvent* xev);
diff --git a/ui/platform_window/platform_window.cc b/ui/platform_window/platform_window.cc
index e42f8ce524d6c..b586913c1ee8f 100644
--- a/ui/platform_window/platform_window.cc
+++ b/ui/platform_window/platform_window.cc
@@ -16,4 +16,8 @@ ZOrderLevel PlatformWindow::GetZOrderLevel() const {
   return ZOrderLevel::kNormal;
 }
 
+void PlatformWindow::StackAbove(gfx::AcceleratedWidget widget) {}
+
+void PlatformWindow::StackAtTop() {}
+
 }  // namespace ui
diff --git a/ui/platform_window/platform_window.h b/ui/platform_window/platform_window.h
index a5ca9927f5be7..4d98e364e0d68 100644
--- a/ui/platform_window/platform_window.h
+++ b/ui/platform_window/platform_window.h
@@ -11,6 +11,7 @@
 #include "ui/base/class_property.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/ui_base_types.h"
+#include "ui/gfx/native_widget_types.h"
 #include "ui/platform_window/platform_window_delegate.h"
 
 namespace gfx {
@@ -82,6 +83,10 @@ class PlatformWindow : public PropertyHandler {
   // implementation always returns ZOrderLevel::kNormal value.
   virtual void SetZOrderLevel(ZOrderLevel order);
   virtual ZOrderLevel GetZOrderLevel() const;
+
+  // Asks the PlatformWindow to stack itself on top of |widget|.
+  virtual void StackAbove(gfx::AcceleratedWidget widget);
+  virtual void StackAtTop();
 };
 
 }  // namespace ui
diff --git a/ui/platform_window/win/win_window.cc b/ui/platform_window/win/win_window.cc
index 94810b5b4fe72..45b02f0f97efb 100644
--- a/ui/platform_window/win/win_window.cc
+++ b/ui/platform_window/win/win_window.cc
@@ -158,6 +158,14 @@ ZOrderLevel WinWindow::GetZOrderLevel() const {
   return ZOrderLevel::kNormal;
 }
 
+void WinWindow::StackAbove(gfx::AcceleratedWidget widget) {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void WinWindow::StackAtTop() {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
 LRESULT WinWindow::OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param) {
   MSG msg = {hwnd(),
              message,
diff --git a/ui/platform_window/win/win_window.h b/ui/platform_window/win/win_window.h
index e83464a2c0035..b78e346307808 100644
--- a/ui/platform_window/win/win_window.h
+++ b/ui/platform_window/win/win_window.h
@@ -52,6 +52,8 @@ class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
   gfx::Rect GetRestoredBoundsInPixels() const override;
   void SetZOrderLevel(ZOrderLevel order) override;
   ZOrderLevel GetZOrderLevel() const override;
+  void StackAbove(gfx::AcceleratedWidget widget) override;
+  void StackAtTop() override;
 
   CR_BEGIN_MSG_MAP_EX(WinWindow)
     CR_MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc
index 3620a87fe1378..46dbd5fa3f2a1 100644
--- a/ui/platform_window/x11/x11_window.cc
+++ b/ui/platform_window/x11/x11_window.cc
@@ -238,6 +238,14 @@ ZOrderLevel X11Window::GetZOrderLevel() const {
                               : ui::ZOrderLevel::kNormal;
 }
 
+void X11Window::StackAbove(gfx::AcceleratedWidget widget) {
+  XWindow::StackXWindowAbove(static_cast<::Window>(widget));
+}
+
+void X11Window::StackAtTop() {
+  XWindow::StackXWindowAtTop();
+}
+
 bool X11Window::CanDispatchEvent(const PlatformEvent& xev) {
 #if defined(USE_X11)
   return XWindow::IsTargetedBy(*xev);
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h
index 739b87391e52e..f2189b3695ebd 100644
--- a/ui/platform_window/x11/x11_window.h
+++ b/ui/platform_window/x11/x11_window.h
@@ -71,6 +71,8 @@ class X11_WINDOW_EXPORT X11Window : public PlatformWindow,
   gfx::Rect GetRestoredBoundsInPixels() const override;
   void SetZOrderLevel(ZOrderLevel order) override;
   ZOrderLevel GetZOrderLevel() const override;
+  void StackAbove(gfx::AcceleratedWidget widget) override;
+  void StackAtTop() override;
 
  protected:
   PlatformWindowDelegateLinux* platform_window_delegate() const {
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 f6e9cfd7c9b39..8a9a6fae6306b 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
@@ -290,11 +290,14 @@ void DesktopWindowTreeHostPlatform::SetSize(const gfx::Size& size) {
 }
 
 void DesktopWindowTreeHostPlatform::StackAbove(aura::Window* window) {
-  NOTIMPLEMENTED_LOG_ONCE();
+  if (!window || !window->GetRootWindow())
+    return;
+
+  platform_window()->StackAbove(window->GetHost()->GetAcceleratedWidget());
 }
 
 void DesktopWindowTreeHostPlatform::StackAtTop() {
-  NOTIMPLEMENTED_LOG_ONCE();
+  platform_window()->StackAtTop();
 }
 
 void DesktopWindowTreeHostPlatform::CenterWindow(const gfx::Size& size) {
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 f209d8bed7dc5..51742bba84a5d 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
@@ -81,25 +81,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(DesktopWindowTreeHostX11*,
 
 namespace {
 
-// Returns the whole path from |window| to the root.
-std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) {
-  ::Window parent_win, root_win;
-  Window* child_windows;
-  unsigned int num_child_windows;
-  std::vector<::Window> result;
-
-  while (window) {
-    result.push_back(window);
-    if (!XQueryTree(xdisplay, window, &root_win, &parent_win, &child_windows,
-                    &num_child_windows))
-      break;
-    if (child_windows)
-      XFree(child_windows);
-    window = parent_win;
-  }
-  return result;
-}
-
 class SwapWithNewSizeObserverHelper : public ui::CompositorObserver {
  public:
   using HelperCallback = base::RepeatingCallback<void(const gfx::Size&)>;
@@ -319,44 +300,6 @@ void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) {
   }
 }
 
-void DesktopWindowTreeHostX11::StackAbove(aura::Window* window) {
-  XDisplay* display = GetXWindow()->display();
-  ::Window xwindow = GetXWindow()->window();
-
-  if (window && window->GetRootWindow()) {
-    ::Window window_below = window->GetHost()->GetAcceleratedWidget();
-    // Find all parent windows up to the root.
-    std::vector<::Window> window_below_parents =
-        GetParentsList(display, window_below);
-    std::vector<::Window> window_above_parents =
-        GetParentsList(display, xwindow);
-
-    // Find their common ancestor.
-    auto it_below_window = window_below_parents.rbegin();
-    auto it_above_window = window_above_parents.rbegin();
-    for (; it_below_window != window_below_parents.rend() &&
-           it_above_window != window_above_parents.rend() &&
-           *it_below_window == *it_above_window;
-         ++it_below_window, ++it_above_window) {
-    }
-
-    if (it_below_window != window_below_parents.rend() &&
-        it_above_window != window_above_parents.rend()) {
-      // First stack |xwindow| below so Z-order of |window| stays the same.
-      ::Window windows[] = {*it_below_window, *it_above_window};
-      if (XRestackWindows(display, windows, 2) == 0) {
-        // Now stack them properly.
-        std::swap(windows[0], windows[1]);
-        XRestackWindows(display, windows, 2);
-      }
-    }
-  }
-}
-
-void DesktopWindowTreeHostX11::StackAtTop() {
-  GetXWindow()->StackAtTop();
-}
-
 void DesktopWindowTreeHostX11::GetWindowPlacement(
     gfx::Rect* bounds,
     ui::WindowShowState* show_state) const {
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 87702baa1f044..a3a015af02044 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
@@ -102,8 +102,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11 : public DesktopWindowTreeHostLinux,
             const gfx::Rect& restore_bounds) override;
   bool IsVisible() const override;
   void SetSize(const gfx::Size& requested_size) override;
-  void StackAbove(aura::Window* window) override;
-  void StackAtTop() override;
   void GetWindowPlacement(gfx::Rect* bounds,
                           ui::WindowShowState* show_state) const override;
   gfx::Rect GetRestoredBounds() const override;