[go: nahoru, domu]

Views/Aura/ui: Replace the "always on top" bool with a z-order enum.

On the Mac, translate the z-order enum to the native window level
values. On other platforms, treat everything other than "normal"
as an undifferentiated "always on top" leaving open the possibility
of implementing full window level support on ChromeOS later.

There are six basic window levels. The "security sensitive" one
is unused in this CL but will be used in a follow-up CL to fix
a bug.

BUG=865287, 869486

Change-Id: Icf3c39b79490a6490b7ad107a94cf5903d569777
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1636606
Commit-Queue: Avi Drissman <avi@chromium.org>
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: Leonard Grey <lgrey@chromium.org>
Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#672649}
diff --git a/ash/accelerators/exit_warning_handler.cc b/ash/accelerators/exit_warning_handler.cc
index a274a69..51dedf1 100644
--- a/ash/accelerators/exit_warning_handler.cc
+++ b/ash/accelerators/exit_warning_handler.cc
@@ -147,7 +147,7 @@
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.accept_events = false;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.delegate = delegate;
   params.bounds = bounds;
   params.name = "ExitWarningWindow";
diff --git a/ash/assistant/ui/assistant_container_view.cc b/ash/assistant/ui/assistant_container_view.cc
index ff5688f..8fe6e2e 100644
--- a/ash/assistant/ui/assistant_container_view.cc
+++ b/ash/assistant/ui/assistant_container_view.cc
@@ -312,7 +312,7 @@
     views::Widget* widget) const {
   params->context = delegate_->GetRootWindowForNewWindows();
   params->corner_radius = kCornerRadiusDip;
-  params->keep_on_top = true;
+  params->z_order = ui::ZOrderLevel::kFloatingWindow;
 }
 
 views::ClientView* AssistantContainerView::CreateClientView(
diff --git a/ash/display/shared_display_edge_indicator.cc b/ash/display/shared_display_edge_indicator.cc
index cc3af89..9e79579 100644
--- a/ash/display/shared_display_edge_indicator.cc
+++ b/ash/display/shared_display_edge_indicator.cc
@@ -51,7 +51,7 @@
   params.context = Shell::GetRootWindowControllerWithDisplayId(display.id())
                        ->GetRootWindow();
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   widget->set_focus_on_creation(false);
   widget->Init(params);
   widget->SetVisibilityChangedAnimationsEnabled(false);
diff --git a/ash/display/touch_calibrator_view.cc b/ash/display/touch_calibrator_view.cc
index ec9b5b6..e40c540 100644
--- a/ash/display/touch_calibrator_view.cc
+++ b/ash/display/touch_calibrator_view.cc
@@ -87,7 +87,7 @@
   views::Widget::InitParams params;
   params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
   params.name = kWidgetName;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingWindow;
   params.accept_events = true;
   params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
diff --git a/ash/drag_drop/drag_image_view.cc b/ash/drag_drop/drag_image_view.cc
index 8ed7d4b0..73e9da60 100644
--- a/ash/drag_drop/drag_image_view.cc
+++ b/ash/drag_drop/drag_image_view.cc
@@ -25,7 +25,6 @@
   Widget::InitParams params;
   params.type = Widget::InitParams::TYPE_TOOLTIP;
   params.name = "DragWidget";
-  params.keep_on_top = true;
   params.accept_events = false;
   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.shadow_type = Widget::InitParams::SHADOW_TYPE_NONE;
@@ -48,7 +47,6 @@
   DCHECK(root_window);
   widget_ = CreateDragWidget(root_window);
   widget_->SetContentsView(this);
-  widget_->SetAlwaysOnTop(true);
 
   // We are owned by the DragDropController.
   set_owned_by_client();
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index a56dc92..09c55e4 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -2347,7 +2347,8 @@
 
   wm::GetWindowState(window_two)
       ->set_autohide_shelf_when_maximized_or_fullscreen(true);
-  window_two->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  window_two->SetProperty(aura::client::kZOrderingKey,
+                          ui::ZOrderLevel::kFloatingWindow);
 
   auto* shelf_window = shelf->GetWindow();
   aura::Window* container = shelf_window->GetRootWindow()->GetChildById(
@@ -3099,7 +3100,8 @@
   aura::Window* window = CreateTestWindow();
   window->SetBounds(gfx::Rect(0, 0, 100, 100));
   // Set always on top so it is put in the PIP container.
-  window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  window->SetProperty(aura::client::kZOrderingKey,
+                      ui::ZOrderLevel::kFloatingWindow);
   window->Show();
   const wm::WMEvent pip_event(wm::WM_EVENT_PIP);
   wm::GetWindowState(window)->OnWMEvent(&pip_event);
diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc
index 878403fb..b9870b38 100644
--- a/ash/shell_unittest.cc
+++ b/ash/shell_unittest.cc
@@ -195,7 +195,8 @@
                         bool always_on_top,
                         aura::Window* expected_container) {
     views::Widget::InitParams widget_params(type);
-    widget_params.keep_on_top = always_on_top;
+    if (always_on_top)
+      widget_params.z_order = ui::ZOrderLevel::kFloatingWindow;
 
     views::Widget* widget = CreateTestWindow(widget_params);
     widget->Show();
@@ -281,11 +282,11 @@
             widget.GetRestoredBounds().CenterPoint());
 }
 
