container_finder.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/wm/container_finder.h"
  5. #include "ash/public/cpp/shell_window_ids.h"
  6. #include "ash/public/cpp/window_properties.h"
  7. #include "ash/root_window_controller.h"
  8. #include "ash/session/session_controller_impl.h"
  9. #include "ash/shell.h"
  10. #include "ash/wm/always_on_top_controller.h"
  11. #include "ash/wm/window_state.h"
  12. #include "ash/wm/window_util.h"
  13. #include "components/app_restore/window_properties.h"
  14. #include "ui/aura/client/aura_constants.h"
  15. #include "ui/aura/window.h"
  16. #include "ui/gfx/geometry/rect.h"
  17. #include "ui/wm/core/window_util.h"
  18. namespace ash {
  19. namespace {
  20. aura::Window* FindContainerRoot(const gfx::Rect& bounds_in_screen) {
  21. if (bounds_in_screen == gfx::Rect())
  22. return Shell::GetRootWindowForNewWindows();
  23. return window_util::GetRootWindowMatching(bounds_in_screen);
  24. }
  25. bool HasTransientParentWindow(const aura::Window* window) {
  26. const aura::Window* transient_parent = ::wm::GetTransientParent(window);
  27. return transient_parent &&
  28. transient_parent->GetType() != aura::client::WINDOW_TYPE_UNKNOWN;
  29. }
  30. aura::Window* GetSystemModalContainer(aura::Window* root,
  31. aura::Window* window) {
  32. DCHECK_EQ(ui::MODAL_TYPE_SYSTEM,
  33. window->GetProperty(aura::client::kModalKey));
  34. // If |window| is already in a system modal container in |root|, re-use it.
  35. for (auto modal_container_id : kSystemModalContainerIds) {
  36. aura::Window* modal_container = root->GetChildById(modal_container_id);
  37. if (window->parent() == modal_container)
  38. return modal_container;
  39. }
  40. aura::Window* transient_parent = ::wm::GetTransientParent(window);
  41. // If screen lock is not active and user session is active,
  42. // all modal windows are placed into the normal modal container.
  43. // In case of missing transient parent (it could happen for alerts from
  44. // background pages) assume that the window belongs to user session.
  45. if (!Shell::Get()->session_controller()->IsUserSessionBlocked() ||
  46. !transient_parent) {
  47. return root->GetChildById(kShellWindowId_SystemModalContainer);
  48. }
  49. // Otherwise those that originate from LockScreen container and above are
  50. // placed in the screen lock modal container.
  51. int window_container_id = transient_parent->parent()->GetId();
  52. if (window_container_id < kShellWindowId_LockScreenContainer)
  53. return root->GetChildById(kShellWindowId_SystemModalContainer);
  54. return root->GetChildById(kShellWindowId_LockSystemModalContainer);
  55. }
  56. aura::Window* GetContainerFromAlwaysOnTopController(aura::Window* root,
  57. aura::Window* window) {
  58. return RootWindowController::ForWindow(root)
  59. ->always_on_top_controller()
  60. ->GetContainer(window);
  61. }
  62. } // namespace
  63. aura::Window* GetContainerForWindow(aura::Window* window) {
  64. aura::Window* parent = window->parent();
  65. // The first parent with an explicit shell window ID is the container.
  66. while (parent && parent->GetId() == kShellWindowId_Invalid)
  67. parent = parent->parent();
  68. return parent;
  69. }
  70. aura::Window* GetDefaultParentForWindow(aura::Window* window,
  71. const gfx::Rect& bounds_in_screen) {
  72. aura::Window* target_root = nullptr;
  73. aura::Window* transient_parent = ::wm::GetTransientParent(window);
  74. if (transient_parent) {
  75. // Transient window should use the same root as its transient parent.
  76. target_root = transient_parent->GetRootWindow();
  77. } else {
  78. target_root = FindContainerRoot(bounds_in_screen);
  79. }
  80. // For window restore, the window may be created before the associated window
  81. // restore data can be retrieved. In this case, we will place it in a hidden
  82. // container and will move it to a desk container when the window restore data
  83. // can be retrieved. An example would be ARC windows, which can be created
  84. // before their associated tasks are, which are required to retrieve window
  85. // restore data.
  86. if (window->GetProperty(app_restore::kParentToHiddenContainerKey))
  87. return target_root->GetChildById(kShellWindowId_UnparentedContainer);
  88. switch (window->GetType()) {
  89. case aura::client::WINDOW_TYPE_NORMAL:
  90. case aura::client::WINDOW_TYPE_POPUP:
  91. if (window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM)
  92. return GetSystemModalContainer(target_root, window);
  93. if (HasTransientParentWindow(window))
  94. return GetContainerForWindow(transient_parent);
  95. return GetContainerFromAlwaysOnTopController(target_root, window);
  96. case aura::client::WINDOW_TYPE_CONTROL:
  97. return target_root->GetChildById(kShellWindowId_UnparentedContainer);
  98. case aura::client::WINDOW_TYPE_MENU:
  99. return target_root->GetChildById(kShellWindowId_MenuContainer);
  100. case aura::client::WINDOW_TYPE_TOOLTIP:
  101. return target_root->GetChildById(
  102. kShellWindowId_DragImageAndTooltipContainer);
  103. default:
  104. NOTREACHED() << "Window " << window->GetId() << " has unhandled type "
  105. << window->GetType();
  106. break;
  107. }
  108. return nullptr;
  109. }
  110. aura::Window::Windows GetContainersForAllRootWindows(
  111. int container_id,
  112. aura::Window* priority_root) {
  113. aura::Window::Windows containers;
  114. for (aura::Window* root : Shell::GetAllRootWindows()) {
  115. aura::Window* container = root->GetChildById(container_id);
  116. if (!container)
  117. continue;
  118. if (priority_root && priority_root->Contains(container))
  119. containers.insert(containers.begin(), container);
  120. else
  121. containers.push_back(container);
  122. }
  123. return containers;
  124. }
  125. } // namespace ash