File: container_finder.cc

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (184 lines) | stat: -rw-r--r-- 7,001 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/wm/container_finder.h"

#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/wm/always_on_top_controller.h"
#include "ash/wm/window_positioning_utils.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "components/app_restore/window_properties.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/wm/core/window_util.h"

namespace ash {
namespace {

aura::Window* FindContainerRoot(aura::Window* root_window,
                                const gfx::Rect& bounds_in_screen) {
  if (bounds_in_screen == gfx::Rect()) {
    return Shell::GetRootWindowForNewWindows();
  }
  auto display =
      display::Screen::GetScreen()->GetDisplayNearestWindow(root_window);
  auto overlap = display.bounds();
  overlap.Intersect(bounds_in_screen);

  // If the window is nearly invisible on the current display, use matching
  // display.
  if (!display.bounds().Contains(bounds_in_screen) &&
      overlap.width() < kMinimumOnScreenArea &&
      overlap.height() < kMinimumOnScreenArea) {
    return window_util::GetRootWindowMatching(bounds_in_screen);
  }
  return root_window;
}

bool HasTransientParentWindow(const aura::Window* window) {
  const aura::Window* transient_parent = ::wm::GetTransientParent(window);
  return transient_parent &&
         transient_parent->GetType() != aura::client::WINDOW_TYPE_UNKNOWN;
}

aura::Window* GetSystemModalContainer(aura::Window* root,
                                      aura::Window* window) {
  DCHECK_EQ(ui::MODAL_TYPE_SYSTEM,
            window->GetProperty(aura::client::kModalKey));

  // If |window| is already in a system modal container in |root|, re-use it.
  for (auto modal_container_id : kSystemModalContainerIds) {
    aura::Window* modal_container = root->GetChildById(modal_container_id);
    if (window->parent() == modal_container) {
      return modal_container;
    }
  }

  aura::Window* transient_parent = ::wm::GetTransientParent(window);

  // If screen lock is not active and user session is active,
  // all modal windows are placed into the normal modal container.
  // In case of missing transient parent (it could happen for alerts from
  // background pages) assume that the window belongs to user session.
  if (!Shell::Get()->session_controller()->IsUserSessionBlocked() ||
      !transient_parent) {
    return root->GetChildById(kShellWindowId_SystemModalContainer);
  }

  // Otherwise those that originate from LockScreen container and above are
  // placed in the screen lock modal container.
  int window_container_id = transient_parent->parent()->GetId();
  if (window_container_id < kShellWindowId_LockScreenContainer) {
    return root->GetChildById(kShellWindowId_SystemModalContainer);
  }
  return root->GetChildById(kShellWindowId_LockSystemModalContainer);
}

aura::Window* GetContainerFromAlwaysOnTopController(aura::Window* root,
                                                    aura::Window* window) {
  return RootWindowController::ForWindow(root)
      ->always_on_top_controller()
      ->GetContainer(window);
}

}  // namespace

aura::Window* GetContainerForWindow(aura::Window* window) {
  aura::Window* parent = window->parent();
  // The first parent with an explicit shell window ID is the container.
  while (parent && parent->GetId() == kShellWindowId_Invalid) {
    parent = parent->parent();
  }
  return parent;
}

aura::Window* GetDefaultParentForWindow(aura::Window* window,
                                        aura::Window* root_window,
                                        const gfx::Rect& bounds_in_screen) {
  aura::Window* target_root = nullptr;
  aura::Window* transient_parent = ::wm::GetTransientParent(window);
  if (transient_parent) {
    // Transient window should use the same root as its transient parent.
    target_root = transient_parent->GetRootWindow();
  } else {
    target_root = FindContainerRoot(root_window, bounds_in_screen);
  }

  // For window restore, the window may be created before the associated window
  // restore data can be retrieved. In this case, we will place it in a hidden
  // container and will move it to a desk container when the window restore data
  // can be retrieved. An example would be ARC windows, which can be created
  // before their associated tasks are, which are required to retrieve window
  // restore data.
  if (window->GetProperty(app_restore::kParentToHiddenContainerKey)) {
    return target_root->GetChildById(kShellWindowId_UnparentedContainer);
  }

  // Use kShellWindowId_DragImageAndTooltipContainer to host security surfaces
  // so that they are on top of other normal widgets (top-level windows, menus,
  // bubbles etc). See http://crbug.com/1317904.
  if (window->GetProperty(aura::client::kZOrderingKey) ==
      ui::ZOrderLevel::kSecuritySurface) {
    return target_root->GetChildById(
        kShellWindowId_DragImageAndTooltipContainer);
  }

  switch (window->GetType()) {
    case aura::client::WINDOW_TYPE_NORMAL:
    case aura::client::WINDOW_TYPE_POPUP:
      if (window->GetProperty(aura::client::kModalKey) ==
          ui::MODAL_TYPE_SYSTEM) {
        return GetSystemModalContainer(target_root, window);
      }
      if (HasTransientParentWindow(window)) {
        return GetContainerForWindow(transient_parent);
      }
      return GetContainerFromAlwaysOnTopController(target_root, window);
    case aura::client::WINDOW_TYPE_CONTROL:
      return target_root->GetChildById(kShellWindowId_UnparentedContainer);
    case aura::client::WINDOW_TYPE_MENU:
      return target_root->GetChildById(kShellWindowId_MenuContainer);
    case aura::client::WINDOW_TYPE_TOOLTIP:
      return target_root->GetChildById(
          kShellWindowId_DragImageAndTooltipContainer);
    default:
      NOTREACHED() << "Window " << window->GetId() << " has unhandled type "
                   << window->GetType();
      break;
  }
  return nullptr;
}

aura::Window::Windows GetContainersForAllRootWindows(
    int container_id,
    aura::Window* priority_root) {
  aura::Window::Windows containers;
  for (aura::Window* root : Shell::GetAllRootWindows()) {
    aura::Window* container = root->GetChildById(container_id);
    if (!container) {
      continue;
    }

    if (priority_root && priority_root->Contains(container)) {
      containers.insert(containers.begin(), container);
    } else {
      containers.push_back(container);
    }
  }
  return containers;
}

aura::Window* GetPowerMenuContainerParent(aura::Window* root_window) {
  return root_window->GetChildById(
      kShellWindowId_LockScreenRelatedContainersContainer);
}

}  // namespace ash