-TEST_F(ShellTest, ChangeAlwaysOnTop) {
+TEST_F(ShellTest, ChangeZOrderLevel) {
   views::Widget::InitParams widget_params(
       views::Widget::InitParams::TYPE_WINDOW);
 
-  // Creates a normal window
+  // Creates a normal window.
   views::Widget* widget = CreateTestWindow(widget_params);
   widget->Show();
 
@@ -293,19 +294,19 @@
   EXPECT_TRUE(
       GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
 
-  // Flip always-on-top flag.
-  widget->SetAlwaysOnTop(true);
+  // Set the z-order to float.
+  widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
   // And it should in always on top container now.
   EXPECT_EQ(GetAlwaysOnTopContainer(), widget->GetNativeWindow()->parent());
 
-  // Flip always-on-top flag.
-  widget->SetAlwaysOnTop(false);
+  // Put the z-order back to normal.
+  widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
   // It should go back to the active desk container.
   EXPECT_TRUE(
       GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
 
-  // Set the same always-on-top flag again.
-  widget->SetAlwaysOnTop(false);
+  // Set the z-order again to the normal value.
+  widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
   // Should have no effect and we are still in the the active desk container.
   EXPECT_TRUE(
       GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
diff --git a/ash/sticky_keys/sticky_keys_overlay.cc b/ash/sticky_keys/sticky_keys_overlay.cc
index cc96f1f..b86db125 100644
--- a/ash/sticky_keys/sticky_keys_overlay.cc
+++ b/ash/sticky_keys/sticky_keys_overlay.cc
@@ -211,7 +211,7 @@
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.accept_events = false;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.bounds = CalculateOverlayBounds();
   params.parent = Shell::GetContainer(Shell::GetRootWindowForNewWindows(),
                                       kShellWindowId_OverlayContainer);
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc
index 6bcda10..f71e4c6 100644
--- a/ash/system/power/power_button_controller.cc
+++ b/ash/system/power/power_button_controller.cc
@@ -64,7 +64,7 @@
   views::Widget::InitParams params(
       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingWindow;
   params.accept_events = true;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.name = "PowerButtonMenuWindow";
diff --git a/ash/system/session/logout_confirmation_controller_unittest.cc b/ash/system/session/logout_confirmation_controller_unittest.cc
index c74750c..1ca732e 100644
--- a/ash/system/session/logout_confirmation_controller_unittest.cc
+++ b/ash/system/session/logout_confirmation_controller_unittest.cc
@@ -286,7 +286,7 @@
 
   // Moving the widget to the always-on-top container does not trigger the
   // dialog because the window didn't close.
-  widget->SetAlwaysOnTop(true);
+  widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
   EXPECT_FALSE(controller->dialog_for_testing());
 
   // Closing the window triggers the dialog.
@@ -302,7 +302,7 @@
   // Create two windows in different containers.
   std::unique_ptr<views::Widget> normal_widget = CreateTestWidget();
   std::unique_ptr<views::Widget> always_on_top_widget = CreateTestWidget();
-  always_on_top_widget->SetAlwaysOnTop(true);
+  always_on_top_widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
 
   // Closing the last window shows the dialog.
   always_on_top_widget.reset();
diff --git a/ash/system/toast/toast_overlay.cc b/ash/system/toast/toast_overlay.cc
index ee85141..0eda9fe 100644
--- a/ash/system/toast/toast_overlay.cc
+++ b/ash/system/toast/toast_overlay.cc
@@ -231,7 +231,7 @@
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.accept_events = true;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.bounds = CalculateOverlayBounds();
   // Show toasts above the app list and below the lock screen.
   params.parent = Shell::GetRootWindowForNewWindows()->GetChildById(
diff --git a/ash/system/tray/tray_event_filter.cc b/ash/system/tray/tray_event_filter.cc
index ea8827a..e291bf0 100644
--- a/ash/system/tray/tray_event_filter.cc
+++ b/ash/system/tray/tray_event_filter.cc
@@ -63,7 +63,7 @@
     // from message center.
     if (container_id == kShellWindowId_StatusContainer &&
         target->type() == aura::client::WINDOW_TYPE_POPUP && target_widget &&
-        target_widget->IsAlwaysOnTop()) {
+        target_widget->GetZOrderLevel() != ui::ZOrderLevel::kNormal) {
       return;
     }
     // Don't process events that occurred inside a virtual keyboard.
diff --git a/ash/system/tray/tray_event_filter_unittest.cc b/ash/system/tray/tray_event_filter_unittest.cc
index 1706348d..550e63ea 100644
--- a/ash/system/tray/tray_event_filter_unittest.cc
+++ b/ash/system/tray/tray_event_filter_unittest.cc
@@ -109,8 +109,8 @@
       CreateTestWindow(gfx::Rect(), aura::client::WINDOW_TYPE_POPUP);
   popup_window->set_owned_by_parent(false);
   popup_widget->GetNativeView()->AddChild(popup_window.get());
-  popup_widget->GetNativeView()->SetProperty(aura::client::kAlwaysOnTopKey,
-                                             true);
+  popup_widget->GetNativeView()->SetProperty(aura::client::kZOrderingKey,
+                                             ui::ZOrderLevel::kFloatingWindow);
 
   ShowSystemTrayMainView();
   EXPECT_TRUE(IsBubbleShown());
diff --git a/ash/wm/always_on_top_controller.cc b/ash/wm/always_on_top_controller.cc
index 92b1798..f41a9d9 100644
--- a/ash/wm/always_on_top_controller.cc
+++ b/ash/wm/always_on_top_controller.cc
@@ -44,7 +44,11 @@
   DCHECK(always_on_top_container_);
   DCHECK(pip_container_);
 
-  if (!window->GetProperty(aura::client::kAlwaysOnTopKey)) {
+  // On other platforms, there are different window levels. For now, treat any
+  // window with non-normal level as "always on top". Perhaps the nuance of
+  // multiple levels will be needed later.
+  if (window->GetProperty(aura::client::kZOrderingKey) ==
+      ui::ZOrderLevel::kNormal) {
     aura::Window* root = always_on_top_container_->GetRootWindow();
 
     // TODO(afakhry): Do we need to worry about the context of |window| here? Or
@@ -103,7 +107,7 @@
                                                     const void* key,
                                                     intptr_t old) {
   if (window != always_on_top_container_ && window != pip_container_ &&
-      key == aura::client::kAlwaysOnTopKey) {
+      key == aura::client::kZOrderingKey) {
     ReparentWindow(window);
   }
 }
diff --git a/ash/wm/always_on_top_controller_unittest.cc b/ash/wm/always_on_top_controller_unittest.cc
index 8117a9e..826dc2e 100644
--- a/ash/wm/always_on_top_controller_unittest.cc
+++ b/ash/wm/always_on_top_controller_unittest.cc
@@ -80,7 +80,7 @@
 }
 
 TEST_F(AlwaysOnTopControllerTest,
-       AlwaysOnTopContainerReturnedForAlwaysOnTopWindow) {
+       AlwaysOnTopContainerReturnedForFloatingWindow) {
   RootWindowController* controller = Shell::GetPrimaryRootWindowController();
   AlwaysOnTopController* always_on_top_controller =
       controller->always_on_top_controller();
@@ -88,7 +88,8 @@
   const gfx::Rect bounds(100, 100, 200, 200);
   std::unique_ptr<aura::Window> always_on_top_window(
       CreateTestWindowInShellWithBounds(bounds));
-  always_on_top_window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  always_on_top_window->SetProperty(aura::client::kZOrderingKey,
+                                    ui::ZOrderLevel::kFloatingWindow);
 
   aura::Window* container =
       always_on_top_controller->GetContainer(always_on_top_window.get());
@@ -96,7 +97,7 @@
   EXPECT_EQ(kShellWindowId_AlwaysOnTopContainer, container->id());
 }
 
-TEST_F(AlwaysOnTopControllerTest, PipContainerReturnedForAlwaysOnTopPipWindow) {
+TEST_F(AlwaysOnTopControllerTest, PipContainerReturnedForFloatingPipWindow) {
   RootWindowController* controller = Shell::GetPrimaryRootWindowController();
   AlwaysOnTopController* always_on_top_controller =
       controller->always_on_top_controller();
@@ -108,7 +109,8 @@
   wm::WindowState* window_state = wm::GetWindowState(pip_window.get());
   const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
   window_state->OnWMEvent(&enter_pip);
-  pip_window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  pip_window->SetProperty(aura::client::kZOrderingKey,
+                          ui::ZOrderLevel::kFloatingWindow);
   EXPECT_TRUE(window_state->IsPip());
 
   aura::Window* container =
@@ -134,11 +136,12 @@
 }
 
 TEST_F(AlwaysOnTopControllerTest,
-       AlwaysOnTopWindowMovedBetweenContainersWhenPipStateChanges) {
+       FloatingWindowMovedBetweenContainersWhenPipStateChanges) {
   const gfx::Rect bounds(100, 100, 200, 200);
   std::unique_ptr<aura::Window> window(
       CreateTestWindowInShellWithBounds(bounds));
-  window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  window->SetProperty(aura::client::kZOrderingKey,
+                      ui::ZOrderLevel::kFloatingWindow);
 
   EXPECT_EQ(kShellWindowId_AlwaysOnTopContainer, window->parent()->id());
 
diff --git a/ash/wm/ash_focus_rules_unittest.cc b/ash/wm/ash_focus_rules_unittest.cc
index 89b6c45..43e31b4 100644
--- a/ash/wm/ash_focus_rules_unittest.cc
+++ b/ash/wm/ash_focus_rules_unittest.cc
@@ -112,7 +112,8 @@
   aura::Window* CreateWindowInAlwaysOnTopContainer() {
     aura::Window* window =
         CreateWindowInContainer(kShellWindowId_AlwaysOnTopContainer);
-    window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+    window->SetProperty(aura::client::kZOrderingKey,
+                        ui::ZOrderLevel::kFloatingWindow);
     return window;
   }
 
diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc
index 1578639..2d3baac 100644
--- a/ash/wm/drag_window_resizer_unittest.cc
+++ b/ash/wm/drag_window_resizer_unittest.cc
@@ -83,7 +83,8 @@
 
     always_on_top_window_ = window_factory::NewWindow(&delegate2_);
     always_on_top_window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
-    always_on_top_window_->SetProperty(aura::client::kAlwaysOnTopKey, true);
+    always_on_top_window_->SetProperty(aura::client::kZOrderingKey,
+                                       ui::ZOrderLevel::kFloatingWindow);
     always_on_top_window_->Init(ui::LAYER_NOT_DRAWN);
     ParentWindowInPrimaryRootWindow(always_on_top_window_.get());
     always_on_top_window_->set_id(2);
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index cd17fda..99c1ee39 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -1019,10 +1019,14 @@
   // Preserves ordering if the category is the same.
   std::sort(items.begin(), items.end(),
             [&selected_item](OverviewItem* a, OverviewItem* b) {
+              // NB: This treats all non-normal z-ordered windows the same. If
+              // Aura ever adopts z-order levels, this will need to be changed.
               const bool a_on_top =
-                  a->GetWindow()->GetProperty(aura::client::kAlwaysOnTopKey);
+                  a->GetWindow()->GetProperty(aura::client::kZOrderingKey) !=
+                  ui::ZOrderLevel::kNormal;
               const bool b_on_top =
-                  b->GetWindow()->GetProperty(aura::client::kAlwaysOnTopKey);
+                  b->GetWindow()->GetProperty(aura::client::kZOrderingKey) !=
+                  ui::ZOrderLevel::kNormal;
               if (selected_item && a_on_top && b_on_top)
                 return a == selected_item;
               if (a_on_top)
@@ -1359,7 +1363,7 @@
   selection_widget_ = std::make_unique<views::Widget>();
   views::Widget::InitParams params;
   params.type = views::Widget::InitParams::TYPE_POPUP;
-  params.keep_on_top = false;
+  params.z_order = ui::ZOrderLevel::kNormal;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.layer_type = ui::LAYER_SOLID_COLOR;
diff --git a/ash/wm/overview/overview_grid_unittest.cc b/ash/wm/overview/overview_grid_unittest.cc
index c6ea4e1c..bbba7e9 100644
--- a/ash/wm/overview/overview_grid_unittest.cc
+++ b/ash/wm/overview/overview_grid_unittest.cc
@@ -149,7 +149,8 @@
   // window. So the first window will not animate.
   auto window1 = CreateTestWindow(gfx::Rect(100, 100));
   auto window2 = CreateTestWindow(gfx::Rect(400, 400));
-  window2->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  window2->SetProperty(aura::client::kZOrderingKey,
+                       ui::ZOrderLevel::kFloatingWindow);
   std::vector<gfx::RectF> target_bounds = {gfx::RectF(100.f, 100.f),
                                            gfx::RectF(100.f, 100.f)};
   CheckAnimationStates({window1.get(), window2.get()}, target_bounds,
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index 2c3731f..e52f167 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -2244,8 +2244,10 @@
   std::unique_ptr<aura::Window> window6(CreateTestWindow(bounds));
   std::unique_ptr<aura::Window> window7(CreateTestWindow(bounds));
   std::unique_ptr<aura::Window> window8(CreateTestWindow(bounds));
-  window3->SetProperty(aura::client::kAlwaysOnTopKey, true);
-  window5->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  window3->SetProperty(aura::client::kZOrderingKey,
+                       ui::ZOrderLevel::kFloatingWindow);
+  window5->SetProperty(aura::client::kZOrderingKey,
+                       ui::ZOrderLevel::kFloatingWindow);
 
   // Control z order and MRU order.
   ::wm::ActivateWindow(window8.get());
diff --git a/ash/wm/overview/rounded_label_widget.cc b/ash/wm/overview/rounded_label_widget.cc
index 8a10601..86c63ef 100644
--- a/ash/wm/overview/rounded_label_widget.cc
+++ b/ash/wm/overview/rounded_label_widget.cc
@@ -79,7 +79,6 @@
 void RoundedLabelWidget::Init(const InitParams& params) {
   views::Widget::InitParams widget_params;
   widget_params.type = views::Widget::InitParams::TYPE_POPUP;
-  widget_params.keep_on_top = false;
   widget_params.ownership =
       views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   widget_params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
diff --git a/ash/wm/pip/pip_window_resizer_unittest.cc b/ash/wm/pip/pip_window_resizer_unittest.cc
index e02e411..90299bc6 100644
--- a/ash/wm/pip/pip_window_resizer_unittest.cc
+++ b/ash/wm/pip/pip_window_resizer_unittest.cc
@@ -117,7 +117,7 @@
     views::Widget::InitParams params;
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
     params.bounds = screen_bounds;
-    params.keep_on_top = true;
+    params.z_order = ui::ZOrderLevel::kFloatingWindow;
     params.context = root_window;
     widget->Init(params);
     widget->Show();
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index e97ff42..91d8ba65 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -601,11 +601,13 @@
   EXPECT_TRUE(!split_view_divider());
   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
   EXPECT_TRUE(split_view_divider());
-  EXPECT_TRUE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
+  EXPECT_NE(ui::ZOrderLevel::kNormal,
+            split_view_divider()->divider_widget()->GetZOrderLevel());
   split_view_controller()->SnapWindow(window2.get(),
                                       SplitViewController::RIGHT);
   EXPECT_TRUE(split_view_divider());
-  EXPECT_TRUE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
+  EXPECT_NE(ui::ZOrderLevel::kNormal,
+            split_view_divider()->divider_widget()->GetZOrderLevel());
 
   // Test that activating an non-snappable window ends the split view mode.
   std::unique_ptr<aura::Window> window3(CreateNonSnappableWindow(bounds));
@@ -2136,7 +2138,8 @@
 TEST_F(SplitViewControllerTest, AlwaysOnTopWindow) {
   const gfx::Rect bounds(0, 0, 400, 400);
   std::unique_ptr<aura::Window> always_on_top_window(CreateWindow(bounds));
-  always_on_top_window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  always_on_top_window->SetProperty(aura::client::kZOrderingKey,
+                                    ui::ZOrderLevel::kFloatingWindow);
   std::unique_ptr<aura::Window> normal_window(CreateWindow(bounds));
 
   split_view_controller()->SnapWindow(always_on_top_window.get(),
@@ -2144,15 +2147,18 @@
   split_view_controller()->SnapWindow(normal_window.get(),
                                       SplitViewController::RIGHT);
   EXPECT_EQ(split_view_controller()->state(), SplitViewState::kBothSnapped);
-  EXPECT_TRUE(always_on_top_window->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window->GetProperty(aura::client::kZOrderingKey));
 
   wm::ActivateWindow(always_on_top_window.get());
   EXPECT_EQ(split_view_controller()->state(), SplitViewState::kBothSnapped);
-  EXPECT_TRUE(always_on_top_window->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window->GetProperty(aura::client::kZOrderingKey));
 
   wm::ActivateWindow(normal_window.get());
   EXPECT_EQ(split_view_controller()->state(), SplitViewState::kBothSnapped);
-  EXPECT_TRUE(always_on_top_window->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window->GetProperty(aura::client::kZOrderingKey));
 }
 
 // Test that pinning a window ends split view mode.
@@ -2716,18 +2722,18 @@
                                       SplitViewController::RIGHT);
   views::Widget* split_divider_widget =
       split_view_controller()->split_view_divider()->divider_widget();
-  EXPECT_TRUE(split_divider_widget->IsAlwaysOnTop());
+  EXPECT_NE(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
 
   std::unique_ptr<WindowResizer> resizer =
       StartDrag(window1.get(), window1.get());
   ASSERT_TRUE(resizer.get());
-  EXPECT_FALSE(split_divider_widget->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
 
   resizer->Drag(gfx::Point(), 0);
-  EXPECT_FALSE(split_divider_widget->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
 
   CompleteDrag(std::move(resizer));
-  EXPECT_TRUE(split_divider_widget->IsAlwaysOnTop());
+  EXPECT_NE(ui::ZOrderLevel::kNormal, split_divider_widget->GetZOrderLevel());
 }
 
 // Test the functionalities that are related to dragging a maximized window's
@@ -4079,7 +4085,8 @@
 
   EXPECT_EQ(split_view_controller()->state(), SplitViewState::kBothSnapped);
   EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_TRUE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
+  EXPECT_NE(ui::ZOrderLevel::kNormal,
+            split_view_divider()->divider_widget()->GetZOrderLevel());
 }
 
 // Tests that the divider bar should be placed on top after the drag ends, no
@@ -4102,7 +4109,8 @@
   DragWindowWithOffset(resizer.get(), 10, 10);
   CompleteDrag(std::move(resizer));
   EXPECT_EQ(split_view_controller()->state(), SplitViewState::kBothSnapped);
-  EXPECT_TRUE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
+  EXPECT_NE(ui::ZOrderLevel::kNormal,
+            split_view_divider()->divider_widget()->GetZOrderLevel());
 
   // If the dragged window is destroyed after drag ends:
   resizer = StartDrag(dragged_window.get(), dragged_window.get());
@@ -4112,7 +4120,8 @@
   dragged_window.reset();
   EXPECT_EQ(split_view_controller()->state(), SplitViewState::kRightSnapped);
   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
-  EXPECT_TRUE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
+  EXPECT_NE(ui::ZOrderLevel::kNormal,
+            split_view_divider()->divider_widget()->GetZOrderLevel());
 }
 
 TEST_F(SplitViewTabDraggingTest, IgnoreActivatedTabDraggingWindow) {
diff --git a/ash/wm/splitview/split_view_divider.cc b/ash/wm/splitview/split_view_divider.cc
index 54443cd..7a08b46 100644
--- a/ash/wm/splitview/split_view_divider.cc
+++ b/ash/wm/splitview/split_view_divider.cc
@@ -454,7 +454,7 @@
 
 void SplitViewDivider::SetAlwaysOnTop(bool on_top) {
   if (on_top) {
-    divider_widget_->SetAlwaysOnTop(true);
+    divider_widget_->SetZOrderLevel(ui::ZOrderLevel::kFloatingUIElement);
 
     // Special handling when put divider into always_on_top container. We want
     // to put it at the bottom so it won't block other always_on_top windows.
@@ -464,7 +464,7 @@
     always_on_top_container->StackChildAtBottom(
         divider_widget_->GetNativeWindow());
   } else {
-    divider_widget_->SetAlwaysOnTop(false);
+    divider_widget_->SetZOrderLevel(ui::ZOrderLevel::kNormal);
   }
 }
 
diff --git a/ash/wm/splitview/split_view_drag_indicators.cc b/ash/wm/splitview/split_view_drag_indicators.cc
index c3a7c18f..0e79125 100644
--- a/ash/wm/splitview/split_view_drag_indicators.cc
+++ b/ash/wm/splitview/split_view_drag_indicators.cc
@@ -43,7 +43,6 @@
   auto widget = std::make_unique<views::Widget>();
   views::Widget::InitParams params;
   params.type = views::Widget::InitParams::TYPE_POPUP;
-  params.keep_on_top = false;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.accept_events = false;
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.cc b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
index d73b1bd..3b63fa6 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
@@ -353,9 +353,10 @@
 void TabletModeWindowManager::OnWindowPropertyChanged(aura::Window* window,
                                                       const void* key,
                                                       intptr_t old) {
-  // Stop managing |window| if the always-on-top property is added.
-  if (key == aura::client::kAlwaysOnTopKey &&
-      window->GetProperty(aura::client::kAlwaysOnTopKey)) {
+  // Stop managing |window| if it is moved to have a non-normal z-order.
+  if (key == aura::client::kZOrderingKey &&
+      window->GetProperty(aura::client::kZOrderingKey) !=
+          ui::ZOrderLevel::kNormal) {
     ForgetWindow(window, false /* destroyed */);
   }
 }
@@ -635,10 +636,12 @@
 bool TabletModeWindowManager::ShouldHandleWindow(aura::Window* window) {
   DCHECK(window);
 
-  // Windows with the always-on-top property should be free-floating and thus
+  // Windows that don't have normal z-ordering should be free-floating and thus
   // not managed by us.
-  if (window->GetProperty(aura::client::kAlwaysOnTopKey))
+  if (window->GetProperty(aura::client::kZOrderingKey) !=
+      ui::ZOrderLevel::kNormal) {
     return false;
+  }
 
   // If the changing bounds in the maximized/fullscreen is allowed, then
   // let the client manage it even in tablet mode.
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
index 5452f7ae..284a200 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -1526,8 +1526,10 @@
       CreateWindow(aura::client::WINDOW_TYPE_NORMAL, rect1));
   std::unique_ptr<aura::Window> w2(CreateFixedSizeNonMaximizableWindow(
       aura::client::WINDOW_TYPE_NORMAL, rect2));
-  w1->SetProperty(aura::client::kAlwaysOnTopKey, true);
-  w2->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  w1->SetProperty(aura::client::kZOrderingKey,
+                  ui::ZOrderLevel::kFloatingWindow);
+  w2->SetProperty(aura::client::kZOrderingKey,
+                  ui::ZOrderLevel::kFloatingWindow);
   EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized());
   EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
   EXPECT_EQ(rect1.ToString(), w1->bounds().ToString());
@@ -1547,8 +1549,8 @@
   // Remove the always-on-top property from both windows while in maximize
   // mode. The windows should become managed, which means they should be
   // maximized/centered and no longer be draggable.
-  w1->SetProperty(aura::client::kAlwaysOnTopKey, false);
-  w2->SetProperty(aura::client::kAlwaysOnTopKey, false);
+  w1->SetProperty(aura::client::kZOrderingKey, ui::ZOrderLevel::kNormal);
+  w2->SetProperty(aura::client::kZOrderingKey, ui::ZOrderLevel::kNormal);
   EXPECT_EQ(2, manager->GetNumberOfManagedWindows());
   EXPECT_TRUE(wm::GetWindowState(w1.get())->IsMaximized());
   EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
@@ -1560,8 +1562,10 @@
   // Applying the always-on-top property to both windows while in maximize
   // mode should cause both windows to return to their original size,
   // position, and state.
-  w1->SetProperty(aura::client::kAlwaysOnTopKey, true);
-  w2->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  w1->SetProperty(aura::client::kZOrderingKey,
+                  ui::ZOrderLevel::kFloatingWindow);
+  w2->SetProperty(aura::client::kZOrderingKey,
+                  ui::ZOrderLevel::kFloatingWindow);
   EXPECT_EQ(0, manager->GetNumberOfManagedWindows());
   EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized());
   EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized());
@@ -1725,7 +1729,8 @@
   params.show_on_creation = false;
   std::unique_ptr<aura::Window> window(CreateWindowInWatchedContainer(params));
   wm::GetWindowState(window.get())->set_allow_set_bounds_direct(true);
-  window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  window->SetProperty(aura::client::kZOrderingKey,
+                      ui::ZOrderLevel::kFloatingWindow);
   window->Show();
 }
 
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc
index 01e6123..446d752 100644
--- a/ash/wm/window_state.cc
+++ b/ash/wm/window_state.cc
@@ -326,8 +326,9 @@
   }
 }
 
-void WindowState::DisableAlwaysOnTop(aura::Window* window_on_top) {
-  if (GetAlwaysOnTop() && !IsPip()) {
+void WindowState::DisableZOrdering(aura::Window* window_on_top) {
+  ui::ZOrderLevel z_order = GetZOrdering();
+  if (z_order != ui::ZOrderLevel::kNormal && !IsPip()) {
     // |window_| is hidden first to avoid canceling fullscreen mode when it is
     // no longer always on top and gets added to default container. This avoids
     // sending redundant OnFullscreenStateChanged to the layout manager. The
@@ -336,7 +337,7 @@
     bool visible = window_->IsVisible();
     if (visible)
       window_->Hide();
-    window_->SetProperty(aura::client::kAlwaysOnTopKey, false);
+    window_->SetProperty(aura::client::kZOrderingKey, ui::ZOrderLevel::kNormal);
     // Technically it is possible that a |window_| could make itself
     // always_on_top really quickly. This is probably not a realistic case but
     // check if the two windows are in the same container just in case.
@@ -344,14 +345,14 @@
       window_->parent()->StackChildAbove(window_on_top, window_);
     if (visible)
       window_->Show();
-    cached_always_on_top_ = true;
+    cached_z_order_ = z_order;
   }
 }
 
-void WindowState::RestoreAlwaysOnTop() {
-  if (cached_always_on_top_) {
-    cached_always_on_top_ = false;
-    window_->SetProperty(aura::client::kAlwaysOnTopKey, true);
+void WindowState::RestoreZOrdering() {
+  if (cached_z_order_ != ui::ZOrderLevel::kNormal) {
+    window_->SetProperty(aura::client::kZOrderingKey, cached_z_order_);
+    cached_z_order_ = ui::ZOrderLevel::kNormal;
   }
 }
 
@@ -544,15 +545,15 @@
       unminimize_to_restore_bounds_(false),
       hide_shelf_when_fullscreen_(true),
       autohide_shelf_when_maximized_or_fullscreen_(false),
-      cached_always_on_top_(false),
+      cached_z_order_(ui::ZOrderLevel::kNormal),
       ignore_property_change_(false),
       current_state_(new DefaultState(ToWindowStateType(GetShowState()))) {
   window_->AddObserver(this);
   OnPrePipStateChange(WindowStateType::kDefault);
 }
 
-bool WindowState::GetAlwaysOnTop() const {
-  return window_->GetProperty(aura::client::kAlwaysOnTopKey);
+ui::ZOrderLevel WindowState::GetZOrdering() const {
+  return window_->GetProperty(aura::client::kZOrderingKey);
 }
 
 ui::WindowShowState WindowState::GetShowState() const {
diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h
index 5f80e8b..5e4f9a5 100644
--- a/ash/wm/window_state.h
+++ b/ash/wm/window_state.h
@@ -174,12 +174,12 @@
   // TODO(oshima): Change to use RESTORE event.
   void Restore();
 
-  // Caches, then disables always on top state and then stacks |window_| below
-  // |window_on_top| if a |window_| is currently in always on top state.
-  void DisableAlwaysOnTop(aura::Window* window_on_top);
+  // Caches, then disables z-ordering state and then stacks |window_| below
+  // |window_on_top| if |window_| currently has a special z-order.
+  void DisableZOrdering(aura::Window* window_on_top);
 
-  // Restores always on top state that a window might have cached.
-  void RestoreAlwaysOnTop();
+  // Restores the z-ordering state that a window might have cached.
+  void RestoreZOrdering();
 
   // Invoked when a WMevent occurs, which drives the internal
   // state machine.
@@ -376,8 +376,8 @@
 
   bool HasMaximumWidthOrHeight() const;
 
-  // Returns the window's current always_on_top state.
-  bool GetAlwaysOnTop() const;
+  // Returns the window's current z-ordering state.
+  ui::ZOrderLevel GetZOrdering() const;
 
   // Returns the window's current show state.
   ui::WindowShowState GetShowState() const;
@@ -452,7 +452,7 @@
   bool ignore_keyboard_bounds_change_ = false;
   bool hide_shelf_when_fullscreen_;
   bool autohide_shelf_when_maximized_or_fullscreen_;
-  bool cached_always_on_top_;
+  ui::ZOrderLevel cached_z_order_;
   bool allow_set_bounds_direct_ = false;
 
   // A property to save the ratio between snapped window width and display
diff --git a/ash/wm/workspace/phantom_window_controller.cc b/ash/wm/workspace/phantom_window_controller.cc
index 2ccf65a..59922fe 100644
--- a/ash/wm/workspace/phantom_window_controller.cc
+++ b/ash/wm/workspace/phantom_window_controller.cc
@@ -73,7 +73,7 @@
   // PhantomWindowController is used by FrameMaximizeButton to highlight the
   // launcher button. Put the phantom in the same window as the launcher so that
   // the phantom is visible.
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.name = "PhantomWindow";
   params.layer_type = ui::LAYER_SOLID_COLOR;
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc
index fa25925..5e61529 100644
--- a/ash/wm/workspace/workspace_layout_manager.cc
+++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -159,7 +159,7 @@
   backdrop_controller_->OnWindowAddedToLayout();
   WindowPositioner::RearrangeVisibleWindowOnShow(child);
   if (Shell::Get()->screen_pinning_controller()->IsPinned())
-    wm::GetWindowState(child)->DisableAlwaysOnTop(nullptr);
+    wm::GetWindowState(child)->DisableZOrdering(nullptr);
 }
 
 void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
@@ -309,8 +309,9 @@
 void WorkspaceLayoutManager::OnWindowPropertyChanged(aura::Window* window,
                                                      const void* key,
                                                      intptr_t old) {
-  if (key == aura::client::kAlwaysOnTopKey) {
-    if (window->GetProperty(aura::client::kAlwaysOnTopKey)) {
+  if (key == aura::client::kZOrderingKey) {
+    if (window->GetProperty(aura::client::kZOrderingKey) !=
+        ui::ZOrderLevel::kNormal) {
       aura::Window* container =
           root_window_controller_->always_on_top_controller()->GetContainer(
               window);
@@ -526,9 +527,9 @@
   for (aura::Window* window : windows) {
     wm::WindowState* window_state = wm::GetWindowState(window);
     if (active_desk_fullscreen_window)
-      window_state->DisableAlwaysOnTop(active_desk_fullscreen_window);
+      window_state->DisableZOrdering(active_desk_fullscreen_window);
     else
-      window_state->RestoreAlwaysOnTop();
+      window_state->RestoreZOrdering();
   }
 }
 
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index d6e5bb25..bc61c12 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -810,34 +810,37 @@
       CreateTestWindowInShellWithBounds(bounds));
   std::unique_ptr<aura::Window> always_on_top_window2(
       CreateTestWindowInShellWithBounds(bounds));
-  always_on_top_window1->SetProperty(aura::client::kAlwaysOnTopKey, true);
-  always_on_top_window2->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  always_on_top_window1->SetProperty(aura::client::kZOrderingKey,
+                                     ui::ZOrderLevel::kFloatingWindow);
+  always_on_top_window2->SetProperty(aura::client::kZOrderingKey,
+                                     ui::ZOrderLevel::kFloatingWindow);
   // Making a window fullscreen temporarily suspends always on top state.
   fullscreen_window->SetProperty(aura::client::kShowStateKey,
                                  ui::SHOW_STATE_FULLSCREEN);
-  EXPECT_FALSE(
-      always_on_top_window1->GetProperty(aura::client::kAlwaysOnTopKey));
-  EXPECT_FALSE(
-      always_on_top_window2->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            always_on_top_window1->GetProperty(aura::client::kZOrderingKey));
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            always_on_top_window2->GetProperty(aura::client::kZOrderingKey));
   EXPECT_NE(nullptr,
             wm::GetWindowForFullscreenModeForContext(fullscreen_window.get()));
 
   // Adding a new always-on-top window is not affected by fullscreen.
   std::unique_ptr<aura::Window> always_on_top_window3(
       CreateTestWindowInShellWithBounds(bounds));
-  always_on_top_window3->SetProperty(aura::client::kAlwaysOnTopKey, true);
-  EXPECT_TRUE(
-      always_on_top_window3->GetProperty(aura::client::kAlwaysOnTopKey));
+  always_on_top_window3->SetProperty(aura::client::kZOrderingKey,
+                                     ui::ZOrderLevel::kFloatingWindow);
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window3->GetProperty(aura::client::kZOrderingKey));
 
   // Making fullscreen window normal restores always on top windows.
   fullscreen_window->SetProperty(aura::client::kShowStateKey,
                                  ui::SHOW_STATE_NORMAL);
-  EXPECT_TRUE(
-      always_on_top_window1->GetProperty(aura::client::kAlwaysOnTopKey));
-  EXPECT_TRUE(
-      always_on_top_window2->GetProperty(aura::client::kAlwaysOnTopKey));
-  EXPECT_TRUE(
-      always_on_top_window3->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window1->GetProperty(aura::client::kZOrderingKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window2->GetProperty(aura::client::kZOrderingKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window3->GetProperty(aura::client::kZOrderingKey));
   EXPECT_EQ(nullptr,
             wm::GetWindowForFullscreenModeForContext(fullscreen_window.get()));
 }
@@ -853,22 +856,26 @@
   wm::WindowState* window_state = wm::GetWindowState(pip_window.get());
   const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
   window_state->OnWMEvent(&enter_pip);
-  pip_window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  pip_window->SetProperty(aura::client::kZOrderingKey,
+                          ui::ZOrderLevel::kFloatingWindow);
   EXPECT_TRUE(window_state->IsPip());
-  EXPECT_TRUE(pip_window->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            pip_window->GetProperty(aura::client::kZOrderingKey));
 
   // Making a window fullscreen temporarily suspends always on top state, but
   // should not do so for PIP.
   fullscreen_window->SetProperty(aura::client::kShowStateKey,
                                  ui::SHOW_STATE_FULLSCREEN);
-  EXPECT_TRUE(pip_window->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            pip_window->GetProperty(aura::client::kZOrderingKey));
   EXPECT_NE(nullptr,
             wm::GetWindowForFullscreenModeForContext(fullscreen_window.get()));
 
   // Making fullscreen window normal does not affect PIP.
   fullscreen_window->SetProperty(aura::client::kShowStateKey,
                                  ui::SHOW_STATE_NORMAL);
-  EXPECT_TRUE(pip_window->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            pip_window->GetProperty(aura::client::kZOrderingKey));
   EXPECT_EQ(nullptr,
             wm::GetWindowForFullscreenModeForContext(fullscreen_window.get()));
 }
@@ -882,32 +889,35 @@
       CreateTestWindowInShellWithBounds(bounds));
   std::unique_ptr<aura::Window> always_on_top_window2(
       CreateTestWindowInShellWithBounds(bounds));
-  always_on_top_window1->SetProperty(aura::client::kAlwaysOnTopKey, true);
-  always_on_top_window2->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  always_on_top_window1->SetProperty(aura::client::kZOrderingKey,
+                                     ui::ZOrderLevel::kFloatingWindow);
+  always_on_top_window2->SetProperty(aura::client::kZOrderingKey,
+                                     ui::ZOrderLevel::kFloatingWindow);
 
   // Making a window pinned temporarily suspends always on top state.
   const bool trusted = false;
   wm::PinWindow(pinned_window.get(), trusted);
-  EXPECT_FALSE(
-      always_on_top_window1->GetProperty(aura::client::kAlwaysOnTopKey));
-  EXPECT_FALSE(
-      always_on_top_window2->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            always_on_top_window1->GetProperty(aura::client::kZOrderingKey));
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            always_on_top_window2->GetProperty(aura::client::kZOrderingKey));
 
   // Adding a new always-on-top window also is affected by pinned mode.
   std::unique_ptr<aura::Window> always_on_top_window3(
       CreateTestWindowInShellWithBounds(bounds));
-  always_on_top_window3->SetProperty(aura::client::kAlwaysOnTopKey, true);
-  EXPECT_FALSE(
-      always_on_top_window3->GetProperty(aura::client::kAlwaysOnTopKey));
+  always_on_top_window3->SetProperty(aura::client::kZOrderingKey,
+                                     ui::ZOrderLevel::kFloatingWindow);
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            always_on_top_window3->GetProperty(aura::client::kZOrderingKey));
 
   // Making pinned window normal restores always on top windows.
   wm::GetWindowState(pinned_window.get())->Restore();
-  EXPECT_TRUE(
-      always_on_top_window1->GetProperty(aura::client::kAlwaysOnTopKey));
-  EXPECT_TRUE(
-      always_on_top_window2->GetProperty(aura::client::kAlwaysOnTopKey));
-  EXPECT_TRUE(
-      always_on_top_window3->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window1->GetProperty(aura::client::kZOrderingKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window2->GetProperty(aura::client::kZOrderingKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            always_on_top_window3->GetProperty(aura::client::kZOrderingKey));
 }
 
 TEST_F(WorkspaceLayoutManagerSoloTest, PinnedDoesNotSuspendAlwaysOnTopForPip) {
@@ -920,16 +930,19 @@
     wm::WindowState* window_state = wm::GetWindowState(pip_window.get());
     const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
     window_state->OnWMEvent(&enter_pip);
-    pip_window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+    pip_window->SetProperty(aura::client::kZOrderingKey,
+                            ui::ZOrderLevel::kFloatingWindow);
     EXPECT_TRUE(window_state->IsPip());
-    EXPECT_TRUE(pip_window->GetProperty(aura::client::kAlwaysOnTopKey));
+    EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+              pip_window->GetProperty(aura::client::kZOrderingKey));
   }
 
   // Making a window pinned temporarily suspends always on top state, except
   // for PIP.
   const bool trusted = false;
   wm::PinWindow(pinned_window.get(), trusted);
-  EXPECT_TRUE(pip_window->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            pip_window->GetProperty(aura::client::kZOrderingKey));
 
   // Adding a new PIP window should still end up always on top.
   std::unique_ptr<aura::Window> pip_window2(
@@ -938,15 +951,19 @@
     wm::WindowState* window_state = wm::GetWindowState(pip_window2.get());
     const wm::WMEvent enter_pip(wm::WM_EVENT_PIP);
     window_state->OnWMEvent(&enter_pip);
-    pip_window2->SetProperty(aura::client::kAlwaysOnTopKey, true);
+    pip_window2->SetProperty(aura::client::kZOrderingKey,
+                             ui::ZOrderLevel::kFloatingWindow);
     EXPECT_TRUE(window_state->IsPip());
-    EXPECT_TRUE(pip_window2->GetProperty(aura::client::kAlwaysOnTopKey));
+    EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+              pip_window2->GetProperty(aura::client::kZOrderingKey));
   }
 
   // Making pinned window normal should not affect existing PIP windows.
   wm::GetWindowState(pinned_window.get())->Restore();
-  EXPECT_TRUE(pip_window->GetProperty(aura::client::kAlwaysOnTopKey));
-  EXPECT_TRUE(pip_window2->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            pip_window->GetProperty(aura::client::kZOrderingKey));
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            pip_window2->GetProperty(aura::client::kZOrderingKey));
 }
 
 // Tests fullscreen window size during root window resize.
@@ -1060,7 +1077,8 @@
   std::unique_ptr<aura::Window> window(
       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4)));
   // window with AlwaysOnTop will be managed by BaseLayoutManager.
-  window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  window->SetProperty(aura::client::kZOrderingKey,
+                      ui::ZOrderLevel::kFloatingWindow);
   window->Show();
 
   Shelf* shelf = GetPrimaryShelf();
@@ -2019,7 +2037,8 @@
   std::unique_ptr<aura::Window> always_on_top_window(
       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4)));
   always_on_top_window->Show();
-  always_on_top_window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  always_on_top_window->SetProperty(aura::client::kZOrderingKey,
+                                    ui::ZOrderLevel::kFloatingWindow);
 
   aura::Window* always_on_top_container =
   always_on_top_controller->GetContainer(always_on_top_window.get());
@@ -2028,7 +2047,8 @@
   // at this moment.
   ASSERT_EQ(always_on_top_container->children().size(), 2U);
 
-  always_on_top_window->SetProperty(aura::client::kAlwaysOnTopKey, false);
+  always_on_top_window->SetProperty(aura::client::kZOrderingKey,
+                                    ui::ZOrderLevel::kNormal);
   // The backdrop window will be destroyed immediately after
   // |always_on_top_window| moves to the default container.
   EXPECT_TRUE(always_on_top_container->children().empty());
diff --git a/chrome/browser/chromeos/ui/idle_app_name_notification_view.cc b/chrome/browser/chromeos/ui/idle_app_name_notification_view.cc
index f91bb3f..c9990e06 100644
--- a/chrome/browser/chromeos/ui/idle_app_name_notification_view.cc
+++ b/chrome/browser/chromeos/ui/idle_app_name_notification_view.cc
@@ -65,7 +65,7 @@
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
   params.accept_events = false;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.delegate = delegate;
   params.bounds = bounds;
   ash_util::SetupWidgetInitParamsForContainer(
diff --git a/chrome/browser/chromeos/ui/kiosk_external_update_notification.cc b/chrome/browser/chromeos/ui/kiosk_external_update_notification.cc
index e05a253..3fc79b8 100644
--- a/chrome/browser/chromeos/ui/kiosk_external_update_notification.cc
+++ b/chrome/browser/chromeos/ui/kiosk_external_update_notification.cc
@@ -133,7 +133,7 @@
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
   params.accept_events = false;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.delegate = view_;
   params.bounds = bounds;
   // The notification is shown on the primary display.
diff --git a/chrome/browser/extensions/api/tabs/app_base_window.cc b/chrome/browser/extensions/api/tabs/app_base_window.cc
index 324756e..fd82bdb 100644
--- a/chrome/browser/extensions/api/tabs/app_base_window.cc
+++ b/chrome/browser/extensions/api/tabs/app_base_window.cc
@@ -105,12 +105,12 @@
   GetBaseWindow()->FlashFrame(flash);
 }
 
-bool AppBaseWindow::IsAlwaysOnTop() const {
-  return GetBaseWindow()->IsAlwaysOnTop();
+ui::ZOrderLevel AppBaseWindow::GetZOrderLevel() const {
+  return GetBaseWindow()->GetZOrderLevel();
 }
 
-void AppBaseWindow::SetAlwaysOnTop(bool always_on_top) {
-  GetBaseWindow()->SetAlwaysOnTop(always_on_top);
+void AppBaseWindow::SetZOrderLevel(ui::ZOrderLevel level) {
+  GetBaseWindow()->SetZOrderLevel(level);
 }
 
 NativeAppWindow* AppBaseWindow::GetBaseWindow() const {
diff --git a/chrome/browser/extensions/api/tabs/app_base_window.h b/chrome/browser/extensions/api/tabs/app_base_window.h
index d9ccfb5..7e17b85 100644
--- a/chrome/browser/extensions/api/tabs/app_base_window.h
+++ b/chrome/browser/extensions/api/tabs/app_base_window.h
@@ -45,8 +45,8 @@
   void Restore() override;
   void SetBounds(const gfx::Rect& bounds) override;
   void FlashFrame(bool flash) override;
-  bool IsAlwaysOnTop() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
 
   NativeAppWindow* GetBaseWindow() const;
 
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index 848a6d9..eb78de66 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -443,7 +443,9 @@
   result->SetBoolean(tabs_constants::kFocusedKey, window->IsActive());
   const Profile* profile = browser.profile();
   result->SetBoolean(tabs_constants::kIncognitoKey, profile->IsOffTheRecord());
-  result->SetBoolean(tabs_constants::kAlwaysOnTopKey, window->IsAlwaysOnTop());
+  result->SetBoolean(
+      tabs_constants::kAlwaysOnTopKey,
+      window->GetZOrderLevel() == ui::ZOrderLevel::kFloatingWindow);
 
   std::string window_state;
   if (window->IsMinimized()) {
diff --git a/chrome/browser/ui/ash/launcher/app_window_base.cc b/chrome/browser/ui/ash/launcher/app_window_base.cc
index 51d70fe..2805a7c2 100644
--- a/chrome/browser/ui/ash/launcher/app_window_base.cc
+++ b/chrome/browser/ui/ash/launcher/app_window_base.cc
@@ -103,11 +103,11 @@
   NOTREACHED();
 }
 
-bool AppWindowBase::IsAlwaysOnTop() const {
+ui::ZOrderLevel AppWindowBase::GetZOrderLevel() const {
   NOTREACHED();
-  return false;
+  return ui::ZOrderLevel::kNormal;
 }
 
-void AppWindowBase::SetAlwaysOnTop(bool always_on_top) {
+void AppWindowBase::SetZOrderLevel(ui::ZOrderLevel level) {
   NOTREACHED();
 }
diff --git a/chrome/browser/ui/ash/launcher/app_window_base.h b/chrome/browser/ui/ash/launcher/app_window_base.h
index a01e8bb..27db0892 100644
--- a/chrome/browser/ui/ash/launcher/app_window_base.h
+++ b/chrome/browser/ui/ash/launcher/app_window_base.h
@@ -58,8 +58,8 @@
   void Restore() override;
   void SetBounds(const gfx::Rect& bounds) override;
   void FlashFrame(bool flash) override;
-  bool IsAlwaysOnTop() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
 
  private:
   ash::ShelfID shelf_id_;
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
index ce6103d..30a4180 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa_browsertest.mm
@@ -35,7 +35,6 @@
 #import "ui/base/test/scoped_fake_nswindow_focus.h"
 #include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
 #import "ui/base/test/windowed_nsnotification_observer.h"
-#import "ui/gfx/mac/nswindow_frame_controls.h"
 
 using extensions::AppWindow;
 using extensions::PlatformAppBrowserTest;
@@ -46,6 +45,10 @@
 
 namespace {
 
+bool IsNSWindowFloating(NSWindow* window) {
+  return [window level] != NSNormalWindowLevel;
+}
+
 class NativeAppWindowCocoaBrowserTest : public PlatformAppBrowserTest {
  protected:
   NativeAppWindowCocoaBrowserTest() {}
@@ -239,7 +242,7 @@
             app_window->fullscreen_types_for_test());
   EXPECT_FALSE(window->IsFullscreen());
   EXPECT_FALSE([ns_window styleMask] & NSFullScreenWindowMask);
-  EXPECT_TRUE(gfx::IsNSWindowAlwaysOnTop(ns_window));
+  EXPECT_TRUE(IsNSWindowFloating(ns_window));
 
   [ns_window toggleFullScreen:nil];
   [waiter waitForEnterCount:1 exitCount:0];
@@ -247,7 +250,7 @@
               AppWindow::FULLSCREEN_TYPE_OS);
   EXPECT_TRUE(window->IsFullscreen());
   EXPECT_TRUE([ns_window styleMask] & NSFullScreenWindowMask);
-  EXPECT_FALSE(gfx::IsNSWindowAlwaysOnTop(ns_window));
+  EXPECT_FALSE(IsNSWindowFloating(ns_window));
 
   app_window->Restore();
   EXPECT_FALSE(window->IsFullscreenOrPending());
@@ -256,7 +259,7 @@
             app_window->fullscreen_types_for_test());
   EXPECT_FALSE(window->IsFullscreen());
   EXPECT_FALSE([ns_window styleMask] & NSFullScreenWindowMask);
-  EXPECT_TRUE(gfx::IsNSWindowAlwaysOnTop(ns_window));
+  EXPECT_TRUE(IsNSWindowFloating(ns_window));
 
   app_window->Fullscreen();
   EXPECT_TRUE(window->IsFullscreenOrPending());
@@ -265,7 +268,7 @@
               AppWindow::FULLSCREEN_TYPE_WINDOW_API);
   EXPECT_TRUE(window->IsFullscreen());
   EXPECT_TRUE([ns_window styleMask] & NSFullScreenWindowMask);
-  EXPECT_FALSE(gfx::IsNSWindowAlwaysOnTop(ns_window));
+  EXPECT_FALSE(IsNSWindowFloating(ns_window));
 
   [ns_window toggleFullScreen:nil];
   [waiter waitForEnterCount:2 exitCount:2];
@@ -273,7 +276,7 @@
             app_window->fullscreen_types_for_test());
   EXPECT_FALSE(window->IsFullscreen());
   EXPECT_FALSE([ns_window styleMask] & NSFullScreenWindowMask);
-  EXPECT_TRUE(gfx::IsNSWindowAlwaysOnTop(ns_window));
+  EXPECT_TRUE(IsNSWindowFloating(ns_window));
 }
 
 // Test Minimize, Restore combinations with their native equivalents.
diff --git a/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc b/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc
index 732ae8ec..14cd8d0 100644
--- a/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc
+++ b/chrome/browser/ui/startup/credential_provider_signin_dialog_win.cc
@@ -483,7 +483,7 @@
       std::make_unique<ChromeWebContentsHandler>());
   views::Widget::InitParams init_params(
       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
-  init_params.keep_on_top = true;
+  init_params.z_order = ui::ZOrderLevel::kFloatingWindow;
   views::WebDialogView* web_view = view.release();
   init_params.name = "GCPW";  // Used for debugging only.
   init_params.delegate = web_view;
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
index 1bb22d5..337c1fa 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
@@ -120,7 +120,8 @@
     if (IsFrameless())
       init_params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
   }
-  init_params.keep_on_top = create_params.always_on_top;
+  if (create_params.always_on_top)
+    init_params.z_order = ui::ZOrderLevel::kFloatingWindow;
   init_params.visible_on_all_workspaces =
       create_params.visible_on_all_workspaces;
 
@@ -205,8 +206,8 @@
   return ui::SHOW_STATE_NORMAL;
 }
 
-bool ChromeNativeAppWindowViews::IsAlwaysOnTop() const {
-  return widget()->IsAlwaysOnTop();
+ui::ZOrderLevel ChromeNativeAppWindowViews::GetZOrderLevel() const {
+  return widget()->GetZOrderLevel();
 }
 
 // views::WidgetDelegate implementation.
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h
index 50a2422c..9398263 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h
@@ -39,7 +39,7 @@
   // ui::BaseWindow implementation.
   gfx::Rect GetRestoredBounds() const override;
   ui::WindowShowState GetRestoredState() const override;
-  bool IsAlwaysOnTop() const override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
 
   // WidgetDelegate implementation.
   gfx::ImageSkia GetWindowAppIcon() override;
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc
index d97a1dfa..695e59c0 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.cc
@@ -105,8 +105,8 @@
   return GetRestorableState(restore_state);
 }
 
-bool ChromeNativeAppWindowViewsAura::IsAlwaysOnTop() const {
-  return widget()->IsAlwaysOnTop();
+ui::ZOrderLevel ChromeNativeAppWindowViewsAura::GetZOrderLevel() const {
+  return widget()->GetZOrderLevel();
 }
 
 void ChromeNativeAppWindowViewsAura::UpdateShape(
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h
index 229eeb1..07801e5b 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h
@@ -33,7 +33,7 @@
 
   // ui::BaseWindow implementation.
   ui::WindowShowState GetRestoredState() const override;
-  bool IsAlwaysOnTop() const override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
 
   // NativeAppWindow implementation.
   void UpdateShape(std::unique_ptr<ShapeRects> rects) override;
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
index 467a359..22609c21 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
@@ -212,8 +212,8 @@
   return GetRestorableState(restore_state);
 }
 
-bool ChromeNativeAppWindowViewsAuraAsh::IsAlwaysOnTop() const {
-  return widget()->IsAlwaysOnTop();
+ui::ZOrderLevel ChromeNativeAppWindowViewsAuraAsh::GetZOrderLevel() const {
+  return widget()->GetZOrderLevel();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
index d729967c..44649449 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
@@ -62,7 +62,7 @@
   // ui::BaseWindow:
   gfx::Rect GetRestoredBounds() const override;
   ui::WindowShowState GetRestoredState() const override;
-  bool IsAlwaysOnTop() const override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
 
   // views::ContextMenuController:
   void ShowContextMenuForViewImpl(views::View* source,
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 3b1c87a..f8788a2 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -707,11 +707,11 @@
   frame_->FlashFrame(flash);
 }
 
-bool BrowserView::IsAlwaysOnTop() const {
-  return false;
+ui::ZOrderLevel BrowserView::GetZOrderLevel() const {
+  return ui::ZOrderLevel::kNormal;
 }
 
-void BrowserView::SetAlwaysOnTop(bool always_on_top) {
+void BrowserView::SetZOrderLevel(ui::ZOrderLevel level) {
   // Not implemented for browser windows.
   NOTIMPLEMENTED();
 }
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index b2ddd63..8e779c3 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -290,8 +290,8 @@
   void Deactivate() override;
   bool IsActive() const override;
   void FlashFrame(bool flash) override;
-  bool IsAlwaysOnTop() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
   gfx::NativeWindow GetNativeWindow() const override;
   void SetTopControlsShownRatio(content::WebContents* web_contents,
                                 float ratio) override;
diff --git a/chrome/browser/ui/views/ime/ime_window_view.cc b/chrome/browser/ui/views/ime/ime_window_view.cc
index e6516d8..2a14d105 100644
--- a/chrome/browser/ui/views/ime/ime_window_view.cc
+++ b/chrome/browser/ui/views/ime/ime_window_view.cc
@@ -38,7 +38,7 @@
   params.delegate = this;
   params.wants_mouse_events_when_inactive = true;
   params.remove_standard_frame = false;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingWindow;
   params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
   params.visible_on_all_workspaces = false;
   params.bounds = bounds;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index cf4e45a2..5770870 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -233,7 +233,7 @@
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.bounds = CalculateAndUpdateWindowBounds();
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingWindow;
   params.visible_on_all_workspaces = true;
   params.remove_standard_frame = true;
   params.name = "PictureInPictureWindow";
diff --git a/chrome/browser/ui/views/screen_capture_notification_ui_views.cc b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
index 0d4e2304..e66ede2 100644
--- a/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
+++ b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
@@ -196,7 +196,7 @@
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.remove_standard_frame = true;
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.name = "ScreenCaptureNotificationUIViews";
 
 #if defined(OS_CHROMEOS)
@@ -208,7 +208,6 @@
 
   widget->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM);
   widget->Init(params);
-  widget->SetAlwaysOnTop(true);
 
   SetBackground(views::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
       ui::NativeTheme::kColorId_DialogBackground)));
diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc
index 83e16bc..7128fa3 100644
--- a/chrome/browser/ui/views/simple_message_box_views.cc
+++ b/chrome/browser/ui/views/simple_message_box_views.cc
@@ -162,7 +162,7 @@
   // attach to, move the dialog's widget on top so other windows do not obscure
   // it.
   if (!parent)
-    widget->SetAlwaysOnTop(true);
+    widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
 #endif
 
   widget->Show();
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index f05ba587..9c565ca 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -660,7 +660,8 @@
   std::unique_ptr<aura::Window> masked_window(
       aura::test::CreateTestWindowWithDelegate(
           &masked_window_delegate, 10, bounds, browser_window->parent()));
-  masked_window->SetProperty(aura::client::kAlwaysOnTopKey, true);
+  masked_window->SetProperty(aura::client::kZOrderingKey,
+                             ui::ZOrderLevel::kFloatingWindow);
   auto targeter = std::make_unique<aura::WindowTargeter>();
   targeter->SetInsets(gfx::Insets(0, bounds.width() - 10, 0, 0));
   masked_window->SetEventTargeter(std::move(targeter));
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 528215f..0b677ebd 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -2668,7 +2668,7 @@
 
   arrow_window = new views::Widget;
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.accept_events = false;
   params.bounds = gfx::Rect(g_drop_indicator_width, g_drop_indicator_height);
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc
index ca236a0..9352a52 100644
--- a/chrome/browser/ui/views/task_manager_view.cc
+++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -357,7 +357,7 @@
 
 void TaskManagerView::InitAlwaysOnTopState() {
   RetrieveSavedAlwaysOnTopState();
-  GetWidget()->SetAlwaysOnTop(is_always_on_top_);
+  GetWidget()->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
 }
 
 void TaskManagerView::ActivateSelectedTab() {
diff --git a/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc b/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc
index cca4fae..c8f9491 100644
--- a/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc
+++ b/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc
@@ -1193,7 +1193,7 @@
   // This propagation can cause views to change their size requirements.
   const gfx::Size preferred = popup_->GetContentsView()->GetPreferredSize();
   popup_->SetBounds(context_->ComputePopupBounds(popup_, preferred));
-  popup_->SetAlwaysOnTop(true);
+  popup_->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
 
   popup_->ShowInactive();
   delegate_->SetToastLocation(context_->GetToastLocation());
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
index de99715..ed36fbf 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
@@ -141,7 +141,7 @@
 
 void AssistantOptInDialog::AdjustWidgetInitParams(
     views::Widget::InitParams* params) {
-  params->keep_on_top = false;
+  params->z_order = ui::ZOrderLevel::kNormal;
 }
 
 void AssistantOptInDialog::GetDialogSize(gfx::Size* size) const {
diff --git a/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc b/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
index b3af756..ce3b17a 100644
--- a/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
+++ b/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
@@ -81,7 +81,8 @@
   dialog->ShowSystemDialog();
   EXPECT_FALSE(ash::ShellTestApi().IsSystemModalWindowOpen());
   aura::Window* window_to_test = dialog->dialog_window();
-  EXPECT_TRUE(window_to_test->GetProperty(aura::client::kAlwaysOnTopKey));
+  EXPECT_NE(ui::ZOrderLevel::kNormal,
+            window_to_test->GetProperty(aura::client::kZOrderingKey));
 }
 
 using SystemWebDialogTest = InProcessBrowserTest;
diff --git a/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc b/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
index 8e4841b0..0f96463 100644
--- a/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
+++ b/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
@@ -155,7 +155,7 @@
   views::Widget::InitParams extra_params;
   // If unparented and not modal, keep it on top (see header comment).
   if (!parent && GetDialogModalType() == ui::MODAL_TYPE_NONE)
-    extra_params.keep_on_top = true;
+    extra_params.z_order = ui::ZOrderLevel::kFloatingWindow;
   AdjustWidgetInitParams(&extra_params);
   dialog_window_ = chrome::ShowWebDialogWithParams(parent, browser_context,
                                                    this, &extra_params);
diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc
index 357352a..5ebb72d 100644
--- a/chrome/test/base/test_browser_window.cc
+++ b/chrome/test/base/test_browser_window.cc
@@ -64,8 +64,8 @@
   return false;
 }
 
-bool TestBrowserWindow::IsAlwaysOnTop() const {
-  return false;
+ui::ZOrderLevel TestBrowserWindow::GetZOrderLevel() const {
+  return ui::ZOrderLevel::kNormal;
 }
 
 gfx::NativeWindow TestBrowserWindow::GetNativeWindow() const {
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index 6499a88..818676e 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -54,8 +54,8 @@
   void Deactivate() override {}
   bool IsActive() const override;
   void FlashFrame(bool flash) override {}
-  bool IsAlwaysOnTop() const override;
-  void SetAlwaysOnTop(bool always_on_top) override {}
+  ui::ZOrderLevel GetZOrderLevel() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override {}
   gfx::NativeWindow GetNativeWindow() const override;
   void SetTopControlsShownRatio(content::WebContents* web_contents,
                                 float ratio) override;
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc
index ff704fe..1116ec2c 100644
--- a/components/exo/client_controlled_shell_surface.cc
+++ b/components/exo/client_controlled_shell_surface.cc
@@ -401,8 +401,10 @@
   if (!widget_)
     CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL);
 
-  widget_->GetNativeWindow()->SetProperty(aura::client::kAlwaysOnTopKey,
-                                          always_on_top);
+  widget_->GetNativeWindow()->SetProperty(aura::client::kZOrderingKey,
+                                          always_on_top
+                                              ? ui::ZOrderLevel::kFloatingWindow
+                                              : ui::ZOrderLevel::kNormal);
 }
 
 void ClientControlledShellSurface::SetImeBlocked(bool ime_blocked) {
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index aeb1b4a..d1b8eef 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -385,8 +385,13 @@
 
   // If |window_| was already visible then add it as a child window immediately.
   // As in OnVisibilityChanged, do not set a parent for sheets.
-  if (window_visible_ && ![window_ isSheet])
+  if (window_visible_ && ![window_ isSheet]) {
+    // Attaching a window to be a child window resets the window level, so
+    // restore the window level afterwards.
+    NSInteger window_level = [window_ level];
     [parent_->ns_window() addChildWindow:window_ ordered:NSWindowAbove];
+    [window_ setLevel:window_level];
+  }
 }
 
 void NativeWidgetNSWindowBridge::CreateSelectFileDialog(
@@ -958,8 +963,13 @@
 
     // Sheets don't need a parentWindow set, and setting one causes graphical
     // glitches (http://crbug.com/605098).
-    if (parent_ && ![window_ isSheet])
+    if (parent_ && ![window_ isSheet]) {
+      // Attaching a window to be a child window resets the window level, so
+      // restore the window level afterwards.
+      NSInteger window_level = [window_ level];
       [parent_->ns_window() addChildWindow:window_ ordered:NSWindowAbove];
+      [window_ setLevel:window_level];
+    }
   } else {
     ReleaseCapture();  // Capture on hidden windows is not permitted.
 
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc
index 987621e..2401ad8 100644
--- a/extensions/browser/app_window/app_window.cc
+++ b/extensions/browser/app_window/app_window.cc
@@ -730,7 +730,9 @@
        ExtensionsBrowserClient::Get()->IsScreensaverInDemoMode(
            extension_id())) &&
       !IntersectsWithTaskbar()) {
-    native_app_window_->SetAlwaysOnTop(always_on_top);
+    native_app_window_->SetZOrderLevel(always_on_top
+                                           ? ui::ZOrderLevel::kFloatingWindow
+                                           : ui::ZOrderLevel::kNormal);
   }
 
   OnNativeWindowChanged();
@@ -855,18 +857,19 @@
 
 void AppWindow::UpdateNativeAlwaysOnTop() {
   DCHECK(cached_always_on_top_);
-  bool is_on_top = native_app_window_->IsAlwaysOnTop();
+  bool is_on_top =
+      native_app_window_->GetZOrderLevel() == ui::ZOrderLevel::kFloatingWindow;
   bool fullscreen = IsFullscreen();
   bool intersects_taskbar = IntersectsWithTaskbar();
 
   if (is_on_top && (fullscreen || intersects_taskbar)) {
     // When entering fullscreen or overlapping the taskbar, ensure windows are
     // not always-on-top.
-    native_app_window_->SetAlwaysOnTop(false);
+    native_app_window_->SetZOrderLevel(ui::ZOrderLevel::kNormal);
   } else if (!is_on_top && !fullscreen && !intersects_taskbar) {
     // When exiting fullscreen and moving away from the taskbar, reinstate
     // always-on-top.
-    native_app_window_->SetAlwaysOnTop(true);
+    native_app_window_->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
   }
 }
 
diff --git a/extensions/browser/app_window/app_window_interactive_uitest.cc b/extensions/browser/app_window/app_window_interactive_uitest.cc
index 44b46e6..d3e2a6a 100644
--- a/extensions/browser/app_window/app_window_interactive_uitest.cc
+++ b/extensions/browser/app_window/app_window_interactive_uitest.cc
@@ -13,29 +13,35 @@
 class AppWindowTest : public PlatformAppBrowserTest {
  protected:
   void CheckAlwaysOnTopToFullscreen(AppWindow* window) {
-    ASSERT_TRUE(window->GetBaseWindow()->IsAlwaysOnTop());
+    ASSERT_EQ(ui::ZOrderLevel::kFloatingWindow,
+              window->GetBaseWindow()->GetZOrderLevel());
 
     // The always-on-top property should be temporarily disabled when the window
     // enters fullscreen.
     window->Fullscreen();
-    EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+    EXPECT_EQ(ui::ZOrderLevel::kNormal,
+              window->GetBaseWindow()->GetZOrderLevel());
 
     // From the API's point of view, the always-on-top property is enabled.
     EXPECT_TRUE(window->IsAlwaysOnTop());
 
     // The always-on-top property is restored when the window exits fullscreen.
     window->Restore();
-    EXPECT_TRUE(window->GetBaseWindow()->IsAlwaysOnTop());
+    EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+              window->GetBaseWindow()->GetZOrderLevel());
   }
 
   void CheckNormalToFullscreen(AppWindow* window) {
     // If the always-on-top property is false, it should remain this way when
     // entering and exiting fullscreen mode.
-    ASSERT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+    ASSERT_EQ(ui::ZOrderLevel::kNormal,
+              window->GetBaseWindow()->GetZOrderLevel());
     window->Fullscreen();
-    EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+    EXPECT_EQ(ui::ZOrderLevel::kNormal,
+              window->GetBaseWindow()->GetZOrderLevel());
     window->Restore();
-    EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+    EXPECT_EQ(ui::ZOrderLevel::kNormal,
+              window->GetBaseWindow()->GetZOrderLevel());
   }
 
   void CheckFullscreenToAlwaysOnTop(AppWindow* window) {
@@ -44,14 +50,16 @@
     // Now enable always-on-top at runtime and ensure the property does not get
     // applied immediately because the window is in fullscreen mode.
     window->SetAlwaysOnTop(true);
-    EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+    EXPECT_EQ(ui::ZOrderLevel::kNormal,
+              window->GetBaseWindow()->GetZOrderLevel());
 
     // From the API's point of view, the always-on-top property is enabled.
     EXPECT_TRUE(window->IsAlwaysOnTop());
 
     // Ensure the always-on-top property is applied when exiting fullscreen.
     window->Restore();
-    EXPECT_TRUE(window->GetBaseWindow()->IsAlwaysOnTop());
+    EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+              window->GetBaseWindow()->GetZOrderLevel());
   }
 };
 
@@ -147,13 +155,15 @@
   ASSERT_TRUE(window);
 
   EXPECT_TRUE(window->GetBaseWindow()->IsFullscreenOrPending());
-  EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            window->GetBaseWindow()->GetZOrderLevel());
 
   // From the API's point of view, the always-on-top property is enabled.
   EXPECT_TRUE(window->IsAlwaysOnTop());
 
   window->Restore();
-  EXPECT_TRUE(window->GetBaseWindow()->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow,
+            window->GetBaseWindow()->GetZOrderLevel());
 
   CloseAppWindow(window);
 }
@@ -174,13 +184,16 @@
 
   // Disable always-on-top while in fullscreen mode.
   window->Fullscreen();
-  EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            window->GetBaseWindow()->GetZOrderLevel());
   window->SetAlwaysOnTop(false);
