1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/root_window_controller.h"
11 #include "ash/accessibility/chromevox/touch_exploration_controller.h"
12 #include "ash/accessibility/chromevox/touch_exploration_manager.h"
13 #include "ash/accessibility/ui/accessibility_panel_layout_manager.h"
14 #include "ash/ambient/ambient_controller.h"
15 #include "ash/app_list/app_list_controller_impl.h"
16 #include "ash/app_menu/app_menu_model_adapter.h"
17 #include "ash/constants/ash_constants.h"
18 #include "ash/constants/ash_features.h"
19 #include "ash/constants/ash_switches.h"
20 #include "ash/curtain/security_curtain_widget_controller.h"
21 #include "ash/focus_cycler.h"
22 #include "ash/host/ash_window_tree_host.h"
23 #include "ash/keyboard/arc/arc_virtual_keyboard_container_layout_manager.h"
24 #include "ash/keyboard/keyboard_controller_impl.h"
25 #include "ash/keyboard/ui/keyboard_layout_manager.h"
26 #include "ash/keyboard/ui/keyboard_ui_controller.h"
27 #include "ash/keyboard/virtual_keyboard_container_layout_manager.h"
28 #include "ash/lock_screen_action/lock_screen_action_background_controller.h"
29 #include "ash/login_status.h"
30 #include "ash/public/cpp/app_menu_constants.h"
31 #include "ash/public/cpp/shell_window_ids.h"
32 #include "ash/public/cpp/window_properties.h"
33 #include "ash/resources/vector_icons/vector_icons.h"
34 #include "ash/root_window_settings.h"
35 #include "ash/rotator/screen_rotation_animator.h"
36 #include "ash/scoped_animation_disabler.h"
37 #include "ash/screen_util.h"
38 #include "ash/session/session_controller_impl.h"
39 #include "ash/shelf/shelf.h"
40 #include "ash/shelf/shelf_context_menu_model.h"
41 #include "ash/shelf/shelf_layout_manager.h"
42 #include "ash/shelf/shelf_widget.h"
43 #include "ash/shelf/shelf_window_targeter.h"
44 #include "ash/shell.h"
45 #include "ash/strings/grit/ash_strings.h"
46 #include "ash/style/ash_color_provider_source.h"
47 #include "ash/system/status_area_widget.h"
48 #include "ash/system/tray/tray_background_view.h"
49 #include "ash/system/unified/unified_system_tray.h"
50 #include "ash/touch/touch_hud_debug.h"
51 #include "ash/touch/touch_hud_projection.h"
52 #include "ash/touch/touch_observer_hud.h"
53 #include "ash/wallpaper/views/wallpaper_widget_controller.h"
54 #include "ash/wm/always_on_top_controller.h"
55 #include "ash/wm/container_finder.h"
56 #include "ash/wm/desks/desks_controller.h"
57 #include "ash/wm/desks/desks_util.h"
58 #include "ash/wm/float/float_controller.h"
59 #include "ash/wm/fullscreen_window_finder.h"
60 #include "ash/wm/lock_action_handler_layout_manager.h"
61 #include "ash/wm/lock_layout_manager.h"
62 #include "ash/wm/mru_window_tracker.h"
63 #include "ash/wm/overlay_layout_manager.h"
64 #include "ash/wm/overview/overview_controller.h"
65 #include "ash/wm/overview/overview_session.h"
66 #include "ash/wm/root_window_layout_manager.h"
67 #include "ash/wm/splitview/split_view_controller.h"
68 #include "ash/wm/splitview/split_view_overview_session.h"
69 #include "ash/wm/splitview/split_view_utils.h"
70 #include "ash/wm/switchable_windows.h"
71 #include "ash/wm/system_modal_container_layout_manager.h"
72 #include "ash/wm/system_wallpaper_controller.h"
73 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
74 #include "ash/wm/window_parenting_controller.h"
75 #include "ash/wm/window_properties.h"
76 #include "ash/wm/window_state.h"
77 #include "ash/wm/window_util.h"
78 #include "ash/wm/wm_metrics.h"
79 #include "ash/wm/work_area_insets.h"
80 #include "ash/wm/workspace/workspace_layout_manager.h"
81 #include "ash/wm/workspace_controller.h"
82 #include "base/command_line.h"
83 #include "base/functional/bind.h"
84 #include "base/memory/raw_ptr.h"
85 #include "base/metrics/histogram_macros.h"
86 #include "base/ranges/algorithm.h"
87 #include "base/task/single_thread_task_runner.h"
88 #include "base/time/time.h"
89 #include "ui/aura/client/aura_constants.h"
90 #include "ui/aura/client/drag_drop_client.h"
91 #include "ui/aura/client/screen_position_client.h"
92 #include "ui/aura/client/window_types.h"
93 #include "ui/aura/null_window_targeter.h"
94 #include "ui/aura/window.h"
95 #include "ui/aura/window_event_dispatcher.h"
96 #include "ui/aura/window_observer.h"
97 #include "ui/aura/window_tracker.h"
98 #include "ui/base/l10n/l10n_util.h"
99 #include "ui/base/models/menu_model.h"
100 #include "ui/base/models/simple_menu_model.h"
101 #include "ui/compositor/layer.h"
102 #include "ui/display/types/display_constants.h"
103 #include "ui/events/event_utils.h"
104 #include "ui/views/controls/menu/menu_runner.h"
105 #include "ui/views/widget/widget.h"
106 #include "ui/wm/core/capture_controller.h"
107 #include "ui/wm/core/coordinate_conversion.h"
108 #include "ui/wm/core/visibility_controller.h"
109 #include "ui/wm/core/window_properties.h"
110 #include "ui/wm/core/window_util.h"
111 #include "ui/wm/public/tooltip_client.h"
116 bool IsInShelfContainer(aura::Window* container) {
120 int id = container->GetId();
121 if (id == ash::kShellWindowId_ShelfContainer ||
122 id == ash::kShellWindowId_ShelfBubbleContainer) {
125 return IsInShelfContainer(container->parent());
128 bool IsWindowAboveContainer(aura::Window* window,
129 aura::Window* blocking_container) {
130 std::vector<aura::Window*> target_path;
131 std::vector<aura::Window*> blocking_path;
134 target_path.push_back(window);
135 window = window->parent();
138 while (blocking_container) {
139 blocking_path.push_back(blocking_container);
140 blocking_container = blocking_container->parent();
143 // The root window is put at the end so that we compare windows at
145 while (!blocking_path.empty()) {
146 if (target_path.empty()) {
150 aura::Window* target = target_path.back();
151 target_path.pop_back();
152 aura::Window* blocking = blocking_path.back();
153 blocking_path.pop_back();
155 // Still on the same path, continue.
156 if (target == blocking) {
160 // This can happen only if unparented window is passed because
161 // first element must be the same root.
162 if (!target->parent() || !blocking->parent()) {
166 aura::Window* common_parent = target->parent();
167 DCHECK_EQ(common_parent, blocking->parent());
168 const aura::Window::Windows& windows = common_parent->children();
169 auto blocking_iter = base::ranges::find(windows, blocking);
170 // If the target window is above blocking window, the window can handle
172 return std::find(blocking_iter, windows.end(), target) != windows.end();
178 // Scales |value| that is originally between 0 and |src_max| to be between
180 float ToRelativeValue(int value, int src_max, int dst_max) {
181 return static_cast<float>(value) / static_cast<float>(src_max) * dst_max;
184 // Uses ToRelativeValue() to scale the origin of |bounds_in_out|. The
185 // width/height are not changed.
186 void MoveOriginRelativeToSize(const gfx::Size& src_size,
187 const gfx::Size& dst_size,
188 gfx::Rect* bounds_in_out) {
189 gfx::Point origin = bounds_in_out->origin();
190 bounds_in_out->set_origin(gfx::Point(
191 ToRelativeValue(origin.x(), src_size.width(), dst_size.width()),
192 ToRelativeValue(origin.y(), src_size.height(), dst_size.height())));
195 // Reparents |window| to |new_parent|.
196 void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
197 const gfx::Size src_size = window->parent()->bounds().size();
198 const gfx::Size dst_size = new_parent->bounds().size();
199 // Update the restore bounds to make it relative to the display.
200 WindowState* state = WindowState::Get(window);
201 gfx::Rect restore_bounds;
202 const bool has_restore_bounds = state && state->HasRestoreBounds();
204 const bool update_bounds =
205 state && (state->IsNormalStateType() || state->IsMinimized());
206 gfx::Rect work_area_in_new_parent =
207 screen_util::GetDisplayWorkAreaBoundsInParent(new_parent);
209 gfx::Rect local_bounds;
211 local_bounds = state->window()->bounds();
212 MoveOriginRelativeToSize(src_size, dst_size, &local_bounds);
213 local_bounds.AdjustToFit(work_area_in_new_parent);
216 if (has_restore_bounds) {
217 restore_bounds = state->GetRestoreBoundsInParent();
218 MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds);
219 restore_bounds.AdjustToFit(work_area_in_new_parent);
222 new_parent->AddChild(window);
224 // Snapped windows have bounds handled by the layout manager in AddChild().
226 window->SetBounds(local_bounds);
229 if (has_restore_bounds) {
230 state->SetRestoreBoundsInParent(restore_bounds);
234 // Reparents the appropriate set of windows from |src| to |dst|.
235 void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
236 // Set of windows to move.
237 constexpr int kContainerIdsToMove[] = {
238 kShellWindowId_AlwaysOnTopContainer,
239 kShellWindowId_FloatContainer,
240 kShellWindowId_PipContainer,
241 kShellWindowId_SystemModalContainer,
242 kShellWindowId_LockSystemModalContainer,
243 kShellWindowId_UnparentedContainer,
244 kShellWindowId_OverlayContainer,
245 kShellWindowId_LockActionHandlerContainer,
246 kShellWindowId_MenuContainer,
248 constexpr int kExtraContainerIdsToMoveInUnifiedMode[] = {
249 kShellWindowId_LockScreenContainer,
252 // Desk container ids are different depends on whether Bento feature is
254 std::vector<int> container_ids = desks_util::GetDesksContainersIds();
255 for (const int id : kContainerIdsToMove) {
256 container_ids.emplace_back(id);
259 // Check the display mode as this is also necessary when trasitioning between
260 // mirror and unified mode.
261 if (Shell::Get()->display_manager()->current_default_multi_display_mode() ==
262 display::DisplayManager::UNIFIED) {
263 for (const int id : kExtraContainerIdsToMoveInUnifiedMode) {
264 container_ids.emplace_back(id);
268 const std::vector<aura::Window*> mru_list =
269 Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks);
270 for (int id : container_ids) {
271 aura::Window* src_container = src->GetChildById(id);
272 aura::Window* dst_container = dst->GetChildById(id);
273 const bool switchable_container = IsSwitchableContainer(src_container);
274 while (!src_container->children().empty()) {
275 // Restart iteration from the source container windows each time as they
276 // may change as a result of moving other windows.
277 const aura::Window::Windows& src_container_children =
278 src_container->children();
279 auto iter = src_container_children.rbegin();
280 while (iter != src_container_children.rend() &&
281 SystemModalContainerLayoutManager::IsModalBackground(*iter)) {
284 // If the entire window list is modal background windows then stop.
285 if (iter == src_container_children.rend()) {
289 // |iter| is invalidated after ReparentWindow. Cache it to use afterwards.
290 aura::Window* const window = *iter;
291 ReparentWindow(window, dst_container);
293 aura::Window* stacking_target = nullptr;
294 if (switchable_container) {
295 // Find the first window that comes after |window| in the MRU list that
296 // shares the same parent.
297 bool found_window = false;
298 for (aura::Window* window_iter : mru_list) {
299 // First determine the position of |window| in the |mru_list|.
300 if (!found_window && window == window_iter) {
305 if (!found_window || window_iter->parent() != dst_container) {
309 // Once |window| is found, the next item in |mru_list| with the same
310 // parent (container) is the stacking target.
311 stacking_target = window_iter;
316 // |stacking_target| may be null if |switchable_container| is false, which
317 // means the children of that container wouldn't be in the MRU list or if
318 // |window| was the last item in the MRU list with parent id |id|. In
319 // this case stack |window| at the bottom.
320 if (stacking_target) {
321 dst_container->StackChildAbove(window, stacking_target);
323 dst_container->StackChildAtBottom(window);
329 bool ShouldDestroyWindowInCloseChildWindows(aura::Window* window) {
330 return window->owned_by_parent();
333 // Clears the workspace controllers from the properties of all virtual desks
334 // containers in |root|.
335 void ClearWorkspaceControllers(aura::Window* root) {
336 for (auto* desk_container : desks_util::GetDesksContainers(root)) {
337 SetWorkspaceController(desk_container, nullptr);
339 if (auto* float_controller = Shell::Get()->float_controller()) {
340 float_controller->ClearWorkspaceEventHandler(root);
344 class RootWindowTargeter : public aura::WindowTargeter {
346 RootWindowTargeter() = default;
348 RootWindowTargeter(const RootWindowTargeter&) = delete;
349 RootWindowTargeter& operator=(const RootWindowTargeter&) = delete;
351 ~RootWindowTargeter() override = default;
354 aura::Window* FindTargetForLocatedEvent(aura::Window* window,
355 ui::LocatedEvent* event) override {
356 if (!window->parent() && !window->bounds().Contains(event->location()) &&
357 IsEventInsideDisplayForTelemetryHack(window, event)) {
358 auto* dispatcher = window->GetHost()->dispatcher();
359 bool has_capture_target = !!dispatcher->mouse_pressed_handler() ||
360 !!aura::client::GetCaptureWindow(window);
362 // Make sure that event location is within the root window bounds if
363 // 1) mouse event isn't captured.
364 // 2) A mouse is clicked without movement and capture.
366 // The event can be outside on some scale factor due to rounding, or due
367 // to not well calibrated a touch screen, or Detect this situation and
368 // adjust the location.
369 bool bounded_click = ShouldConstrainMouseClick(event, has_capture_target);
370 if (!has_capture_target || bounded_click) {
371 gfx::Point new_location =
372 FitPointToBounds(event->location(), window->bounds());
373 // Do not change |location_f|. It's used to compute pixel position and
374 // such client should know what they're doing.
375 event->set_location(new_location);
376 event->set_root_location(new_location);
379 return aura::WindowTargeter::FindTargetForLocatedEvent(window, event);
382 // Stop-gap workaround for telemetry tests that send events far outside of the
383 // display (e.g. 512, -4711). Fix the test and remove this (crbgu.com/904623).
384 bool IsEventInsideDisplayForTelemetryHack(aura::Window* window,
385 ui::LocatedEvent* event) {
386 constexpr int ExtraMarginForTelemetryTest = -10;
387 gfx::Rect bounds = window->bounds();
388 bounds.Inset(ExtraMarginForTelemetryTest);
389 return bounds.Contains(event->location());
393 // Returns true if the mouse event should be constrainted.
394 bool ShouldConstrainMouseClick(ui::LocatedEvent* event,
395 bool has_capture_target) {
396 if (event->type() == ui::ET_MOUSE_PRESSED && !has_capture_target) {
397 last_mouse_event_type_ = ui::ET_MOUSE_PRESSED;
400 if (last_mouse_event_type_ == ui::ET_MOUSE_PRESSED &&
401 event->type() == ui::ET_MOUSE_RELEASED && has_capture_target) {
402 last_mouse_event_type_ = ui::ET_UNKNOWN;
405 // For other cases, reset the state
406 if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
407 last_mouse_event_type_ = ui::ET_UNKNOWN;
412 gfx::Point FitPointToBounds(const gfx::Point p, const gfx::Rect& bounds) {
413 return gfx::Point(std::clamp(p.x(), bounds.x(), bounds.right() - 1),
414 std::clamp(p.y(), bounds.y(), bounds.bottom() - 1));
417 ui::EventType last_mouse_event_type_ = ui::ET_UNKNOWN;
420 class RootWindowMenuModelAdapter : public AppMenuModelAdapter {
422 RootWindowMenuModelAdapter(std::unique_ptr<ui::SimpleMenuModel> model,
423 views::Widget* widget_owner,
424 ui::MenuSourceType source_type,
425 base::OnceClosure on_menu_closed_callback,
427 : AppMenuModelAdapter(std::string(),
431 std::move(on_menu_closed_callback),
434 RootWindowMenuModelAdapter(const RootWindowMenuModelAdapter&) = delete;
435 RootWindowMenuModelAdapter& operator=(const RootWindowMenuModelAdapter&) =
438 ~RootWindowMenuModelAdapter() override = default;
441 // AppMenuModelAdapter overrides:
442 void RecordHistogramOnMenuClosed() override {
443 const base::TimeDelta user_journey_time =
444 base::TimeTicks::Now() - menu_open_time();
446 UMA_HISTOGRAM_TIMES("Apps.ContextMenuUserJourneyTime.Desktop",
448 UMA_HISTOGRAM_ENUMERATION("Apps.ContextMenuShowSource.Desktop",
449 source_type(), ui::MENU_SOURCE_TYPE_LAST);
450 if (is_tablet_mode()) {
451 UMA_HISTOGRAM_TIMES("Apps.ContextMenuUserJourneyTime.Desktop.TabletMode",
453 UMA_HISTOGRAM_ENUMERATION("Apps.ContextMenuShowSource.Desktop.TabletMode",
454 source_type(), ui::MENU_SOURCE_TYPE_LAST);
457 "Apps.ContextMenuUserJourneyTime.Desktop.ClamshellMode",
459 UMA_HISTOGRAM_ENUMERATION(
460 "Apps.ContextMenuShowSource.Desktop.ClamshellMode", source_type(),
461 ui::MENU_SOURCE_TYPE_LAST);
466 // A layout manager that fills its container when the child window's resize
467 // behavior is set to be maximizable.
468 class FillLayoutManager : public aura::LayoutManager {
470 explicit FillLayoutManager(aura::Window* container) : container_(container) {}
471 ~FillLayoutManager() override = default;
472 FillLayoutManager(const FillLayoutManager&) = delete;
473 FillLayoutManager& operator=(const FillLayoutManager&) = delete;
475 // aura::LayoutManager:
476 void OnWindowResized() override { Relayout(); }
477 void OnWindowAddedToLayout(aura::Window* child) override { Relayout(); }
478 void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
479 void OnWindowRemovedFromLayout(aura::Window* child) override {}
480 void OnChildWindowVisibilityChanged(aura::Window* child,
481 bool visible) override {}
482 void SetChildBounds(aura::Window* child,
483 const gfx::Rect& requested_bounds) override {}
487 // Fill the window that is set to be maximizable.
488 const gfx::Rect fullscreen(container_->bounds().size());
489 for (auto* child : container_->children()) {
490 const int resize_behavior =
491 child->GetProperty(aura::client::kResizeBehaviorKey);
492 if (resize_behavior & aura::client::kResizeBehaviorCanMaximize) {
493 SetChildBoundsDirect(child, fullscreen);
498 raw_ptr<aura::Window, ExperimentalAsh> container_;
504 std::vector<RootWindowController*>*
505 RootWindowController::root_window_controllers_ = nullptr;
507 RootWindowController::~RootWindowController() {
509 DCHECK(!wallpaper_widget_controller_.get());
510 work_area_insets_.reset();
512 // The CaptureClient needs to be around for as long as the RootWindow is
514 capture_client_.reset();
515 root_window_controllers_->erase(
516 base::ranges::find(*root_window_controllers_, this));
519 RootWindowController* RootWindowController::CreateForPrimaryDisplay(
520 AshWindowTreeHost* host) {
521 RootWindowController* controller = new RootWindowController(host);
522 controller->Init(RootWindowType::PRIMARY);
526 RootWindowController* RootWindowController::CreateForSecondaryDisplay(
527 AshWindowTreeHost* host) {
528 RootWindowController* controller = new RootWindowController(host);
529 controller->Init(RootWindowType::SECONDARY);
534 RootWindowController* RootWindowController::ForWindow(
535 const aura::Window* window) {
537 CHECK(Shell::HasInstance());
538 return GetRootWindowSettings(window->GetRootWindow())->controller;
542 RootWindowController* RootWindowController::ForTargetRootWindow() {
543 CHECK(Shell::HasInstance());
544 return ForWindow(Shell::GetRootWindowForNewWindows());
547 aura::WindowTreeHost* RootWindowController::GetHost() {
548 return window_tree_host_;
551 const aura::WindowTreeHost* RootWindowController::GetHost() const {
552 return window_tree_host_;
555 aura::Window* RootWindowController::GetRootWindow() {
556 return GetHost()->window();
559 const aura::Window* RootWindowController::GetRootWindow() const {
560 return GetHost()->window();
563 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
564 return shelf_->shelf_layout_manager();
567 SystemModalContainerLayoutManager*
568 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
569 aura::Window* modal_container = nullptr;
571 aura::Window* window_container = GetContainerForWindow(window);
572 if (window_container &&
573 window_container->GetId() >= kShellWindowId_LockScreenContainer) {
574 modal_container = GetContainer(kShellWindowId_LockSystemModalContainer);
576 modal_container = GetContainer(kShellWindowId_SystemModalContainer);
579 int modal_window_id =
580 Shell::Get()->session_controller()->IsUserSessionBlocked()
581 ? kShellWindowId_LockSystemModalContainer
582 : kShellWindowId_SystemModalContainer;
583 modal_container = GetContainer(modal_window_id);
585 return modal_container ? static_cast<SystemModalContainerLayoutManager*>(
586 modal_container->layout_manager())
590 StatusAreaWidget* RootWindowController::GetStatusAreaWidget() {
591 ShelfWidget* shelf_widget = shelf_->shelf_widget();
592 return shelf_widget ? shelf_widget->status_area_widget() : nullptr;
595 bool RootWindowController::IsSystemTrayVisible() {
596 TrayBackgroundView* tray = GetStatusAreaWidget()->unified_system_tray();
597 return tray && tray->GetWidget()->IsVisible() && tray->GetVisible();
600 bool RootWindowController::CanWindowReceiveEvents(aura::Window* window) {
601 if (GetRootWindow() != window->GetRootWindow()) {
605 aura::Window* blocking_container = nullptr;
606 aura::Window* modal_container = nullptr;
607 window_util::GetBlockingContainersForRoot(
608 GetRootWindow(), &blocking_container, &modal_container);
609 SystemModalContainerLayoutManager* modal_layout_manager = nullptr;
610 if (modal_container && modal_container->layout_manager()) {
611 modal_layout_manager = static_cast<SystemModalContainerLayoutManager*>(
612 modal_container->layout_manager());
615 if (modal_layout_manager && modal_layout_manager->has_window_dimmer()) {
616 blocking_container = modal_container;
618 modal_container = nullptr; // Don't check modal dialogs.
621 // In normal session.
622 if (!blocking_container) {
626 if (!IsWindowAboveContainer(window, blocking_container)) {
630 if (modal_container) {
631 // If the window is in the target modal container, only allow the top most
633 if (modal_container->Contains(window)) {
634 return modal_layout_manager->IsPartOfActiveModalWindow(window);
636 // Don't allow shelf to process events if there is a visible modal dialog.
637 if (IsInShelfContainer(window->parent())) {
644 aura::Window* RootWindowController::FindEventTarget(
645 const gfx::Point& location_in_screen) {
646 gfx::Point location_in_root(location_in_screen);
647 aura::Window* root_window = GetRootWindow();
648 ::wm::ConvertPointFromScreen(root_window, &location_in_root);
649 ui::MouseEvent test_event(ui::ET_MOUSE_MOVED, location_in_root,
650 location_in_root, ui::EventTimeForNow(),
651 ui::EF_NONE, ui::EF_NONE);
652 ui::EventTarget* event_handler =
653 root_window->GetHost()
655 ->GetDefaultEventTargeter()
656 ->FindTargetForEvent(root_window, &test_event);
657 return static_cast<aura::Window*>(event_handler);
660 gfx::Point RootWindowController::GetLastMouseLocationInRoot() {
661 return window_tree_host_->dispatcher()->GetLastMouseLocationInRoot();
664 aura::Window* RootWindowController::GetContainer(int container_id) {
665 return GetRootWindow()->GetChildById(container_id);
668 const aura::Window* RootWindowController::GetContainer(int container_id) const {
669 return window_tree_host_->window()->GetChildById(container_id);
672 ScreenRotationAnimator* RootWindowController::GetScreenRotationAnimator() {
673 if (is_shutting_down_) {
677 if (!screen_rotation_animator_) {
678 screen_rotation_animator_ =
679 std::make_unique<ScreenRotationAnimator>(GetRootWindow());
682 return screen_rotation_animator_.get();
685 void RootWindowController::Shutdown() {
686 is_shutting_down_ = true;
688 // Destroy the `screen_rotation_animator_` now to avoid any potential crashes
689 // if there's any ongoing animation. See http://b/293667233.
690 screen_rotation_animator_.reset();
692 aura::Window* root_window = GetRootWindow();
693 auto targeter = root_window->SetEventTargeter(
694 std::make_unique<aura::NullWindowTargeter>());
696 touch_exploration_manager_.reset();
697 wallpaper_widget_controller_.reset();
698 EndSplitViewOverviewSession(SplitViewOverviewSessionExitPoint::kShutdown);
699 CloseAmbientWidget(/*immediately=*/true);
702 GetRootWindowSettings(root_window)->controller = nullptr;
703 // Forget with the display ID so that display lookup
704 // ends up with invalid display.
705 GetRootWindowSettings(root_window)->display_id = display::kInvalidDisplayId;
707 ash_host_->PrepareForShutdown();
709 window_parenting_controller_.reset();
710 system_wallpaper_.reset();
711 security_curtain_widget_controller_.reset();
712 lock_screen_action_background_controller_.reset();
713 aura::client::SetScreenPositionClient(root_window, nullptr);
715 // The targeter may still on the stack, so delete it later.
717 base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(
718 FROM_HERE, std::move(targeter));
722 void RootWindowController::CloseChildWindows() {
723 // Child windows can be closed by secondary monitor disconnection, Shell
724 // shutdown, or both. Avoid running the related cleanup code twice.
725 if (did_close_child_windows_) {
728 did_close_child_windows_ = true;
730 aura::Window* root = GetRootWindow();
732 Shell::Get()->desks_controller()->OnRootWindowClosing(root);
734 // Notify the keyboard controller before closing child windows and shutting
735 // down associated layout managers.
736 Shell::Get()->keyboard_controller()->OnRootWindowClosing(root);
738 OverviewController* overview_controller = Shell::Get()->overview_controller();
739 if (overview_controller && overview_controller->InOverviewSession()) {
740 overview_controller->overview_session()->OnRootWindowClosing(root);
743 shelf_->ShutdownShelfWidget();
745 ClearWorkspaceControllers(root);
746 always_on_top_controller_->ClearLayoutManagers();
748 // Explicitly destroy top level windows. We do this because such windows may
749 // query the RootWindow for state.
750 aura::WindowTracker non_toplevel_windows;
751 non_toplevel_windows.Add(root);
752 while (!non_toplevel_windows.windows().empty()) {
753 aura::Window* non_toplevel_window = non_toplevel_windows.Pop();
754 aura::WindowTracker toplevel_windows;
755 for (aura::Window* child : non_toplevel_window->children()) {
756 if (!ShouldDestroyWindowInCloseChildWindows(child)) {
759 if (child->delegate()) {
760 toplevel_windows.Add(child);
762 non_toplevel_windows.Add(child);
765 while (!toplevel_windows.windows().empty()) {
766 aura::Window* toplevel_window = toplevel_windows.windows().back();
767 // Complete in progress animations before deleting the window. This is
768 // done as deleting the window implicitly cancels animations (as long
769 // as the toplevel_window is the layer owner), which may delete the
771 if (toplevel_window->layer()->owner() == toplevel_window) {
772 toplevel_window->layer()->CompleteAllAnimations();
773 if (toplevel_windows.windows().empty() ||
774 toplevel_windows.windows().back() != toplevel_window) {
778 delete toplevel_windows.Pop();
782 // Reset layout manager so that it won't fire unnecessary layout evetns.
783 root->SetLayoutManager(nullptr);
784 // And then remove the containers.
785 while (!root->children().empty()) {
786 aura::Window* child = root->children()[0];
787 if (ShouldDestroyWindowInCloseChildWindows(child)) {
790 root->RemoveChild(child);
794 // Removing the containers destroys ShelfLayoutManager. ShelfWidget outlives
795 // ShelfLayoutManager because ShelfLayoutManager holds a pointer to it.
796 shelf_->DestroyShelfWidget();
798 ::wm::SetTooltipClient(GetRootWindow(), nullptr);
801 void RootWindowController::MoveWindowsTo(aura::Window* dst) {
802 // Suspend unnecessary updates of the shelf visibility indefinitely since it
804 if (GetShelfLayoutManager()) {
805 GetShelfLayoutManager()->SuspendVisibilityUpdateForShutdown();
808 // Clear the workspace controller to avoid a lot of unnecessary operations
809 // when window are removed.
810 // TODO(afakhry): Should we also clear the WorkspaceLayoutManagers of the pip,
811 // always-on-top, and other containers?
812 aura::Window* root = GetRootWindow();
813 ClearWorkspaceControllers(root);
815 ReparentAllWindows(root, dst);
818 void RootWindowController::InitTouchHuds() {
819 // Enable touch debugging features when each display is initialized.
820 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
821 if (command_line->HasSwitch(switches::kAshTouchHud)) {
822 set_touch_hud_debug(new TouchHudDebug(GetRootWindow()));
825 // TouchHudProjection manages its own lifetime.
826 if (command_line->HasSwitch(switches::kShowTaps)) {
827 touch_hud_projection_ = new TouchHudProjection(GetRootWindow());
831 aura::Window* RootWindowController::GetWindowForFullscreenMode() {
832 return GetWindowForFullscreenModeInRoot(GetRootWindow());
835 bool RootWindowController::IsInFullscreenMode() {
836 auto* window = GetWindowForFullscreenMode();
837 return window && WindowState::Get(window)->GetHideShelfWhenFullscreen();
840 void RootWindowController::SetTouchAccessibilityAnchorPoint(
841 const gfx::Point& anchor_point) {
842 if (touch_exploration_manager_) {
843 touch_exploration_manager_->SetTouchAccessibilityAnchorPoint(anchor_point);
847 void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
848 ui::MenuSourceType source_type) {
849 const int64_t display_id = display::Screen::GetScreen()
850 ->GetDisplayNearestWindow(GetRootWindow())
853 const bool tablet_mode =
854 Shell::Get()->tablet_mode_controller()->InTabletMode();
855 root_window_menu_model_adapter_ =
856 std::make_unique<RootWindowMenuModelAdapter>(
857 std::make_unique<ShelfContextMenuModel>(nullptr, display_id,
858 /*menu_in_shelf=*/false),
859 wallpaper_widget_controller()->GetWidget(), source_type,
860 base::BindOnce(&RootWindowController::OnMenuClosed,
861 base::Unretained(this)),
864 // Appends the apps sort options in ShelfContextMenuModel in tablet mode. Note
865 // that the launcher UI is fullscreen in tablet mode, so the whole root window
866 // can be perceived by users to be part of the launcher.
867 auto* const app_list_controller = Shell::Get()->app_list_controller();
868 if (tablet_mode && app_list_controller->IsVisible(display_id) &&
869 app_list_controller->GetCurrentAppListPage() ==
870 AppListState::kStateApps) {
871 ui::SimpleMenuModel* menu_model = root_window_menu_model_adapter_->model();
872 sort_apps_submenu_ = std::make_unique<ui::SimpleMenuModel>(
873 static_cast<ShelfContextMenuModel*>(menu_model));
874 sort_apps_submenu_->AddItemWithIcon(
875 REORDER_BY_NAME_ALPHABETICAL,
876 l10n_util::GetStringUTF16(
877 IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_BY_NAME),
878 ui::ImageModel::FromVectorIcon(kSortAlphabeticalIcon,
879 ui::kColorAshSystemUIMenuIcon));
880 sort_apps_submenu_->AddItemWithIcon(
882 l10n_util::GetStringUTF16(
883 IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_BY_COLOR),
884 ui::ImageModel::FromVectorIcon(kSortColorIcon,
885 ui::kColorAshSystemUIMenuIcon));
886 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
887 menu_model->AddSubMenuWithIcon(
889 l10n_util::GetStringUTF16(
890 IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_TITLE),
891 sort_apps_submenu_.get(),
892 ui::ImageModel::FromVectorIcon(kReorderIcon,
893 ui::kColorAshSystemUIMenuIcon));
895 // Append the "Show all suggestions" / "Hide all suggestions" item.
896 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
897 if (app_list_controller->ShouldHideContinueSection()) {
898 menu_model->AddItemWithIcon(
899 ShelfContextMenuModel::MENU_SHOW_CONTINUE_SECTION,
900 l10n_util::GetStringUTF16(IDS_ASH_LAUNCHER_SHOW_CONTINUE_SECTION),
901 ui::ImageModel::FromVectorIcon(kLauncherShowContinueSectionIcon,
902 ui::kColorAshSystemUIMenuIcon));
904 menu_model->AddItemWithIcon(
905 ShelfContextMenuModel::MENU_HIDE_CONTINUE_SECTION,
906 l10n_util::GetStringUTF16(IDS_ASH_LAUNCHER_HIDE_CONTINUE_SECTION),
907 ui::ImageModel::FromVectorIcon(kLauncherHideContinueSectionIcon,
908 ui::kColorAshSystemUIMenuIcon));
912 root_window_menu_model_adapter_->Run(
913 gfx::Rect(location_in_screen, gfx::Size()),
914 views::MenuAnchorPosition::kBubbleRight,
915 views::MenuRunner::CONTEXT_MENU |
916 views::MenuRunner::USE_ASH_SYS_UI_LAYOUT |
917 views::MenuRunner::FIXED_ANCHOR);
920 void RootWindowController::HideContextMenu() {
921 if (root_window_menu_model_adapter_) {
922 root_window_menu_model_adapter_->Cancel();
926 void RootWindowController::HideContextMenuNoAnimation() {
927 if (!IsContextMenuShown()) {
931 views::Widget* submenu_widget =
932 root_window_menu_model_adapter_->GetSubmenuWidget();
933 DCHECK(submenu_widget);
934 ScopedAnimationDisabler disable(submenu_widget->GetNativeWindow());
935 root_window_menu_model_adapter_->Cancel();
938 bool RootWindowController::IsContextMenuShown() const {
939 return root_window_menu_model_adapter_ &&
940 root_window_menu_model_adapter_->IsShowingMenu();
943 void RootWindowController::UpdateAfterLoginStatusChange(LoginStatus status) {
944 StatusAreaWidget* status_area_widget =
945 shelf_->shelf_widget()->status_area_widget();
946 if (status_area_widget) {
947 status_area_widget->UpdateAfterLoginStatusChange(status);
951 void RootWindowController::CreateAmbientWidget() {
952 DCHECK(!ambient_widget_);
954 auto* ambient_controller = Shell::Get()->ambient_controller();
955 if (ambient_controller) {
956 ambient_widget_ = ambient_controller->CreateWidget(
957 GetRootWindow()->GetChildById(kShellWindowId_AmbientModeContainer));
961 void RootWindowController::CloseAmbientWidget(bool immediately) {
962 if (ambient_widget_) {
964 ambient_widget_->CloseNow();
966 ambient_widget_->CloseWithReason(views::Widget::ClosedReason::kLostFocus);
970 ambient_widget_.reset();
973 bool RootWindowController::HasAmbientWidget() const {
974 return !!ambient_widget_;
977 AccessibilityPanelLayoutManager*
978 RootWindowController::GetAccessibilityPanelLayoutManagerForTest() {
979 return GetAccessibilityPanelLayoutManager();
982 void RootWindowController::SetSecurityCurtainWidgetController(
983 std::unique_ptr<curtain::SecurityCurtainWidgetController> controller) {
984 DCHECK(!security_curtain_widget_controller_);
985 security_curtain_widget_controller_ = std::move(controller);
988 void RootWindowController::ClearSecurityCurtainWidgetController() {
989 security_curtain_widget_controller_ = nullptr;
992 curtain::SecurityCurtainWidgetController*
993 RootWindowController::security_curtain_widget_controller() {
994 return security_curtain_widget_controller_.get();
997 void RootWindowController::StartSplitViewOverviewSession(
998 aura::Window* window,
999 absl::optional<OverviewStartAction> action,
1000 absl::optional<OverviewEnterExitType> type,
1001 WindowSnapActionSource snap_action_source) {
1002 split_view_overview_session_ =
1003 std::make_unique<SplitViewOverviewSession>(window, snap_action_source);
1004 split_view_overview_session_->Init(action, type);
1007 void RootWindowController::EndSplitViewOverviewSession(
1008 SplitViewOverviewSessionExitPoint exit_point) {
1009 if (!is_shutting_down_ && split_view_overview_session_) {
1010 split_view_overview_session_
1011 ->RecordSplitViewOverviewSessionExitPointMetrics(exit_point);
1013 split_view_overview_session_.reset();
1016 void RootWindowController::SetScreenRotationAnimatorForTest(
1017 std::unique_ptr<ScreenRotationAnimator> animator) {
1018 screen_rotation_animator_ = std::move(animator);
1021 ////////////////////////////////////////////////////////////////////////////////
1022 // RootWindowController, private:
1024 RootWindowController::RootWindowController(AshWindowTreeHost* ash_host)
1025 : ash_host_(ash_host),
1026 window_tree_host_(ash_host->AsWindowTreeHost()),
1027 shelf_(std::make_unique<Shelf>()),
1028 lock_screen_action_background_controller_(
1029 LockScreenActionBackgroundController::Create()),
1030 work_area_insets_(std::make_unique<WorkAreaInsets>(this)) {
1032 DCHECK(window_tree_host_);
1034 if (!root_window_controllers_) {
1035 root_window_controllers_ = new std::vector<RootWindowController*>;
1037 root_window_controllers_->push_back(this);
1039 aura::Window* root_window = GetRootWindow();
1040 GetRootWindowSettings(root_window)->controller = this;
1042 window_parenting_controller_ =
1043 std::make_unique<WindowParentingController>(root_window);
1044 capture_client_ = std::make_unique<::wm::ScopedCaptureClient>(root_window);
1047 void RootWindowController::Init(RootWindowType root_window_type) {
1048 aura::Window* root_window = GetRootWindow();
1049 // Create |split_view_controller_| for every display.
1050 split_view_controller_ = std::make_unique<SplitViewController>(root_window);
1051 Shell* shell = Shell::Get();
1052 shell->InitRootWindow(root_window);
1054 root_window->SetEventTargeter(std::make_unique<RootWindowTargeter>());
1055 DCHECK(!old_targeter);
1057 std::unique_ptr<RootWindowLayoutManager> root_window_layout_manager =
1058 std::make_unique<RootWindowLayoutManager>(root_window);
1059 root_window_layout_manager_ = root_window_layout_manager.get();
1062 CreateSystemWallpaper(root_window_type);
1064 InitLayoutManagers(std::move(root_window_layout_manager));
1067 // `shelf_` was created in the constructor.
1068 shelf_->shelf_widget()->PostCreateShelf();
1070 color_provider_source_ = std::make_unique<AshColorProviderSource>();
1071 if (Shell::GetPrimaryRootWindowController()
1072 ->GetSystemModalLayoutManager(nullptr)
1073 ->has_window_dimmer()) {
1074 GetSystemModalLayoutManager(nullptr)->CreateModalBackground();
1077 wallpaper_widget_controller_ =
1078 std::make_unique<WallpaperWidgetController>(root_window);
1080 wallpaper_widget_controller_->Init(
1081 Shell::Get()->session_controller()->IsUserSessionBlocked());
1082 root_window_layout_manager_->OnWindowResized();
1084 CreateAmbientWidget();
1086 // Explicitly update the desks controller before notifying the ShellObservers.
1087 // This is to make sure the desks' states are correct before clients are
1089 shell->desks_controller()->OnRootWindowAdded(root_window);
1091 if (root_window_type == RootWindowType::PRIMARY) {
1092 shell->keyboard_controller()->RebuildKeyboardIfEnabled();
1094 window_tree_host_->Show();
1096 // Notify shell observers about new root window.
1097 shell->OnRootWindowAdded(root_window);
1100 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1101 switches::kAshDisableTouchExplorationMode)) {
1102 touch_exploration_manager_ =
1103 std::make_unique<TouchExplorationManager>(this);
1107 void RootWindowController::InitLayoutManagers(
1108 std::unique_ptr<RootWindowLayoutManager> root_window_layout_manager) {
1109 // Create the shelf and status area widgets. Creates the ShelfLayoutManager
1110 // as a side-effect.
1111 DCHECK(!shelf_->shelf_widget());
1112 aura::Window* root = GetRootWindow();
1113 shelf_->CreateShelfWidget(root);
1115 root->SetLayoutManager(std::move(root_window_layout_manager));
1117 for (auto* container : desks_util::GetDesksContainers(root)) {
1118 // Installs WorkspaceLayoutManager on the container.
1119 SetWorkspaceController(container,
1120 std::make_unique<WorkspaceController>(container));
1123 aura::Window* modal_container =
1124 GetContainer(kShellWindowId_SystemModalContainer);
1125 modal_container->SetLayoutManager(
1126 std::make_unique<SystemModalContainerLayoutManager>(modal_container));
1128 aura::Window* lock_modal_container =
1129 GetContainer(kShellWindowId_LockSystemModalContainer);
1130 DCHECK(lock_modal_container);
1131 lock_modal_container->SetLayoutManager(
1132 std::make_unique<SystemModalContainerLayoutManager>(
1133 lock_modal_container));
1135 aura::Window* lock_action_handler_container =
1136 GetContainer(kShellWindowId_LockActionHandlerContainer);
1137 DCHECK(lock_action_handler_container);
1138 lock_screen_action_background_controller_->SetParentWindow(
1139 lock_action_handler_container);
1140 lock_action_handler_container->SetLayoutManager(
1141 std::make_unique<LockActionHandlerLayoutManager>(
1142 lock_action_handler_container,
1143 lock_screen_action_background_controller_.get()));
1145 aura::Window* lock_container =
1146 GetContainer(kShellWindowId_LockScreenContainer);
1147 DCHECK(lock_container);
1148 lock_container->SetLayoutManager(
1149 std::make_unique<LockLayoutManager>(lock_container));
1151 aura::Window* always_on_top_container =
1152 GetContainer(kShellWindowId_AlwaysOnTopContainer);
1153 aura::Window* pip_container = GetContainer(kShellWindowId_PipContainer);
1154 DCHECK(always_on_top_container);
1155 DCHECK(pip_container);
1156 always_on_top_controller_ = std::make_unique<AlwaysOnTopController>(
1157 always_on_top_container, pip_container);
1159 // Make it easier to resize windows that partially overlap the shelf. Must
1160 // occur after the ShelfLayoutManager is constructed by ShelfWidget.
1161 aura::Window* shelf_container = GetContainer(kShellWindowId_ShelfContainer);
1162 shelf_container->SetEventTargeter(
1163 std::make_unique<ShelfWindowTargeter>(shelf_container, shelf_.get()));
1166 void RootWindowController::CreateContainers() {
1167 // CreateContainer() depends on root_window_layout_manager_.
1168 DCHECK(root_window_layout_manager_);
1170 aura::Window* root = GetRootWindow();
1172 // Add a NOT_DRAWN layer in between the root_window's layer and its current
1173 // children so that we only need to initiate two LayerAnimationSequences for
1174 // fullscreen animations such as the screen rotation animation and the desk
1175 // switch animation. Those animations take a screenshot of this container,
1176 // stack it ontop and animate the screenshot instead of the individual
1178 aura::Window* screen_rotation_container =
1179 CreateContainer(kShellWindowId_ScreenAnimationContainer,
1180 "ScreenAnimationContainer", root);
1182 // Everything that needs to be included in the docked magnifier, when enabled,
1183 // should be a descendant of MagnifiedContainer. The DockedMagnifierContainer
1184 // should not be a descendant of this container, otherwise there would be a
1185 // cycle (docked magnifier trying to magnify itself).
1186 aura::Window* magnified_container =
1187 CreateContainer(kShellWindowId_MagnifiedContainer, "MagnifiedContainer",
1188 screen_rotation_container);
1190 CreateContainer(kShellWindowId_DockedMagnifierContainer,
1191 "DockedMagnifierContainer", screen_rotation_container);
1193 // These containers are just used by PowerButtonController to animate groups
1194 // of containers simultaneously without messing up the current transformations
1195 // on those containers. These are direct children of the magnified_container
1196 // window; all of the other containers are their children.
1198 // The wallpaper container is not part of the lock animation, so it is not
1199 // included in those animate groups. When the screen is locked, the wallpaper
1200 // is moved to the lock screen wallpaper container (and moved back on unlock).
1201 // Ensure that there's an opaque layer occluding the non-lock-screen layers.
1202 aura::Window* wallpaper_container =
1203 CreateContainer(kShellWindowId_WallpaperContainer, "WallpaperContainer",
1204 magnified_container);
1205 ::wm::SetChildWindowVisibilityChangesAnimated(wallpaper_container);
1206 wallpaper_container->SetLayoutManager(
1207 std::make_unique<FillLayoutManager>(wallpaper_container));
1209 aura::Window* non_lock_screen_containers =
1210 CreateContainer(kShellWindowId_NonLockScreenContainersContainer,
1211 "NonLockScreenContainersContainer", magnified_container);
1212 // Clip all windows inside this container, as half pixel of the window's
1213 // texture may become visible when the screen is scaled. crbug.com/368591.
1214 non_lock_screen_containers->layer()->SetMasksToBounds(true);
1216 aura::Window* lock_wallpaper_container =
1217 CreateContainer(kShellWindowId_LockScreenWallpaperContainer,
1218 "LockScreenWallpaperContainer", magnified_container);
1219 ::wm::SetChildWindowVisibilityChangesAnimated(lock_wallpaper_container);
1220 lock_wallpaper_container->SetLayoutManager(
1221 std::make_unique<FillLayoutManager>(lock_wallpaper_container));
1223 aura::Window* lock_screen_containers =
1224 CreateContainer(kShellWindowId_LockScreenContainersContainer,
1225 "LockScreenContainersContainer", magnified_container);
1226 aura::Window* lock_screen_related_containers = CreateContainer(
1227 kShellWindowId_LockScreenRelatedContainersContainer,
1228 "LockScreenRelatedContainersContainer", magnified_container);
1230 aura::Window* app_list_tablet_mode_container =
1231 CreateContainer(kShellWindowId_HomeScreenContainer, "HomeScreenContainer",
1232 non_lock_screen_containers);
1233 app_list_tablet_mode_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1236 CreateContainer(kShellWindowId_UnparentedContainer, "UnparentedContainer",
1237 non_lock_screen_containers);
1239 for (const auto& id : desks_util::GetDesksContainersIds()) {
1240 aura::Window* container = CreateContainer(
1241 id, desks_util::GetDeskContainerName(id), non_lock_screen_containers);
1242 ::wm::SetChildWindowVisibilityChangesAnimated(container);
1243 container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1244 container->SetProperty(kForceVisibleInMiniViewKey, true);
1245 window_util::SetChildrenUseExtendedHitRegionForWindow(container);
1247 // Hide the non-active containers.
1248 if (id != desks_util::GetActiveDeskContainerId()) {
1253 aura::Window* always_on_top_container =
1254 CreateContainer(kShellWindowId_AlwaysOnTopContainer,
1255 "AlwaysOnTopContainer", non_lock_screen_containers);
1256 ::wm::SetChildWindowVisibilityChangesAnimated(always_on_top_container);
1257 always_on_top_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1259 aura::Window* float_container =
1260 CreateContainer(kShellWindowId_FloatContainer, "FloatContainer",
1261 non_lock_screen_containers);
1262 wm::SetChildWindowVisibilityChangesAnimated(float_container);
1263 float_container->SetProperty(wm::kUsesScreenCoordinatesKey, true);
1264 window_util::SetChildrenUseExtendedHitRegionForWindow(float_container);
1266 aura::Window* app_list_container =
1267 CreateContainer(kShellWindowId_AppListContainer, "AppListContainer",
1268 non_lock_screen_containers);
1269 app_list_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1271 aura::Window* pip_container = CreateContainer(
1272 kShellWindowId_PipContainer, "PipContainer", non_lock_screen_containers);
1273 ::wm::SetChildWindowVisibilityChangesAnimated(pip_container);
1274 pip_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1276 aura::Window* arc_ime_parent_container = CreateContainer(
1277 kShellWindowId_ArcImeWindowParentContainer, "ArcImeWindowParentContainer",
1278 non_lock_screen_containers);
1279 arc_ime_parent_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1280 arc_ime_parent_container->SetLayoutManager(
1281 std::make_unique<ArcVirtualKeyboardContainerLayoutManager>(
1282 arc_ime_parent_container));
1283 aura::Window* arc_vk_container =
1284 CreateContainer(kShellWindowId_ArcVirtualKeyboardContainer,
1285 "ArcVirtualKeyboardContainer", arc_ime_parent_container);
1286 arc_vk_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1288 aura::Window* shelf_container_parent = lock_screen_related_containers;
1289 aura::Window* shelf_container = CreateContainer(
1290 kShellWindowId_ShelfContainer, "ShelfContainer", shelf_container_parent);
1291 shelf_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1292 shelf_container->SetProperty(kLockedToRootKey, true);
1294 aura::Window* shelf_bubble_container =
1295 CreateContainer(kShellWindowId_ShelfBubbleContainer,
1296 "ShelfBubbleContainer", non_lock_screen_containers);
1297 shelf_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1298 shelf_bubble_container->SetProperty(kLockedToRootKey, true);
1300 aura::Window* modal_container =
1301 CreateContainer(kShellWindowId_SystemModalContainer,
1302 "SystemModalContainer", non_lock_screen_containers);
1303 ::wm::SetChildWindowVisibilityChangesAnimated(modal_container);
1304 modal_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1305 window_util::SetChildrenUseExtendedHitRegionForWindow(modal_container);
1307 aura::Window* lock_container =
1308 CreateContainer(kShellWindowId_LockScreenContainer, "LockScreenContainer",
1309 lock_screen_containers);
1310 lock_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1312 aura::Window* lock_action_handler_container =
1313 CreateContainer(kShellWindowId_LockActionHandlerContainer,
1314 "LockActionHandlerContainer", lock_screen_containers);
1315 ::wm::SetChildWindowVisibilityChangesAnimated(lock_action_handler_container);
1316 lock_action_handler_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1319 aura::Window* lock_modal_container =
1320 CreateContainer(kShellWindowId_LockSystemModalContainer,
1321 "LockSystemModalContainer", lock_screen_containers);
1322 ::wm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
1323 lock_modal_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1324 window_util::SetChildrenUseExtendedHitRegionForWindow(lock_modal_container);
1326 aura::Window* power_menu_container =
1327 CreateContainer(kShellWindowId_PowerMenuContainer, "PowerMenuContainer",
1328 GetPowerMenuContainerParent(GetRootWindow()));
1329 power_menu_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1331 aura::Window* settings_bubble_container =
1332 CreateContainer(kShellWindowId_SettingBubbleContainer,
1333 "SettingBubbleContainer", lock_screen_related_containers);
1334 ::wm::SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
1335 settings_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1336 settings_bubble_container->SetProperty(kLockedToRootKey, true);
1338 aura::Window* help_bubble_container =
1339 CreateContainer(kShellWindowId_HelpBubbleContainer, "HelpBubbleContainer",
1340 lock_screen_related_containers);
1341 ::wm::SetChildWindowVisibilityChangesAnimated(help_bubble_container);
1342 help_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1344 aura::Window* virtual_keyboard_parent_container = CreateContainer(
1345 kShellWindowId_ImeWindowParentContainer, "ImeWindowParentContainer",
1346 lock_screen_related_containers);
1347 virtual_keyboard_parent_container->SetProperty(
1348 ::wm::kUsesScreenCoordinatesKey, true);
1349 virtual_keyboard_parent_container->SetLayoutManager(
1350 std::make_unique<VirtualKeyboardContainerLayoutManager>(
1351 virtual_keyboard_parent_container));
1352 aura::Window* virtual_keyboard_container = CreateContainer(
1353 kShellWindowId_VirtualKeyboardContainer, "VirtualKeyboardContainer",
1354 virtual_keyboard_parent_container);
1355 virtual_keyboard_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1357 virtual_keyboard_container->SetLayoutManager(
1358 std::make_unique<keyboard::KeyboardLayoutManager>(
1359 keyboard::KeyboardUIController::Get()));
1361 aura::Window* accessibility_panel_container = CreateContainer(
1362 kShellWindowId_AccessibilityPanelContainer, "AccessibilityPanelContainer",
1363 lock_screen_related_containers);
1364 ::wm::SetChildWindowVisibilityChangesAnimated(accessibility_panel_container);
1365 accessibility_panel_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1367 accessibility_panel_container->SetProperty(kLockedToRootKey, true);
1368 accessibility_panel_container->SetLayoutManager(
1369 std::make_unique<AccessibilityPanelLayoutManager>());
1371 aura::Window* menu_container =
1372 CreateContainer(kShellWindowId_MenuContainer, "MenuContainer",
1373 lock_screen_related_containers);
1374 ::wm::SetChildWindowVisibilityChangesAnimated(menu_container);
1375 menu_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1377 aura::Window* accessibility_bubble_container = CreateContainer(
1378 kShellWindowId_AccessibilityBubbleContainer,
1379 "AccessibilityBubbleContainer", lock_screen_related_containers);
1380 accessibility_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1383 aura::Window* drag_drop_container = CreateContainer(
1384 kShellWindowId_DragImageAndTooltipContainer,
1385 "DragImageAndTooltipContainer", lock_screen_related_containers);
1386 ::wm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
1387 drag_drop_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1389 aura::Window* overlay_container =
1390 CreateContainer(kShellWindowId_OverlayContainer, "OverlayContainer",
1391 lock_screen_related_containers);
1392 overlay_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1393 overlay_container->SetLayoutManager(
1394 std::make_unique<OverlayLayoutManager>(overlay_container));
1396 aura::Window* ambient_container =
1397 CreateContainer(kShellWindowId_AmbientModeContainer,
1398 "AmbientModeContainer", lock_screen_related_containers);
1399 ::wm::SetChildWindowVisibilityChangesAnimated(ambient_container);
1400 ambient_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1401 ambient_container->SetLayoutManager(
1402 std::make_unique<FillLayoutManager>(ambient_container));
1404 aura::Window* mouse_cursor_container =
1405 CreateContainer(kShellWindowId_MouseCursorContainer,
1406 "MouseCursorContainer", magnified_container);
1407 mouse_cursor_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1409 aura::Window* always_on_top_wallpaper_container =
1410 CreateContainer(kShellWindowId_AlwaysOnTopWallpaperContainer,
1411 "AlwaysOnTopWallpaperContainer", magnified_container);
1412 always_on_top_wallpaper_container->SetLayoutManager(
1413 std::make_unique<FillLayoutManager>(always_on_top_wallpaper_container));
1415 CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
1416 "PowerButtonAnimationContainer", magnified_container);
1418 // Make sure booting animation container is always on top of all other
1419 // siblings under the `magnified_container`.
1420 if (ash::features::IsOobeSimonEnabled()) {
1421 aura::Window* booting_animation_container =
1422 CreateContainer(kShellWindowId_BootingAnimationContainer,
1423 "BootingAnimationContainer", magnified_container);
1424 booting_animation_container->SetLayoutManager(
1425 std::make_unique<FillLayoutManager>(booting_animation_container));
1429 aura::Window* RootWindowController::CreateContainer(int window_id,
1431 aura::Window* parent) {
1432 aura::Window* window =
1433 new aura::Window(nullptr, aura::client::WINDOW_TYPE_UNKNOWN);
1434 window->Init(ui::LAYER_NOT_DRAWN);
1435 window->SetId(window_id);
1436 window->SetName(name);
1437 parent->AddChild(window);
1438 if (window_id != kShellWindowId_UnparentedContainer) {
1441 root_window_layout_manager_->AddContainer(window);
1445 void RootWindowController::CreateSystemWallpaper(
1446 RootWindowType root_window_type) {
1447 SkColor color = SK_ColorBLACK;
1448 // The splash screen appears on the primary display at boot. If this is a
1449 // secondary monitor (either connected at boot or connected later) or if the
1450 // browser restarted for a second login then don't use the boot color.
1451 const bool is_boot_splash_screen =
1452 root_window_type == RootWindowType::PRIMARY &&
1453 base::CommandLine::ForCurrentProcess()->HasSwitch(
1454 switches::kFirstExecAfterBoot);
1455 if (is_boot_splash_screen) {
1456 color = kChromeOsBootColor;
1459 std::make_unique<SystemWallpaperController>(GetRootWindow(), color);
1462 AccessibilityPanelLayoutManager*
1463 RootWindowController::GetAccessibilityPanelLayoutManager() const {
1464 aura::Window* container = const_cast<aura::Window*>(
1465 GetContainer(kShellWindowId_AccessibilityPanelContainer));
1466 auto* layout_manager = static_cast<AccessibilityPanelLayoutManager*>(
1467 container->layout_manager());
1468 return layout_manager;
1471 void RootWindowController::OnMenuClosed() {
1472 root_window_menu_model_adapter_.reset();
1473 sort_apps_submenu_.reset();
1474 shelf_->UpdateVisibilityState();