-  EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            window->GetBaseWindow()->GetZOrderLevel());
 
   // Ensure that always-on-top remains disabled.
   window->Restore();
-  EXPECT_FALSE(window->GetBaseWindow()->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kNormal,
+            window->GetBaseWindow()->GetZOrderLevel());
 
   CloseAppWindow(window);
 }
diff --git a/extensions/components/native_app_window/native_app_window_views.cc b/extensions/components/native_app_window/native_app_window_views.cc
index 35aa2fb8..f1b3c80 100644
--- a/extensions/components/native_app_window/native_app_window_views.cc
+++ b/extensions/components/native_app_window/native_app_window_views.cc
@@ -63,7 +63,8 @@
   // Stub implementation. See also ChromeNativeAppWindowViews.
   views::Widget::InitParams init_params(views::Widget::InitParams::TYPE_WINDOW);
   init_params.delegate = this;
-  init_params.keep_on_top = create_params.always_on_top;
+  if (create_params.always_on_top)
+    init_params.z_order = ui::ZOrderLevel::kFloatingWindow;
   widget_->Init(init_params);
   widget_->CenterWindow(
       create_params.GetInitialWindowBounds(gfx::Insets()).size());
@@ -163,13 +164,13 @@
   widget_->FlashFrame(flash);
 }
 
-bool NativeAppWindowViews::IsAlwaysOnTop() const {
+ui::ZOrderLevel NativeAppWindowViews::GetZOrderLevel() const {
   // Stub implementation. See also ChromeNativeAppWindowViews.
-  return widget_->IsAlwaysOnTop();
+  return widget_->GetZOrderLevel();
 }
 
-void NativeAppWindowViews::SetAlwaysOnTop(bool always_on_top) {
-  widget_->SetAlwaysOnTop(always_on_top);
+void NativeAppWindowViews::SetZOrderLevel(ui::ZOrderLevel order) {
+  widget_->SetZOrderLevel(order);
 }
 
 gfx::NativeView NativeAppWindowViews::GetHostView() const {
diff --git a/extensions/components/native_app_window/native_app_window_views.h b/extensions/components/native_app_window/native_app_window_views.h
index a537c42..7682a6ae 100644
--- a/extensions/components/native_app_window/native_app_window_views.h
+++ b/extensions/components/native_app_window/native_app_window_views.h
@@ -85,8 +85,8 @@
   void Restore() override;
   void SetBounds(const gfx::Rect& bounds) override;
   void FlashFrame(bool flash) override;
-  bool IsAlwaysOnTop() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
 
   // WidgetDelegate implementation.
   void OnWidgetMove() override;
diff --git a/extensions/shell/browser/shell_native_app_window.cc b/extensions/shell/browser/shell_native_app_window.cc
index 33b3bf5..dd836d3 100644
--- a/extensions/shell/browser/shell_native_app_window.cc
+++ b/extensions/shell/browser/shell_native_app_window.cc
@@ -72,11 +72,11 @@
   NOTIMPLEMENTED();
 }
 
-bool ShellNativeAppWindow::IsAlwaysOnTop() const {
-  return false;
+ui::ZOrderLevel ShellNativeAppWindow::GetZOrderLevel() const {
+  return ui::ZOrderLevel::kNormal;
 }
 
-void ShellNativeAppWindow::SetAlwaysOnTop(bool always_on_top) {
+void ShellNativeAppWindow::SetZOrderLevel(ui::ZOrderLevel level) {
   NOTIMPLEMENTED();
 }
 
diff --git a/extensions/shell/browser/shell_native_app_window.h b/extensions/shell/browser/shell_native_app_window.h
index a00a052..b25bafb3 100644
--- a/extensions/shell/browser/shell_native_app_window.h
+++ b/extensions/shell/browser/shell_native_app_window.h
@@ -32,8 +32,8 @@
   void Minimize() override;
   void Restore() override;
   void FlashFrame(bool flash) override;
-  bool IsAlwaysOnTop() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
 
   // web_modal::ModalDialogHost overrides:
   gfx::NativeView GetHostView() const override;
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc
index f2024e6..5826c67 100644
--- a/ui/aura/client/aura_constants.cc
+++ b/ui/aura/client/aura_constants.cc
@@ -12,6 +12,7 @@
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::UnguessableToken*)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::string16*)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, ui::ModalType)
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, ui::ZOrderLevel)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::ImageSkia*)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::NativeViewAccessible)
 DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::Rect*)
@@ -39,7 +40,6 @@
                              kAccessibilityTouchExplorationPassThrough,
                              false)
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kActivateOnPointerKey, true)
-DEFINE_UI_CLASS_PROPERTY_KEY(bool, kAlwaysOnTopKey, false)
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kAnimationsDisabledKey, false)
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kAppIconKey, nullptr)
 DEFINE_UI_CLASS_PROPERTY_KEY(int, kAppType, 0)
@@ -79,6 +79,9 @@
 DEFINE_UI_CLASS_PROPERTY_KEY(int, kTopViewInset, 0)
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kWindowIconKey, nullptr)
 DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowCornerRadiusKey, -1)
+DEFINE_UI_CLASS_PROPERTY_KEY(ui::ZOrderLevel,
+                             kZOrderingKey,
+                             ui::ZOrderLevel::kNormal)
 
 }  // namespace client
 }  // namespace aura
diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h
index f99e4f1..0991ada 100644
--- a/ui/aura/client/aura_constants.h
+++ b/ui/aura/client/aura_constants.h
@@ -47,9 +47,6 @@
 // pointer down event occurs on them.
 AURA_EXPORT extern const WindowProperty<bool>* const kActivateOnPointerKey;
 
-// A property key to store always-on-top flag.
-AURA_EXPORT extern const WindowProperty<bool>* const kAlwaysOnTopKey;
-
 // A property key to store whether animations are disabled for the window. Type
 // of value is an int.
 AURA_EXPORT extern const WindowProperty<bool>* const kAnimationsDisabledKey;
@@ -168,6 +165,9 @@
 // Default is -1, meaning "unspecified". 0 Ensures corners are square.
 AURA_EXPORT extern const WindowProperty<int>* const kWindowCornerRadiusKey;
 
+// A property key to store the z-ordering.
+AURA_EXPORT extern const WindowProperty<ui::ZOrderLevel>* const kZOrderingKey;
+
 // Alphabetical sort.
 
 }  // namespace client
diff --git a/ui/base/base_window.h b/ui/base/base_window.h
index bbb7e28..17192330 100644
--- a/ui/base/base_window.h
+++ b/ui/base/base_window.h
@@ -7,7 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "build/build_config.h"
-#include "ui/base/ui_base_types.h"  // WindowShowState
+#include "ui/base/ui_base_types.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace gfx {
@@ -88,12 +88,11 @@
   // Set |flash| to true to initiate flashing, false to stop flashing.
   virtual void FlashFrame(bool flash) = 0;
 
-  // Returns true if a window is set to be always on top.
-  virtual bool IsAlwaysOnTop() const = 0;
+  // Returns the z-order level of the window.
+  virtual ZOrderLevel GetZOrderLevel() const = 0;
 
-  // If set to true, the window will stay on top of other windows which do not
-  // have this flag enabled.
-  virtual void SetAlwaysOnTop(bool always_on_top) = 0;
+  // Sets the z-order level of the window.
+  virtual void SetZOrderLevel(ZOrderLevel order) = 0;
 };
 
 }  // namespace ui
diff --git a/ui/base/ui_base_types.h b/ui/base/ui_base_types.h
index 5309805f..efd565f 100644
--- a/ui/base/ui_base_types.h
+++ b/ui/base/ui_base_types.h
@@ -39,6 +39,38 @@
   MODAL_TYPE_SYSTEM = 3   // Window is modal to all other windows.
 };
 
+// The class of window and its overall z-order. Not all platforms provide this
+// level of z-order granularity. For such platforms, which only provide a
+// distinction between "normal" and "always on top" windows, any of the values
+// here that aren't |kNormal| are treated equally as "always on top".
+enum class ZOrderLevel {
+  // The default level for windows.
+  kNormal = 0,
+
+  // A "floating" window z-ordered above other normal windows.
+  //
+  // Note this is the traditional _desktop_ concept of a "floating window".
+  // Android has a concept of "freeform window mode" in which apps are presented
+  // in separate "floating" windows that can be moved and resized by the user.
+  // That's not what this is.
+  kFloatingWindow,
+
+  // UI elements are used to annotate positions on the screen, and thus must
+  // appear above floating windows.
+  kFloatingUIElement,
+
+  // There have been horrific security decisions that have been made on the web
+  // platform that are now expected behavior and cannot easily be changed. The
+  // only way to mitigate problems with these decisions is to inform the user by
+  // presenting them with a message that they are in a state that they might not
+  // expect, and this message must be presented in a UI that cannot be
+  // interfered with or covered up. Thus this level for Security UI that must be
+  // Z-ordered in front of everything else. Note that this is useful in
+  // situations where window modality (as in ModalType) cannot or should not be
+  // used.
+  kSecuritySurface,
+};
+
 // TODO(varunjain): Remove MENU_SOURCE_NONE (crbug.com/250964)
 // A Java counterpart will be generated for this enum.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.ui.base
diff --git a/ui/gfx/mac/nswindow_frame_controls.h b/ui/gfx/mac/nswindow_frame_controls.h
index 61c6331..d58eecae 100644
--- a/ui/gfx/mac/nswindow_frame_controls.h
+++ b/ui/gfx/mac/nswindow_frame_controls.h
@@ -17,16 +17,6 @@
 GFX_EXPORT void SetNSWindowCanFullscreen(NSWindow* window,
                                          bool allow_fullscreen);
 
-// Returns whether the window is always-on-top.
-GFX_EXPORT bool IsNSWindowAlwaysOnTop(NSWindow* window);
-
-// Sets whether the window is always-on-top. This also sets
-// NSWindowCollectionBehaviorManaged because by default always-on-top windows
-// are NSWindowCollectionBehaviorTransient which means they will not appear in
-// Expose and cannot be moved between workspaces.
-GFX_EXPORT void SetNSWindowAlwaysOnTop(NSWindow* window,
-                                       bool always_on_top);
-
 // Sets whether the window appears on all workspaces.
 GFX_EXPORT void SetNSWindowVisibleOnAllWorkspaces(NSWindow* window,
                                                   bool always_visible);
diff --git a/ui/gfx/mac/nswindow_frame_controls.mm b/ui/gfx/mac/nswindow_frame_controls.mm
index fc63d29d..f06af3e 100644
--- a/ui/gfx/mac/nswindow_frame_controls.mm
+++ b/ui/gfx/mac/nswindow_frame_controls.mm
@@ -21,13 +21,6 @@
   [window setStyleMask:style_mask];
 }
 
-// Returns the level for windows that are configured to be always on top.
-// This is not a constant because NSFloatingWindowLevel is a macro defined
-// as a function call.
-NSInteger AlwaysOnTopWindowLevel() {
-  return NSFloatingWindowLevel;
-}
-
 }  // namespace
 
 namespace gfx {
@@ -43,23 +36,6 @@
   [window setCollectionBehavior:behavior];
 }
 
-bool IsNSWindowAlwaysOnTop(NSWindow* window) {
-  return [window level] == AlwaysOnTopWindowLevel();
-}
-
-void SetNSWindowAlwaysOnTop(NSWindow* window,
-                            bool always_on_top) {
-  [window setLevel:(always_on_top ? AlwaysOnTopWindowLevel()
-                                  : NSNormalWindowLevel)];
-  // Since always-on-top windows have a higher window level than
-  // NSNormalWindowLevel, they will default to
-  // NSWindowCollectionBehaviorTransient. Set the value explicitly here to match
-  // normal windows.
-  NSWindowCollectionBehavior behavior =
-      [window collectionBehavior] | NSWindowCollectionBehaviorManaged;
-  [window setCollectionBehavior:behavior];
-}
-
 void SetNSWindowVisibleOnAllWorkspaces(NSWindow* window, bool always_visible) {
   NSWindowCollectionBehavior behavior = [window collectionBehavior];
   if (always_visible)
diff --git a/ui/message_center/views/message_popup_view.cc b/ui/message_center/views/message_popup_view.cc
index 686fc87..0751647 100644
--- a/ui/message_center/views/message_popup_view.cc
+++ b/ui/message_center/views/message_popup_view.cc
@@ -105,7 +105,7 @@
 
 void MessagePopupView::Show() {
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingWindow;
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   // Make the widget explicitly activatable as TYPE_POPUP is not activatable by
   // default but we need focus for the inline reply textarea.
diff --git a/ui/views/corewm/tooltip_aura.cc b/ui/views/corewm/tooltip_aura.cc
index 9ff7e6a..2279c53 100644
--- a/ui/views/corewm/tooltip_aura.cc
+++ b/ui/views/corewm/tooltip_aura.cc
@@ -58,7 +58,7 @@
   params.type = views::Widget::InitParams::TYPE_TOOLTIP;
   params.context = tooltip_window;
   DCHECK(params.context);
-  params.keep_on_top = true;
+  params.z_order = ui::ZOrderLevel::kFloatingUIElement;
   params.accept_events = false;
   params.bounds = bounds;
   if (CanUseTranslucentTooltipWidget())
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 8556940..32ea162f 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -86,7 +86,7 @@
                                           const gfx::Rect& bounds,
                                           bool full_screen,
                                           bool is_menu,
-                                          bool root_is_always_on_top) {
+                                          ui::ZOrderLevel root_z_order) {
     // This instance will get deleted when the widget is destroyed.
     DesktopNativeWidgetTopLevelHandler* top_level_handler =
         new DesktopNativeWidgetTopLevelHandler;
@@ -103,7 +103,7 @@
     init_params.activatable = full_screen ?
         Widget::InitParams::ACTIVATABLE_YES :
         Widget::InitParams::ACTIVATABLE_NO;
-    init_params.keep_on_top = root_is_always_on_top;
+    init_params.z_order = root_z_order;
 
     // This widget instance will get deleted when the window is
     // destroyed.
@@ -193,14 +193,14 @@
     bool is_menu = window->type() == aura::client::WINDOW_TYPE_MENU;
 
     if (is_fullscreen || is_menu) {
-      bool root_is_always_on_top = false;
+      ui::ZOrderLevel root_z_order = ui::ZOrderLevel::kNormal;
       internal::NativeWidgetPrivate* native_widget =
           DesktopNativeWidgetAura::ForWindow(root_window_);
       if (native_widget)
-        root_is_always_on_top = native_widget->IsAlwaysOnTop();
+        root_z_order = native_widget->GetZOrderLevel();
 
       return DesktopNativeWidgetTopLevelHandler::CreateParentWindow(
-          window, bounds, is_fullscreen, is_menu, root_is_always_on_top);
+          window, bounds, is_fullscreen, is_menu, root_z_order);
     }
     return root_window_;
   }
@@ -814,13 +814,15 @@
   return content_window_ && desktop_window_tree_host_->IsActive();
 }
 
-void DesktopNativeWidgetAura::SetAlwaysOnTop(bool always_on_top) {
+void DesktopNativeWidgetAura::SetZOrderLevel(ui::ZOrderLevel order) {
   if (content_window_)
-    desktop_window_tree_host_->SetAlwaysOnTop(always_on_top);
+    desktop_window_tree_host_->SetZOrderLevel(order);
 }
 
-bool DesktopNativeWidgetAura::IsAlwaysOnTop() const {
-  return content_window_ && desktop_window_tree_host_->IsAlwaysOnTop();
+ui::ZOrderLevel DesktopNativeWidgetAura::GetZOrderLevel() const {
+  if (content_window_)
+    return desktop_window_tree_host_->GetZOrderLevel();
+  return ui::ZOrderLevel::kNormal;
 }
 
 void DesktopNativeWidgetAura::SetVisibleOnAllWorkspaces(bool always_visible) {
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index 5d45002..a87d551 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -151,8 +151,8 @@
   void Activate() override;
   void Deactivate() override;
   bool IsActive() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
-  bool IsAlwaysOnTop() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
   void SetVisibleOnAllWorkspaces(bool always_visible) override;
   bool IsVisibleOnAllWorkspaces() const override;
   void Maximize() override;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host.h b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index eff14bc..cf2aa407 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -130,8 +130,8 @@
 
   virtual bool HasCapture() const = 0;
 
-  virtual void SetAlwaysOnTop(bool always_on_top) = 0;
-  virtual bool IsAlwaysOnTop() const = 0;
+  virtual void SetZOrderLevel(ui::ZOrderLevel order) = 0;
+  virtual ui::ZOrderLevel GetZOrderLevel() const = 0;
 
   virtual void SetVisibleOnAllWorkspaces(bool always_visible) = 0;
   virtual bool IsVisibleOnAllWorkspaces() const = 0;
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 ac7c92d..1c9fba3 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
@@ -345,14 +345,14 @@
   return platform_window()->HasCapture();
 }
 
-void DesktopWindowTreeHostPlatform::SetAlwaysOnTop(bool always_on_top) {
+void DesktopWindowTreeHostPlatform::SetZOrderLevel(ui::ZOrderLevel order) {
   // TODO: needs PlatformWindow support.
   NOTIMPLEMENTED_LOG_ONCE();
 }
 
-bool DesktopWindowTreeHostPlatform::IsAlwaysOnTop() const {
+ui::ZOrderLevel DesktopWindowTreeHostPlatform::GetZOrderLevel() const {
   // TODO: needs PlatformWindow support.
-  return false;
+  return ui::ZOrderLevel::kNormal;
 }
 
 void DesktopWindowTreeHostPlatform::SetVisibleOnAllWorkspaces(
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 02f30ef..8760639 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
@@ -59,8 +59,8 @@
   bool IsMaximized() const override;
   bool IsMinimized() const override;
   bool HasCapture() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
-  bool IsAlwaysOnTop() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
   void SetVisibleOnAllWorkspaces(bool always_visible) override;
   bool IsVisibleOnAllWorkspaces() const override;
   bool SetWindowTitle(const base::string16& title) override;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index eed8b61..7e31a1c1 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -133,6 +133,7 @@
 
   remove_standard_frame_ = params.remove_standard_frame;
   has_non_client_view_ = Widget::RequiresNonClientView(params.type);
+  z_order_ = params.EffectiveZOrderLevel();
 
   // We don't have an HWND yet, so scale relative to the nearest screen.
   gfx::Rect pixel_bounds =
@@ -367,12 +368,16 @@
   return message_handler_->HasCapture();
 }
 
-void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) {
-  message_handler_->SetAlwaysOnTop(always_on_top);
+void DesktopWindowTreeHostWin::SetZOrderLevel(ui::ZOrderLevel order) {
+  z_order_ = order;
+  // Emulate the multiple window levels provided by other platforms by
+  // collapsing the z-order enum into kNormal = normal, everything else = always
+  // on top.
+  message_handler_->SetAlwaysOnTop(order != ui::ZOrderLevel::kNormal);
 }
 
-bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const {
-  return message_handler_->IsAlwaysOnTop();
+ui::ZOrderLevel DesktopWindowTreeHostWin::GetZOrderLevel() const {
+  return z_order_;
 }
 
 void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 8ac960b..335db0db 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -95,8 +95,8 @@
   bool IsMaximized() const override;
   bool IsMinimized() const override;
   bool HasCapture() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
-  bool IsAlwaysOnTop() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
   void SetVisibleOnAllWorkspaces(bool always_visible) override;
   bool IsVisibleOnAllWorkspaces() const override;
   bool SetWindowTitle(const base::string16& title) override;
@@ -307,6 +307,10 @@
   // become activated.
   bool wants_mouse_events_when_inactive_ = false;
 
+  // The z-order level of the window; the window exhibits "always on top"
+  // behavior if > 0.
+  ui::ZOrderLevel z_order_ = ui::ZOrderLevel::kNormal;
+
   DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostWin);
 };
 
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 efe92fed..3fb42bd 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
@@ -907,13 +907,17 @@
   return g_current_capture == this;
 }
 
-void DesktopWindowTreeHostX11::SetAlwaysOnTop(bool always_on_top) {
-  is_always_on_top_ = always_on_top;
-  SetWMSpecState(always_on_top, gfx::GetAtom("_NET_WM_STATE_ABOVE"), x11::None);
+void DesktopWindowTreeHostX11::SetZOrderLevel(ui::ZOrderLevel order) {
+  z_order_ = order;
+  // Emulate the multiple window levels provided by other platforms by
+  // collapsing the z-order enum into kNormal = normal, everything else = always
+  // on top.
+  SetWMSpecState(order != ui::ZOrderLevel::kNormal,
+                 gfx::GetAtom("_NET_WM_STATE_ABOVE"), x11::None);
 }
 
-bool DesktopWindowTreeHostX11::IsAlwaysOnTop() const {
-  return is_always_on_top_;
+ui::ZOrderLevel DesktopWindowTreeHostX11::GetZOrderLevel() const {
+  return z_order_;
 }
 
 void DesktopWindowTreeHostX11::SetVisible(bool visible) {
@@ -1598,8 +1602,8 @@
 
   // If the window should stay on top of other windows, add the
   // _NET_WM_STATE_ABOVE property.
-  is_always_on_top_ = params.keep_on_top;
-  if (is_always_on_top_)
+  z_order_ = params.EffectiveZOrderLevel();
+  if (z_order_ != ui::ZOrderLevel::kNormal)
     window_properties_.insert(gfx::GetAtom("_NET_WM_STATE_ABOVE"));
 
   workspace_ = base::nullopt;
@@ -1809,8 +1813,12 @@
   // handle window manager initiated fullscreen. In particular, Chrome needs to
   // do preprocessing before the x window's fullscreen state is toggled.
 
-  is_always_on_top_ = ui::HasWMSpecProperty(
-      window_properties_, gfx::GetAtom("_NET_WM_STATE_ABOVE"));
+  // Which z-level is the map of the "always on top" bit? This choice is a bit
+  // arbitrary.
+  z_order_ = ui::HasWMSpecProperty(window_properties_,
+                                   gfx::GetAtom("_NET_WM_STATE_ABOVE"))
+                 ? ui::ZOrderLevel::kFloatingWindow
+                 : ui::ZOrderLevel::kNormal;
 
   // 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
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 4717440a..f9027c3 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
@@ -131,8 +131,8 @@
   bool IsMaximized() const override;
   bool IsMinimized() const override;
   bool HasCapture() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
-  bool IsAlwaysOnTop() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
   void SetVisibleOnAllWorkspaces(bool always_visible) override;
   bool IsVisibleOnAllWorkspaces() const override;
   bool SetWindowTitle(const base::string16& title) override;
@@ -357,8 +357,9 @@
   // Whether |xwindow_| was requested to be fullscreen via SetFullscreen().
   bool is_fullscreen_ = false;
 
-  // True if the window should stay on top of most other windows.
-  bool is_always_on_top_ = false;
+  // The z-order level of the window; the window exhibits "always on top"
+  // behavior if > 0.
+  ui::ZOrderLevel z_order_ = ui::ZOrderLevel::kNormal;
 
   // True if the window has title-bar / borders provided by the window manager.
   bool use_native_frame_ = false;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index cab2854..f506f99 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -205,8 +205,8 @@
             ->set_parent_controls_visibility(true);
       }
     }
-    // SetAlwaysOnTop before SetParent so that always-on-top container is used.
-    SetAlwaysOnTop(params.keep_on_top);
+    // SetZOrderLevel before SetParent so that always-on-top container is used.
+    SetZOrderLevel(params.EffectiveZOrderLevel());
 
     // Make sure we have a real |window_bounds|.
     aura::Window* parent_or_context = parent ? parent : context;
@@ -611,13 +611,16 @@
   return window_ && wm::IsActiveWindow(window_);
 }
 
-void NativeWidgetAura::SetAlwaysOnTop(bool on_top) {
+void NativeWidgetAura::SetZOrderLevel(ui::ZOrderLevel order) {
   if (window_)
-    window_->SetProperty(aura::client::kAlwaysOnTopKey, on_top);
+    window_->SetProperty(aura::client::kZOrderingKey, order);
 }
 
-bool NativeWidgetAura::IsAlwaysOnTop() const {
-  return window_ && window_->GetProperty(aura::client::kAlwaysOnTopKey);
+ui::ZOrderLevel NativeWidgetAura::GetZOrderLevel() const {
+  if (window_)
+    return window_->GetProperty(aura::client::kZOrderingKey);
+
+  return ui::ZOrderLevel::kNormal;
 }
 
 void NativeWidgetAura::SetVisibleOnAllWorkspaces(bool always_visible) {
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index 686840f..d9bfb45d 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -116,8 +116,8 @@
   void Activate() override;
   void Deactivate() override;
   bool IsActive() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
-  bool IsAlwaysOnTop() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
   void SetVisibleOnAllWorkspaces(bool always_visible) override;
   bool IsVisibleOnAllWorkspaces() const override;
   void Maximize() override;
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h
index c03b37c..0c55708 100644
--- a/ui/views/widget/native_widget_mac.h
+++ b/ui/views/widget/native_widget_mac.h
@@ -133,8 +133,8 @@
   void Activate() override;
   void Deactivate() override;
   bool IsActive() const override;
-  void SetAlwaysOnTop(bool always_on_top) override;
-  bool IsAlwaysOnTop() const override;
+  void SetZOrderLevel(ui::ZOrderLevel order) override;
+  ui::ZOrderLevel GetZOrderLevel() const override;
   void SetVisibleOnAllWorkspaces(bool always_visible) override;
   bool IsVisibleOnAllWorkspaces() const override;
   void Maximize() override;
@@ -233,6 +233,8 @@
   // Internal name.
   std::string name_;
 
+  Widget::InitParams::Type type_;
+
   DISALLOW_COPY_AND_ASSIGN(NativeWidgetMac);
 };
 
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index 4a441b8..02b118b 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/no_destructor.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/crash/core/common/crash_key.h"
@@ -25,7 +26,6 @@
 #include "ui/events/gestures/gesture_recognizer_impl_mac.h"
 #include "ui/gfx/font_list.h"
 #import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/gfx/mac/nswindow_frame_controls.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/native_theme/native_theme_mac.h"
 #import "ui/views/cocoa/drag_drop_client_mac.h"
@@ -37,6 +37,7 @@
 using remote_cocoa::mojom::WindowVisibilityState;
 
 namespace views {
+
 namespace {
 
 base::LazyInstance<ui::GestureRecognizerImplMac>::Leaky
@@ -65,6 +66,42 @@
   return NSBorderlessWindowMask;
 }
 
+CGWindowLevel CGWindowLevelForZOrderLevel(ui::ZOrderLevel level,
+                                          Widget::InitParams::Type type) {
+  switch (level) {
+    case ui::ZOrderLevel::kNormal:
+      return kCGNormalWindowLevel;
+    case ui::ZOrderLevel::kFloatingWindow:
+      if (type == Widget::InitParams::TYPE_MENU)
+        return kCGPopUpMenuWindowLevel;
+      else
+        return kCGFloatingWindowLevel;
+    case ui::ZOrderLevel::kFloatingUIElement:
+      if (type == Widget::InitParams::TYPE_DRAG)
+        return kCGDraggingWindowLevel;
+      else
+        return kCGStatusWindowLevel;
+    case ui::ZOrderLevel::kSecuritySurface:
+      return kCGScreenSaverWindowLevel - 1;
+  }
+}
+
+ui::ZOrderLevel ZOrderLevelForCGWindowLevel(CGWindowLevel level) {
+  switch (level) {
+    case kCGNormalWindowLevel:
+      return ui::ZOrderLevel::kNormal;
+    case kCGFloatingWindowLevel:
+    case kCGPopUpMenuWindowLevel:
+    default:
+      return ui::ZOrderLevel::kFloatingWindow;
+    case kCGStatusWindowLevel:
+    case kCGDraggingWindowLevel:
+      return ui::ZOrderLevel::kFloatingUIElement;
+    case kCGScreenSaverWindowLevel - 1:
+      return ui::ZOrderLevel::kSecuritySurface;
+  }
+}
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -125,6 +162,7 @@
 void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
   ownership_ = params.ownership;
   name_ = params.name;
+  type_ = params.type;
   NativeWidgetMacNSWindowHost* parent_host =
       NativeWidgetMacNSWindowHost::GetFromNativeView(params.parent);
 
@@ -154,10 +192,10 @@
   ns_window_host_->InitWindow(params);
   OnWindowInitialized();
 
-  // Only set always-on-top here if it is true since setting it may affect how
-  // the window is treated by Expose.
-  if (params.keep_on_top)
-    SetAlwaysOnTop(true);
+  // Only set the z-order here if it is non-default since setting it may affect
+  // how the window is treated by Expose.
+  if (params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal)
+    SetZOrderLevel(params.EffectiveZOrderLevel());
 
   delegate_->OnNativeWidgetCreated();
 
@@ -473,13 +511,21 @@
   return ns_window_host_ ? ns_window_host_->IsWindowKey() : false;
 }
 
-void NativeWidgetMac::SetAlwaysOnTop(bool always_on_top) {
-  gfx::SetNSWindowAlwaysOnTop(GetNativeWindow().GetNativeNSWindow(),
-                              always_on_top);
+void NativeWidgetMac::SetZOrderLevel(ui::ZOrderLevel order) {
+  NSWindow* window = GetNativeWindow().GetNativeNSWindow();
+  [window setLevel:CGWindowLevelForZOrderLevel(order, type_)];
+
+  // Windows that have a higher window level than NSNormalWindowLevel default to
+  // NSWindowCollectionBehaviorTransient. Set the value explicitly here to match
+  // normal windows.
+  NSWindowCollectionBehavior behavior =
+      [window collectionBehavior] | NSWindowCollectionBehaviorManaged;
+  [window setCollectionBehavior:behavior];
 }
 
-bool NativeWidgetMac::IsAlwaysOnTop() const {
-  return gfx::IsNSWindowAlwaysOnTop(GetNativeWindow().GetNativeNSWindow());
+ui::ZOrderLevel NativeWidgetMac::GetZOrderLevel() const {
+  return ZOrderLevelForCGWindowLevel(
+      [GetNativeWindow().GetNativeNSWindow() level]);
 }
 
 void NativeWidgetMac::SetVisibleOnAllWorkspaces(bool always_visible) {
diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h
index 03a5e9b..8f0555b 100644
--- a/ui/views/widget/native_widget_private.h
+++ b/ui/views/widget/native_widget_private.h
@@ -187,8 +187,8 @@
   virtual void Activate() = 0;
   virtual void Deactivate() = 0;
   virtual bool IsActive() const = 0;
-  virtual void SetAlwaysOnTop(bool always_on_top) = 0;
-  virtual bool IsAlwaysOnTop() const = 0;
+  virtual void SetZOrderLevel(ui::ZOrderLevel order) = 0;
+  virtual ui::ZOrderLevel GetZOrderLevel() const = 0;
   virtual void SetVisibleOnAllWorkspaces(bool always_visible) = 0;
   virtual bool IsVisibleOnAllWorkspaces() const = 0;
   virtual void Maximize() = 0;
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 3541c2d..319df80 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -149,7 +149,6 @@
       opacity(INFER_OPACITY),
       accept_events(true),
       activatable(ACTIVATABLE_DEFAULT),
-      keep_on_top(type == TYPE_MENU || type == TYPE_DRAG),
       visible_on_all_workspaces(false),
       ownership(NATIVE_WIDGET_OWNS_WIDGET),
       mirror_origin_in_rtl(false),
@@ -177,6 +176,22 @@
          type != InitParams::TYPE_DRAG;
 }
 
+ui::ZOrderLevel Widget::InitParams::EffectiveZOrderLevel() const {
+  if (z_order.has_value())
+    return z_order.value();
+
+  switch (type) {
+    case TYPE_MENU:
+      return ui::ZOrderLevel::kFloatingWindow;
+      break;
+    case TYPE_DRAG:
+      return ui::ZOrderLevel::kFloatingUIElement;
+      break;
+    default:
+      return ui::ZOrderLevel::kNormal;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Widget, public:
 
@@ -682,12 +697,12 @@
   return native_widget_->IsActive();
 }
 
-void Widget::SetAlwaysOnTop(bool on_top) {
-  native_widget_->SetAlwaysOnTop(on_top);
+void Widget::SetZOrderLevel(ui::ZOrderLevel order) {
+  native_widget_->SetZOrderLevel(order);
 }
 
-bool Widget::IsAlwaysOnTop() const {
-  return native_widget_->IsAlwaysOnTop();
+ui::ZOrderLevel Widget::GetZOrderLevel() const {
+  return native_widget_->GetZOrderLevel();
 }
 
 void Widget::SetVisibleOnAllWorkspaces(bool always_visible) {
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index 5c275ae..cceddac 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -217,6 +217,10 @@
     // case where |activatable| is |ACTIVATABLE_DEFAULT|.
     bool CanActivate() const;
 
+    // Returns the z-order level, based on the overriding |z_order| but also
+    // taking into account special levels due to |type|.
+    ui::ZOrderLevel EffectiveZOrderLevel() const;
+
     Type type;
     // If null, a default implementation will be constructed. The default
     // implementation deletes itself when the Widget closes.
@@ -234,7 +238,7 @@
     WindowOpacity opacity;
     bool accept_events;
     Activatable activatable;
-    bool keep_on_top;
+    base::Optional<ui::ZOrderLevel> z_order;
     bool visible_on_all_workspaces;
     // See Widget class comment above.
     Ownership ownership;
@@ -536,12 +540,11 @@
   // Returns whether the Widget is the currently active window.
   virtual bool IsActive() const;
 
-  // Sets the widget to be on top of all other widgets in the windowing system.
-  void SetAlwaysOnTop(bool on_top);
+  // Sets the z-order of the widget. This only applies to top-level widgets.
+  void SetZOrderLevel(ui::ZOrderLevel order);
 
-  // Returns whether the widget has been set to be on top of most other widgets
-  // in the windowing system.
-  bool IsAlwaysOnTop() const;
+  // Gets the z-order of the widget. This only applies to top-level widgets.
+  ui::ZOrderLevel GetZOrderLevel() const;
 
   // Sets the widget to be visible on all work spaces.
   void SetVisibleOnAllWorkspaces(bool always_visible);
diff --git a/ui/views/widget/widget_hwnd_utils.cc b/ui/views/widget/widget_hwnd_utils.cc
index 7d74fdff..ef5c671 100644
--- a/ui/views/widget/widget_hwnd_utils.cc
+++ b/ui/views/widget/widget_hwnd_utils.cc
@@ -45,7 +45,7 @@
   DCHECK_NE(Widget::InitParams::ACTIVATABLE_DEFAULT, params.activatable);
   if (params.activatable == Widget::InitParams::ACTIVATABLE_NO)
     *ex_style |= WS_EX_NOACTIVATE;
-  if (params.keep_on_top)
+  if (params.z_order != ui::ZOrderLevel::kNormal)
     *ex_style |= WS_EX_TOPMOST;
   if (params.mirror_origin_in_rtl)
     *ex_style |= l10n_util::GetExtendedTooltipStyles();
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index de60af6..64a5731a 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -588,8 +588,8 @@
   widget.Activate();
   widget.Deactivate();
   widget.IsActive();
-  widget.SetAlwaysOnTop(true);
-  widget.IsAlwaysOnTop();
+  widget.SetZOrderLevel(ui::ZOrderLevel::kNormal);
+  widget.GetZOrderLevel();
   widget.Maximize();
   widget.Minimize();
   widget.Restore();
@@ -3692,14 +3692,14 @@
 
 #endif
 
-// Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent.
-TEST_F(WidgetTest, AlwaysOnTop) {
+// Test that the z-order levels round-trip.
+TEST_F(WidgetTest, ZOrderLevel) {
   WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
-  EXPECT_FALSE(widget->IsAlwaysOnTop());
-  widget->SetAlwaysOnTop(true);
-  EXPECT_TRUE(widget->IsAlwaysOnTop());
-  widget->SetAlwaysOnTop(false);
-  EXPECT_FALSE(widget->IsAlwaysOnTop());
+  EXPECT_EQ(ui::ZOrderLevel::kNormal, widget->GetZOrderLevel());
+  widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
+  EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow, widget->GetZOrderLevel());
+  widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
+  EXPECT_EQ(ui::ZOrderLevel::kNormal, widget->GetZOrderLevel());
 }
 
 namespace {
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 4f7b6667..af5b17eec 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -753,10 +753,6 @@
   return fullscreen_handler_->fullscreen();
 }
 
-bool HWNDMessageHandler::IsAlwaysOnTop() const {
-  return (GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
-}
-
 bool HWNDMessageHandler::RunMoveLoop(const gfx::Vector2d& drag_offset,
                                      bool hide_on_escape) {
   ReleaseCapture();
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h
index 060aa2d..b943cad 100644
--- a/ui/views/win/hwnd_message_handler.h
+++ b/ui/views/win/hwnd_message_handler.h
@@ -135,7 +135,6 @@
   bool IsMinimized() const;
   bool IsMaximized() const;
   bool IsFullscreen() const;
-  bool IsAlwaysOnTop() const;
 
   bool RunMoveLoop(const gfx::Vector2d& drag_offset, bool hide_on_escape);
   void EndMoveLoop();