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"
12 #include "ash/accessibility/chromevox/touch_exploration_controller.h"
13 #include "ash/accessibility/chromevox/touch_exploration_manager.h"
14 #include "ash/accessibility/ui/accessibility_panel_layout_manager.h"
15 #include "ash/ambient/ambient_controller.h"
16 #include "ash/app_list/app_list_controller_impl.h"
17 #include "ash/app_menu/app_menu_model_adapter.h"
18 #include "ash/constants/ash_constants.h"
19 #include "ash/constants/ash_features.h"
20 #include "ash/constants/ash_switches.h"
21 #include "ash/curtain/security_curtain_widget_controller.h"
22 #include "ash/focus_cycler.h"
23 #include "ash/host/ash_window_tree_host.h"
24 #include "ash/keyboard/arc/arc_virtual_keyboard_container_layout_manager.h"
25 #include "ash/keyboard/keyboard_controller_impl.h"
26 #include "ash/keyboard/ui/keyboard_layout_manager.h"
27 #include "ash/keyboard/ui/keyboard_ui_controller.h"
28 #include "ash/keyboard/ui/keyboard_util.h"
29 #include "ash/keyboard/virtual_keyboard_container_layout_manager.h"
30 #include "ash/lock_screen_action/lock_screen_action_background_controller.h"
31 #include "ash/login_status.h"
32 #include "ash/public/cpp/app_menu_constants.h"
33 #include "ash/public/cpp/shelf_types.h"
34 #include "ash/public/cpp/shell_window_ids.h"
35 #include "ash/public/cpp/window_properties.h"
36 #include "ash/resources/vector_icons/vector_icons.h"
37 #include "ash/root_window_settings.h"
38 #include "ash/scoped_animation_disabler.h"
39 #include "ash/screen_util.h"
40 #include "ash/session/session_controller_impl.h"
41 #include "ash/shelf/shelf.h"
42 #include "ash/shelf/shelf_context_menu_model.h"
43 #include "ash/shelf/shelf_layout_manager.h"
44 #include "ash/shelf/shelf_widget.h"
45 #include "ash/shelf/shelf_window_targeter.h"
46 #include "ash/shell.h"
47 #include "ash/strings/grit/ash_strings.h"
48 #include "ash/style/ash_color_provider_source.h"
49 #include "ash/system/status_area_widget.h"
50 #include "ash/system/tray/tray_background_view.h"
51 #include "ash/system/unified/unified_system_tray.h"
52 #include "ash/touch/touch_hud_debug.h"
53 #include "ash/touch/touch_hud_projection.h"
54 #include "ash/touch/touch_observer_hud.h"
55 #include "ash/wallpaper/wallpaper_widget_controller.h"
56 #include "ash/wm/always_on_top_controller.h"
57 #include "ash/wm/container_finder.h"
58 #include "ash/wm/desks/desks_controller.h"
59 #include "ash/wm/desks/desks_util.h"
60 #include "ash/wm/fullscreen_window_finder.h"
61 #include "ash/wm/lock_action_handler_layout_manager.h"
62 #include "ash/wm/lock_layout_manager.h"
63 #include "ash/wm/mru_window_tracker.h"
64 #include "ash/wm/overlay_layout_manager.h"
65 #include "ash/wm/overview/overview_controller.h"
66 #include "ash/wm/overview/overview_session.h"
67 #include "ash/wm/root_window_layout_manager.h"
68 #include "ash/wm/splitview/split_view_controller.h"
69 #include "ash/wm/splitview/split_view_utils.h"
70 #include "ash/wm/stacking_controller.h"
71 #include "ash/wm/switchable_windows.h"
72 #include "ash/wm/system_modal_container_layout_manager.h"
73 #include "ash/wm/system_wallpaper_controller.h"
74 #include "ash/wm/tablet_mode/tablet_mode_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/work_area_insets.h"
79 #include "ash/wm/workspace/workspace_layout_manager.h"
80 #include "ash/wm/workspace_controller.h"
81 #include "base/bind.h"
82 #include "base/command_line.h"
83 #include "base/cxx17_backports.h"
84 #include "base/metrics/histogram_macros.h"
85 #include "base/ranges/algorithm.h"
86 #include "base/time/time.h"
87 #include "ui/aura/client/aura_constants.h"
88 #include "ui/aura/client/drag_drop_client.h"
89 #include "ui/aura/client/screen_position_client.h"
90 #include "ui/aura/client/window_types.h"
91 #include "ui/aura/null_window_targeter.h"
92 #include "ui/aura/window.h"
93 #include "ui/aura/window_event_dispatcher.h"
94 #include "ui/aura/window_observer.h"
95 #include "ui/aura/window_tracker.h"
96 #include "ui/base/l10n/l10n_util.h"
97 #include "ui/base/models/menu_model.h"
98 #include "ui/base/models/simple_menu_model.h"
99 #include "ui/compositor/layer.h"
100 #include "ui/display/types/display_constants.h"
101 #include "ui/events/event_utils.h"
102 #include "ui/views/controls/menu/menu_model_adapter.h"
103 #include "ui/views/controls/menu/menu_runner.h"
104 #include "ui/views/view_model.h"
105 #include "ui/views/view_model_utils.h"
106 #include "ui/views/widget/widget.h"
107 #include "ui/wm/core/capture_controller.h"
108 #include "ui/wm/core/coordinate_conversion.h"
109 #include "ui/wm/core/visibility_controller.h"
110 #include "ui/wm/core/window_properties.h"
111 #include "ui/wm/core/window_util.h"
112 #include "ui/wm/public/tooltip_client.h"
117 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())
149 aura::Window* target = target_path.back();
150 target_path.pop_back();
151 aura::Window* blocking = blocking_path.back();
152 blocking_path.pop_back();
154 // Still on the same path, continue.
155 if (target == blocking)
158 // This can happen only if unparented window is passed because
159 // first element must be the same root.
160 if (!target->parent() || !blocking->parent())
163 aura::Window* common_parent = target->parent();
164 DCHECK_EQ(common_parent, blocking->parent());
165 const aura::Window::Windows& windows = common_parent->children();
166 auto blocking_iter = base::ranges::find(windows, blocking);
167 // If the target window is above blocking window, the window can handle
169 return std::find(blocking_iter, windows.end(), target) != windows.end();
175 // Scales |value| that is originally between 0 and |src_max| to be between
177 float ToRelativeValue(int value, int src_max, int dst_max) {
178 return static_cast<float>(value) / static_cast<float>(src_max) * dst_max;
181 // Uses ToRelativeValue() to scale the origin of |bounds_in_out|. The
182 // width/height are not changed.
183 void MoveOriginRelativeToSize(const gfx::Size& src_size,
184 const gfx::Size& dst_size,
185 gfx::Rect* bounds_in_out) {
186 gfx::Point origin = bounds_in_out->origin();
187 bounds_in_out->set_origin(gfx::Point(
188 ToRelativeValue(origin.x(), src_size.width(), dst_size.width()),
189 ToRelativeValue(origin.y(), src_size.height(), dst_size.height())));
192 // Reparents |window| to |new_parent|.
193 void ReparentWindow(aura::Window* window, aura::Window* new_parent) {
194 const gfx::Size src_size = window->parent()->bounds().size();
195 const gfx::Size dst_size = new_parent->bounds().size();
196 // Update the restore bounds to make it relative to the display.
197 WindowState* state = WindowState::Get(window);
198 gfx::Rect restore_bounds;
199 const bool has_restore_bounds = state && state->HasRestoreBounds();
201 const bool update_bounds =
202 state && (state->IsNormalOrSnapped() || state->IsMinimized());
203 gfx::Rect work_area_in_new_parent =
204 screen_util::GetDisplayWorkAreaBoundsInParent(new_parent);
206 gfx::Rect local_bounds;
208 local_bounds = state->window()->bounds();
209 MoveOriginRelativeToSize(src_size, dst_size, &local_bounds);
210 local_bounds.AdjustToFit(work_area_in_new_parent);
213 if (has_restore_bounds) {
214 restore_bounds = state->GetRestoreBoundsInParent();
215 MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds);
216 restore_bounds.AdjustToFit(work_area_in_new_parent);
219 new_parent->AddChild(window);
221 // Docked windows have bounds handled by the layout manager in AddChild().
223 window->SetBounds(local_bounds);
225 if (has_restore_bounds)
226 state->SetRestoreBoundsInParent(restore_bounds);
229 // Reparents the appropriate set of windows from |src| to |dst|.
230 void ReparentAllWindows(aura::Window* src, aura::Window* dst) {
231 // Set of windows to move.
232 constexpr int kContainerIdsToMove[] = {
233 kShellWindowId_AlwaysOnTopContainer,
234 kShellWindowId_FloatContainer,
235 kShellWindowId_PipContainer,
236 kShellWindowId_SystemModalContainer,
237 kShellWindowId_LockSystemModalContainer,
238 kShellWindowId_UnparentedContainer,
239 kShellWindowId_OverlayContainer,
240 kShellWindowId_LockActionHandlerContainer,
241 kShellWindowId_MenuContainer,
243 constexpr int kExtraContainerIdsToMoveInUnifiedMode[] = {
244 kShellWindowId_LockScreenContainer,
247 // Desk container ids are different depends on whether Bento feature is
249 std::vector<int> container_ids = desks_util::GetDesksContainersIds();
250 for (const int id : kContainerIdsToMove)
251 container_ids.emplace_back(id);
253 // Check the display mode as this is also necessary when trasitioning between
254 // mirror and unified mode.
255 if (Shell::Get()->display_manager()->current_default_multi_display_mode() ==
256 display::DisplayManager::UNIFIED) {
257 for (const int id : kExtraContainerIdsToMoveInUnifiedMode)
258 container_ids.emplace_back(id);
261 const std::vector<aura::Window*> mru_list =
262 Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks);
263 for (int id : container_ids) {
264 aura::Window* src_container = src->GetChildById(id);
265 aura::Window* dst_container = dst->GetChildById(id);
266 const bool switchable_container = IsSwitchableContainer(src_container);
267 while (!src_container->children().empty()) {
268 // Restart iteration from the source container windows each time as they
269 // may change as a result of moving other windows.
270 const aura::Window::Windows& src_container_children =
271 src_container->children();
272 auto iter = src_container_children.rbegin();
273 while (iter != src_container_children.rend() &&
274 SystemModalContainerLayoutManager::IsModalBackground(*iter)) {
277 // If the entire window list is modal background windows then stop.
278 if (iter == src_container_children.rend())
281 // |iter| is invalidated after ReparentWindow. Cache it to use afterwards.
282 aura::Window* const window = *iter;
283 ReparentWindow(window, dst_container);
285 aura::Window* stacking_target = nullptr;
286 if (switchable_container) {
287 // Find the first window that comes after |window| in the MRU list that
288 // shares the same parent.
289 bool found_window = false;
290 for (aura::Window* window_iter : mru_list) {
291 // First determine the position of |window| in the |mru_list|.
292 if (!found_window && window == window_iter) {
297 if (!found_window || window_iter->parent() != dst_container)
300 // Once |window| is found, the next item in |mru_list| with the same
301 // parent (container) is the stacking target.
302 stacking_target = window_iter;
307 // |stacking_target| may be null if |switchable_container| is false, which
308 // means the children of that container wouldn't be in the MRU list or if
309 // |window| was the last item in the MRU list with parent id |id|. In
310 // this case stack |window| at the bottom.
312 dst_container->StackChildAbove(window, stacking_target);
314 dst_container->StackChildAtBottom(window);
319 bool ShouldDestroyWindowInCloseChildWindows(aura::Window* window) {
320 return window->owned_by_parent();
323 // Clears the workspace controllers from the properties of all virtual desks
324 // containers in |root|.
325 void ClearWorkspaceControllers(aura::Window* root) {
326 for (auto* desk_container : desks_util::GetDesksContainers(root))
327 SetWorkspaceController(desk_container, nullptr);
330 class RootWindowTargeter : public aura::WindowTargeter {
332 RootWindowTargeter() = default;
334 RootWindowTargeter(const RootWindowTargeter&) = delete;
335 RootWindowTargeter& operator=(const RootWindowTargeter&) = delete;
337 ~RootWindowTargeter() override = default;
340 aura::Window* FindTargetForLocatedEvent(aura::Window* window,
341 ui::LocatedEvent* event) override {
342 if (!window->parent() && !window->bounds().Contains(event->location()) &&
343 IsEventInsideDisplayForTelemetryHack(window, event)) {
344 auto* dispatcher = window->GetHost()->dispatcher();
345 bool has_capture_target = !!dispatcher->mouse_pressed_handler() ||
346 !!aura::client::GetCaptureWindow(window);
348 // Make sure that event location is within the root window bounds if
349 // 1) mouse event isn't captured.
350 // 2) A mouse is clicked without movement and capture.
352 // The event can be outside on some scale factor due to rounding, or due
353 // to not well calibrated a touch screen, or Detect this situation and
354 // adjust the location.
355 bool bounded_click = ShouldConstrainMouseClick(event, has_capture_target);
356 if (!has_capture_target || bounded_click) {
357 gfx::Point new_location =
358 FitPointToBounds(event->location(), window->bounds());
359 // Do not change |location_f|. It's used to compute pixel position and
360 // such client should know what they're doing.
361 event->set_location(new_location);
362 event->set_root_location(new_location);
365 return aura::WindowTargeter::FindTargetForLocatedEvent(window, event);
368 // Stop-gap workaround for telemetry tests that send events far outside of the
369 // display (e.g. 512, -4711). Fix the test and remove this (crbgu.com/904623).
370 bool IsEventInsideDisplayForTelemetryHack(aura::Window* window,
371 ui::LocatedEvent* event) {
372 constexpr int ExtraMarginForTelemetryTest = -10;
373 gfx::Rect bounds = window->bounds();
374 bounds.Inset(ExtraMarginForTelemetryTest);
375 return bounds.Contains(event->location());
379 // Returns true if the mouse event should be constrainted.
380 bool ShouldConstrainMouseClick(ui::LocatedEvent* event,
381 bool has_capture_target) {
382 if (event->type() == ui::ET_MOUSE_PRESSED && !has_capture_target) {
383 last_mouse_event_type_ = ui::ET_MOUSE_PRESSED;
386 if (last_mouse_event_type_ == ui::ET_MOUSE_PRESSED &&
387 event->type() == ui::ET_MOUSE_RELEASED && has_capture_target) {
388 last_mouse_event_type_ = ui::ET_UNKNOWN;
391 // For other cases, reset the state
392 if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED)
393 last_mouse_event_type_ = ui::ET_UNKNOWN;
397 gfx::Point FitPointToBounds(const gfx::Point p, const gfx::Rect& bounds) {
398 return gfx::Point(base::clamp(p.x(), bounds.x(), bounds.right() - 1),
399 base::clamp(p.y(), bounds.y(), bounds.bottom() - 1));
402 ui::EventType last_mouse_event_type_ = ui::ET_UNKNOWN;
405 class RootWindowMenuModelAdapter : public AppMenuModelAdapter {
407 RootWindowMenuModelAdapter(std::unique_ptr<ui::SimpleMenuModel> model,
408 views::Widget* widget_owner,
409 ui::MenuSourceType source_type,
410 base::OnceClosure on_menu_closed_callback,
412 : AppMenuModelAdapter(std::string(),
416 std::move(on_menu_closed_callback),
419 RootWindowMenuModelAdapter(const RootWindowMenuModelAdapter&) = delete;
420 RootWindowMenuModelAdapter& operator=(const RootWindowMenuModelAdapter&) =
423 ~RootWindowMenuModelAdapter() override = default;
426 // AppMenuModelAdapter overrides:
427 void RecordHistogramOnMenuClosed() override {
428 const base::TimeDelta user_journey_time =
429 base::TimeTicks::Now() - menu_open_time();
431 UMA_HISTOGRAM_TIMES("Apps.ContextMenuUserJourneyTime.Desktop",
433 UMA_HISTOGRAM_ENUMERATION("Apps.ContextMenuShowSource.Desktop",
434 source_type(), ui::MENU_SOURCE_TYPE_LAST);
435 if (is_tablet_mode()) {
436 UMA_HISTOGRAM_TIMES("Apps.ContextMenuUserJourneyTime.Desktop.TabletMode",
438 UMA_HISTOGRAM_ENUMERATION("Apps.ContextMenuShowSource.Desktop.TabletMode",
439 source_type(), ui::MENU_SOURCE_TYPE_LAST);
442 "Apps.ContextMenuUserJourneyTime.Desktop.ClamshellMode",
444 UMA_HISTOGRAM_ENUMERATION(
445 "Apps.ContextMenuShowSource.Desktop.ClamshellMode", source_type(),
446 ui::MENU_SOURCE_TYPE_LAST);
451 // A layout manager that fills its container when the child window's resize
452 // behavior is set to be maximizable.
453 class FillLayoutManager : public aura::LayoutManager {
455 explicit FillLayoutManager(aura::Window* container) : container_(container) {}
456 ~FillLayoutManager() override = default;
457 FillLayoutManager(const FillLayoutManager&) = delete;
458 FillLayoutManager& operator=(const FillLayoutManager&) = delete;
460 // aura::LayoutManager:
461 void OnWindowResized() override { Relayout(); }
462 void OnWindowAddedToLayout(aura::Window* child) override { Relayout(); }
463 void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
464 void OnWindowRemovedFromLayout(aura::Window* child) override {}
465 void OnChildWindowVisibilityChanged(aura::Window* child,
466 bool visible) override {}
467 void SetChildBounds(aura::Window* child,
468 const gfx::Rect& requested_bounds) override {}
472 // Fill the window that is set to be maximizable.
473 const gfx::Rect fullscreen(container_->bounds().size());
474 for (auto* child : container_->children()) {
475 const int resize_behavior =
476 child->GetProperty(aura::client::kResizeBehaviorKey);
477 if (resize_behavior & aura::client::kResizeBehaviorCanMaximize)
478 SetChildBoundsDirect(child, fullscreen);
482 aura::Window* container_;
488 std::vector<RootWindowController*>*
489 RootWindowController::root_window_controllers_ = nullptr;
491 RootWindowController::~RootWindowController() {
493 DCHECK(!wallpaper_widget_controller_.get());
494 work_area_insets_.reset();
496 // The CaptureClient needs to be around for as long as the RootWindow is
498 capture_client_.reset();
499 root_window_controllers_->erase(
500 base::ranges::find(*root_window_controllers_, this));
503 RootWindowController* RootWindowController::CreateForPrimaryDisplay(
504 AshWindowTreeHost* host) {
505 RootWindowController* controller = new RootWindowController(host);
506 controller->Init(RootWindowType::PRIMARY);
510 RootWindowController* RootWindowController::CreateForSecondaryDisplay(
511 AshWindowTreeHost* host) {
512 RootWindowController* controller = new RootWindowController(host);
513 controller->Init(RootWindowType::SECONDARY);
518 RootWindowController* RootWindowController::ForWindow(
519 const aura::Window* window) {
521 CHECK(Shell::HasInstance());
522 return GetRootWindowSettings(window->GetRootWindow())->controller;
526 RootWindowController* RootWindowController::ForTargetRootWindow() {
527 CHECK(Shell::HasInstance());
528 return ForWindow(Shell::GetRootWindowForNewWindows());
531 aura::WindowTreeHost* RootWindowController::GetHost() {
532 return window_tree_host_;
535 const aura::WindowTreeHost* RootWindowController::GetHost() const {
536 return window_tree_host_;
539 aura::Window* RootWindowController::GetRootWindow() {
540 return GetHost()->window();
543 const aura::Window* RootWindowController::GetRootWindow() const {
544 return GetHost()->window();
547 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
548 return shelf_->shelf_layout_manager();
551 SystemModalContainerLayoutManager*
552 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
553 aura::Window* modal_container = nullptr;
555 aura::Window* window_container = GetContainerForWindow(window);
556 if (window_container &&
557 window_container->GetId() >= kShellWindowId_LockScreenContainer) {
558 modal_container = GetContainer(kShellWindowId_LockSystemModalContainer);
560 modal_container = GetContainer(kShellWindowId_SystemModalContainer);
563 int modal_window_id =
564 Shell::Get()->session_controller()->IsUserSessionBlocked()
565 ? kShellWindowId_LockSystemModalContainer
566 : kShellWindowId_SystemModalContainer;
567 modal_container = GetContainer(modal_window_id);
569 return modal_container ? static_cast<SystemModalContainerLayoutManager*>(
570 modal_container->layout_manager())
574 StatusAreaWidget* RootWindowController::GetStatusAreaWidget() {
575 ShelfWidget* shelf_widget = shelf_->shelf_widget();
576 return shelf_widget ? shelf_widget->status_area_widget() : nullptr;
579 bool RootWindowController::IsSystemTrayVisible() {
580 TrayBackgroundView* tray = GetStatusAreaWidget()->unified_system_tray();
581 return tray && tray->GetWidget()->IsVisible() && tray->GetVisible();
584 bool RootWindowController::CanWindowReceiveEvents(aura::Window* window) {
585 if (GetRootWindow() != window->GetRootWindow())
588 aura::Window* blocking_container = nullptr;
589 aura::Window* modal_container = nullptr;
590 window_util::GetBlockingContainersForRoot(
591 GetRootWindow(), &blocking_container, &modal_container);
592 SystemModalContainerLayoutManager* modal_layout_manager = nullptr;
593 modal_layout_manager = static_cast<SystemModalContainerLayoutManager*>(
594 modal_container->layout_manager());
596 if (modal_layout_manager->has_window_dimmer())
597 blocking_container = modal_container;
599 modal_container = nullptr; // Don't check modal dialogs.
601 // In normal session.
602 if (!blocking_container)
605 if (!IsWindowAboveContainer(window, blocking_container))
608 if (modal_container) {
609 // If the window is in the target modal container, only allow the top most
611 if (modal_container->Contains(window))
612 return modal_layout_manager->IsPartOfActiveModalWindow(window);
613 // Don't allow shelf to process events if there is a visible modal dialog.
614 if (IsInShelfContainer(window->parent()))
620 aura::Window* RootWindowController::FindEventTarget(
621 const gfx::Point& location_in_screen) {
622 gfx::Point location_in_root(location_in_screen);
623 aura::Window* root_window = GetRootWindow();
624 ::wm::ConvertPointFromScreen(root_window, &location_in_root);
625 ui::MouseEvent test_event(ui::ET_MOUSE_MOVED, location_in_root,
626 location_in_root, ui::EventTimeForNow(),
627 ui::EF_NONE, ui::EF_NONE);
628 ui::EventTarget* event_handler =
629 root_window->GetHost()
631 ->GetDefaultEventTargeter()
632 ->FindTargetForEvent(root_window, &test_event);
633 return static_cast<aura::Window*>(event_handler);
636 gfx::Point RootWindowController::GetLastMouseLocationInRoot() {
637 return window_tree_host_->dispatcher()->GetLastMouseLocationInRoot();
640 aura::Window* RootWindowController::GetContainer(int container_id) {
641 return GetRootWindow()->GetChildById(container_id);
644 const aura::Window* RootWindowController::GetContainer(int container_id) const {
645 return window_tree_host_->window()->GetChildById(container_id);
648 void RootWindowController::Shutdown() {
649 auto targeter = GetRootWindow()->SetEventTargeter(
650 std::make_unique<aura::NullWindowTargeter>());
652 touch_exploration_manager_.reset();
653 wallpaper_widget_controller_.reset();
654 CloseAmbientWidget(/*immediately=*/true);
657 aura::Window* root_window = GetRootWindow();
658 GetRootWindowSettings(root_window)->controller = nullptr;
659 // Forget with the display ID so that display lookup
660 // ends up with invalid display.
661 GetRootWindowSettings(root_window)->display_id = display::kInvalidDisplayId;
663 ash_host_->PrepareForShutdown();
665 system_wallpaper_.reset();
666 security_curtain_widget_controller_.reset();
667 lock_screen_action_background_controller_.reset();
668 aura::client::SetScreenPositionClient(root_window, nullptr);
670 // The targeter may still on the stack, so delete it later.
672 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
673 std::move(targeter));
677 void RootWindowController::CloseChildWindows() {
678 // Child windows can be closed by secondary monitor disconnection, Shell
679 // shutdown, or both. Avoid running the related cleanup code twice.
680 if (did_close_child_windows_)
682 did_close_child_windows_ = true;
684 aura::Window* root = GetRootWindow();
686 Shell::Get()->desks_controller()->OnRootWindowClosing(root);
688 // Notify the keyboard controller before closing child windows and shutting
689 // down associated layout managers.
690 Shell::Get()->keyboard_controller()->OnRootWindowClosing(root);
692 OverviewController* overview_controller = Shell::Get()->overview_controller();
693 if (overview_controller && overview_controller->InOverviewSession())
694 overview_controller->overview_session()->OnRootWindowClosing(root);
696 shelf_->ShutdownShelfWidget();
698 ClearWorkspaceControllers(root);
699 always_on_top_controller_->ClearLayoutManagers();
701 // Explicitly destroy top level windows. We do this because such windows may
702 // query the RootWindow for state.
703 aura::WindowTracker non_toplevel_windows;
704 non_toplevel_windows.Add(root);
705 while (!non_toplevel_windows.windows().empty()) {
706 aura::Window* non_toplevel_window = non_toplevel_windows.Pop();
707 aura::WindowTracker toplevel_windows;
708 for (aura::Window* child : non_toplevel_window->children()) {
709 if (!ShouldDestroyWindowInCloseChildWindows(child))
711 if (child->delegate())
712 toplevel_windows.Add(child);
714 non_toplevel_windows.Add(child);
716 while (!toplevel_windows.windows().empty())
717 delete toplevel_windows.Pop();
720 // Reset layout manager so that it won't fire unnecessary layout evetns.
721 root->SetLayoutManager(nullptr);
722 // And then remove the containers.
723 while (!root->children().empty()) {
724 aura::Window* child = root->children()[0];
725 if (ShouldDestroyWindowInCloseChildWindows(child))
728 root->RemoveChild(child);
731 // Removing the containers destroys ShelfLayoutManager. ShelfWidget outlives
732 // ShelfLayoutManager because ShelfLayoutManager holds a pointer to it.
733 shelf_->DestroyShelfWidget();
735 ::wm::SetTooltipClient(GetRootWindow(), nullptr);
738 void RootWindowController::MoveWindowsTo(aura::Window* dst) {
739 // Suspend unnecessary updates of the shelf visibility indefinitely since it
741 if (GetShelfLayoutManager())
742 GetShelfLayoutManager()->SuspendVisibilityUpdateForShutdown();
744 // Clear the workspace controller to avoid a lot of unnecessary operations
745 // when window are removed.
746 // TODO(afakhry): Should we also clear the WorkspaceLayoutManagers of the pip,
747 // always-on-top, and other containers?
748 aura::Window* root = GetRootWindow();
749 ClearWorkspaceControllers(root);
751 ReparentAllWindows(root, dst);
754 void RootWindowController::InitTouchHuds() {
755 // Enable touch debugging features when each display is initialized.
756 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
757 if (command_line->HasSwitch(switches::kAshTouchHud))
758 set_touch_hud_debug(new TouchHudDebug(GetRootWindow()));
760 // TouchHudProjection manages its own lifetime.
761 if (command_line->HasSwitch(switches::kShowTaps))
762 touch_hud_projection_ = new TouchHudProjection(GetRootWindow());
765 aura::Window* RootWindowController::GetWindowForFullscreenMode() {
766 return GetWindowForFullscreenModeInRoot(GetRootWindow());
769 bool RootWindowController::IsInFullscreenMode() {
770 auto* window = GetWindowForFullscreenMode();
771 return window && WindowState::Get(window)->GetHideShelfWhenFullscreen();
774 void RootWindowController::SetTouchAccessibilityAnchorPoint(
775 const gfx::Point& anchor_point) {
776 if (touch_exploration_manager_)
777 touch_exploration_manager_->SetTouchAccessibilityAnchorPoint(anchor_point);
780 void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen,
781 ui::MenuSourceType source_type) {
782 const int64_t display_id = display::Screen::GetScreen()
783 ->GetDisplayNearestWindow(GetRootWindow())
786 const bool tablet_mode =
787 Shell::Get()->tablet_mode_controller()->InTabletMode();
788 root_window_menu_model_adapter_ =
789 std::make_unique<RootWindowMenuModelAdapter>(
790 std::make_unique<ShelfContextMenuModel>(nullptr, display_id),
791 wallpaper_widget_controller()->GetWidget(), source_type,
792 base::BindOnce(&RootWindowController::OnMenuClosed,
793 base::Unretained(this)),
796 // Appends the apps sort options in ShelfContextMenuModel in tablet mode. Note
797 // that the launcher UI is fullscreen in tablet mode, so the whole root window
798 // can be perceived by users to be part of the launcher.
799 auto* const app_list_controller = Shell::Get()->app_list_controller();
800 if (features::IsLauncherAppSortEnabled() && tablet_mode &&
801 app_list_controller->IsVisible(display_id) &&
802 app_list_controller->GetCurrentAppListPage() ==
803 AppListState::kStateApps) {
804 ui::SimpleMenuModel* menu_model = root_window_menu_model_adapter_->model();
805 sort_apps_submenu_ = std::make_unique<ui::SimpleMenuModel>(
806 static_cast<ShelfContextMenuModel*>(menu_model));
807 sort_apps_submenu_->AddItemWithIcon(
808 REORDER_BY_NAME_ALPHABETICAL,
809 l10n_util::GetStringUTF16(
810 IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_BY_NAME),
811 ui::ImageModel::FromVectorIcon(kSortAlphabeticalIcon,
812 ui::kColorAshSystemUIMenuIcon));
813 sort_apps_submenu_->AddItemWithIcon(
815 l10n_util::GetStringUTF16(
816 IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_BY_COLOR),
817 ui::ImageModel::FromVectorIcon(kSortColorIcon,
818 ui::kColorAshSystemUIMenuIcon));
819 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
820 menu_model->AddSubMenuWithIcon(
822 l10n_util::GetStringUTF16(
823 IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_TITLE),
824 sort_apps_submenu_.get(),
825 ui::ImageModel::FromVectorIcon(kReorderIcon,
826 ui::kColorAshSystemUIMenuIcon));
828 // Append the "Show all suggestions" / "Hide all suggestions" item.
829 menu_model->AddSeparator(ui::NORMAL_SEPARATOR);
830 if (app_list_controller->ShouldHideContinueSection()) {
831 menu_model->AddItemWithIcon(
832 ShelfContextMenuModel::MENU_SHOW_CONTINUE_SECTION,
833 l10n_util::GetStringUTF16(IDS_ASH_LAUNCHER_SHOW_CONTINUE_SECTION),
834 ui::ImageModel::FromVectorIcon(kLauncherShowContinueSectionIcon,
835 ui::kColorAshSystemUIMenuIcon));
837 menu_model->AddItemWithIcon(
838 ShelfContextMenuModel::MENU_HIDE_CONTINUE_SECTION,
839 l10n_util::GetStringUTF16(IDS_ASH_LAUNCHER_HIDE_CONTINUE_SECTION),
840 ui::ImageModel::FromVectorIcon(kLauncherHideContinueSectionIcon,
841 ui::kColorAshSystemUIMenuIcon));
845 root_window_menu_model_adapter_->Run(
846 gfx::Rect(location_in_screen, gfx::Size()),
847 views::MenuAnchorPosition::kBubbleRight,
848 views::MenuRunner::CONTEXT_MENU |
849 views::MenuRunner::USE_ASH_SYS_UI_LAYOUT |
850 views::MenuRunner::FIXED_ANCHOR);
853 void RootWindowController::HideContextMenu() {
854 if (root_window_menu_model_adapter_)
855 root_window_menu_model_adapter_->Cancel();
858 void RootWindowController::HideContextMenuNoAnimation() {
859 if (!IsContextMenuShown())
862 views::Widget* submenu_widget =
863 root_window_menu_model_adapter_->GetSubmenuWidget();
864 DCHECK(submenu_widget);
865 ScopedAnimationDisabler disable(submenu_widget->GetNativeWindow());
866 root_window_menu_model_adapter_->Cancel();
869 bool RootWindowController::IsContextMenuShown() const {
870 return root_window_menu_model_adapter_ &&
871 root_window_menu_model_adapter_->IsShowingMenu();
874 void RootWindowController::UpdateAfterLoginStatusChange(LoginStatus status) {
875 StatusAreaWidget* status_area_widget =
876 shelf_->shelf_widget()->status_area_widget();
877 if (status_area_widget)
878 status_area_widget->UpdateAfterLoginStatusChange(status);
881 void RootWindowController::CreateAmbientWidget() {
882 DCHECK(!ambient_widget_);
884 auto* ambient_controller = Shell::Get()->ambient_controller();
885 if (ambient_controller && ambient_controller->IsShown()) {
886 ambient_widget_ = ambient_controller->CreateWidget(
887 GetRootWindow()->GetChildById(kShellWindowId_AmbientModeContainer));
891 void RootWindowController::CloseAmbientWidget(bool immediately) {
892 if (ambient_widget_) {
894 ambient_widget_->CloseNow();
896 ambient_widget_->CloseWithReason(views::Widget::ClosedReason::kLostFocus);
899 ambient_widget_.reset();
902 bool RootWindowController::HasAmbientWidget() const {
903 return !!ambient_widget_;
906 AccessibilityPanelLayoutManager*
907 RootWindowController::GetAccessibilityPanelLayoutManagerForTest() {
908 return GetAccessibilityPanelLayoutManager();
911 void RootWindowController::SetSecurityCurtainWidgetController(
912 std::unique_ptr<curtain::SecurityCurtainWidgetController> controller) {
913 DCHECK(!security_curtain_widget_controller_);
914 security_curtain_widget_controller_ = std::move(controller);
917 void RootWindowController::ClearSecurityCurtainWidgetController() {
918 security_curtain_widget_controller_ = nullptr;
921 curtain::SecurityCurtainWidgetController*
922 RootWindowController::security_curtain_widget_controller() {
923 return security_curtain_widget_controller_.get();
926 ////////////////////////////////////////////////////////////////////////////////
927 // RootWindowController, private:
929 RootWindowController::RootWindowController(AshWindowTreeHost* ash_host)
930 : ash_host_(ash_host),
931 window_tree_host_(ash_host->AsWindowTreeHost()),
932 shelf_(std::make_unique<Shelf>()),
933 lock_screen_action_background_controller_(
934 LockScreenActionBackgroundController::Create()),
935 work_area_insets_(std::make_unique<WorkAreaInsets>(this)) {
937 DCHECK(window_tree_host_);
939 if (!root_window_controllers_)
940 root_window_controllers_ = new std::vector<RootWindowController*>;
941 root_window_controllers_->push_back(this);
943 aura::Window* root_window = GetRootWindow();
944 GetRootWindowSettings(root_window)->controller = this;
946 stacking_controller_ = std::make_unique<StackingController>();
947 aura::client::SetWindowParentingClient(root_window,
948 stacking_controller_.get());
949 capture_client_ = std::make_unique<::wm::ScopedCaptureClient>(root_window);
952 void RootWindowController::Init(RootWindowType root_window_type) {
953 aura::Window* root_window = GetRootWindow();
954 // Create |split_view_controller_| for every display.
955 split_view_controller_ = std::make_unique<SplitViewController>(root_window);
956 Shell* shell = Shell::Get();
957 shell->InitRootWindow(root_window);
959 root_window->SetEventTargeter(std::make_unique<RootWindowTargeter>());
960 DCHECK(!old_targeter);
962 std::unique_ptr<RootWindowLayoutManager> root_window_layout_manager =
963 std::make_unique<RootWindowLayoutManager>(root_window);
964 root_window_layout_manager_ = root_window_layout_manager.get();
967 CreateSystemWallpaper(root_window_type);
969 InitLayoutManagers(std::move(root_window_layout_manager));
972 // `shelf_` was created in the constructor.
973 shelf_->shelf_widget()->PostCreateShelf();
975 color_provider_source_ = std::make_unique<AshColorProviderSource>();
976 if (Shell::GetPrimaryRootWindowController()
977 ->GetSystemModalLayoutManager(nullptr)
978 ->has_window_dimmer()) {
979 GetSystemModalLayoutManager(nullptr)->CreateModalBackground();
982 wallpaper_widget_controller_ =
983 std::make_unique<WallpaperWidgetController>(root_window);
985 wallpaper_widget_controller_->Init(
986 Shell::Get()->session_controller()->IsUserSessionBlocked());
987 root_window_layout_manager_->OnWindowResized();
989 CreateAmbientWidget();
991 // Explicitly update the desks controller before notifying the ShellObservers.
992 // This is to make sure the desks' states are correct before clients are
994 Shell::Get()->desks_controller()->OnRootWindowAdded(root_window);
996 if (root_window_type == RootWindowType::PRIMARY) {
997 shell->keyboard_controller()->RebuildKeyboardIfEnabled();
999 window_tree_host_->Show();
1001 // Notify shell observers about new root window.
1002 shell->OnRootWindowAdded(root_window);
1005 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1006 switches::kAshDisableTouchExplorationMode)) {
1007 touch_exploration_manager_ =
1008 std::make_unique<TouchExplorationManager>(this);
1012 void RootWindowController::InitLayoutManagers(
1013 std::unique_ptr<RootWindowLayoutManager> root_window_layout_manager) {
1014 // Create the shelf and status area widgets. Creates the ShelfLayoutManager
1015 // as a side-effect.
1016 DCHECK(!shelf_->shelf_widget());
1017 aura::Window* root = GetRootWindow();
1018 shelf_->CreateShelfWidget(root);
1020 root->SetLayoutManager(std::move(root_window_layout_manager));
1022 for (auto* container : desks_util::GetDesksContainers(root)) {
1023 // Installs WorkspaceLayoutManager on the container.
1024 SetWorkspaceController(container, new WorkspaceController(container));
1027 aura::Window* modal_container =
1028 GetContainer(kShellWindowId_SystemModalContainer);
1029 modal_container->SetLayoutManager(
1030 std::make_unique<SystemModalContainerLayoutManager>(modal_container));
1032 aura::Window* lock_modal_container =
1033 GetContainer(kShellWindowId_LockSystemModalContainer);
1034 DCHECK(lock_modal_container);
1035 lock_modal_container->SetLayoutManager(
1036 std::make_unique<SystemModalContainerLayoutManager>(
1037 lock_modal_container));
1039 aura::Window* lock_action_handler_container =
1040 GetContainer(kShellWindowId_LockActionHandlerContainer);
1041 DCHECK(lock_action_handler_container);
1042 lock_screen_action_background_controller_->SetParentWindow(
1043 lock_action_handler_container);
1044 lock_action_handler_container->SetLayoutManager(
1045 std::make_unique<LockActionHandlerLayoutManager>(
1046 lock_action_handler_container, shelf_.get(),
1047 lock_screen_action_background_controller_.get()));
1049 aura::Window* lock_container =
1050 GetContainer(kShellWindowId_LockScreenContainer);
1051 DCHECK(lock_container);
1052 lock_container->SetLayoutManager(
1053 std::make_unique<LockLayoutManager>(lock_container, shelf_.get()));
1055 aura::Window* always_on_top_container =
1056 GetContainer(kShellWindowId_AlwaysOnTopContainer);
1057 aura::Window* pip_container = GetContainer(kShellWindowId_PipContainer);
1058 DCHECK(always_on_top_container);
1059 DCHECK(pip_container);
1060 always_on_top_controller_ = std::make_unique<AlwaysOnTopController>(
1061 always_on_top_container, pip_container);
1063 // Make it easier to resize windows that partially overlap the shelf. Must
1064 // occur after the ShelfLayoutManager is constructed by ShelfWidget.
1065 aura::Window* shelf_container = GetContainer(kShellWindowId_ShelfContainer);
1066 shelf_container->SetEventTargeter(
1067 std::make_unique<ShelfWindowTargeter>(shelf_container, shelf_.get()));
1070 void RootWindowController::CreateContainers() {
1071 // CreateContainer() depends on root_window_layout_manager_.
1072 DCHECK(root_window_layout_manager_);
1074 aura::Window* root = GetRootWindow();
1076 // Add a NOT_DRAWN layer in between the root_window's layer and its current
1077 // children so that we only need to initiate two LayerAnimationSequences for
1078 // fullscreen animations such as the screen rotation animation and the desk
1079 // switch animation. Those animations take a screenshot of this container,
1080 // stack it ontop and animate the screenshot instead of the individual
1082 aura::Window* screen_rotation_container =
1083 CreateContainer(kShellWindowId_ScreenAnimationContainer,
1084 "ScreenAnimationContainer", root);
1086 // Everything that needs to be included in the docked magnifier, when enabled,
1087 // should be a descendant of MagnifiedContainer. The DockedMagnifierContainer
1088 // should not be a descendant of this container, otherwise there would be a
1089 // cycle (docked magnifier trying to magnify itself).
1090 aura::Window* magnified_container =
1091 CreateContainer(kShellWindowId_MagnifiedContainer, "MagnifiedContainer",
1092 screen_rotation_container);
1094 CreateContainer(kShellWindowId_DockedMagnifierContainer,
1095 "DockedMagnifierContainer", screen_rotation_container);
1097 // These containers are just used by PowerButtonController to animate groups
1098 // of containers simultaneously without messing up the current transformations
1099 // on those containers. These are direct children of the magnified_container
1100 // window; all of the other containers are their children.
1102 // The wallpaper container is not part of the lock animation, so it is not
1103 // included in those animate groups. When the screen is locked, the wallpaper
1104 // is moved to the lock screen wallpaper container (and moved back on unlock).
1105 // Ensure that there's an opaque layer occluding the non-lock-screen layers.
1106 aura::Window* wallpaper_container =
1107 CreateContainer(kShellWindowId_WallpaperContainer, "WallpaperContainer",
1108 magnified_container);
1109 ::wm::SetChildWindowVisibilityChangesAnimated(wallpaper_container);
1110 wallpaper_container->SetLayoutManager(
1111 std::make_unique<FillLayoutManager>(wallpaper_container));
1113 if (features::AreGlanceablesEnabled()) {
1114 aura::Window* glanceables_container =
1115 CreateContainer(kShellWindowId_GlanceablesContainer,
1116 "GlanceablesContainer", magnified_container);
1117 glanceables_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1118 glanceables_container->SetLayoutManager(
1119 std::make_unique<FillLayoutManager>(glanceables_container));
1122 aura::Window* non_lock_screen_containers =
1123 CreateContainer(kShellWindowId_NonLockScreenContainersContainer,
1124 "NonLockScreenContainersContainer", magnified_container);
1125 // Clip all windows inside this container, as half pixel of the window's
1126 // texture may become visible when the screen is scaled. crbug.com/368591.
1127 non_lock_screen_containers->layer()->SetMasksToBounds(true);
1129 aura::Window* lock_wallpaper_container =
1130 CreateContainer(kShellWindowId_LockScreenWallpaperContainer,
1131 "LockScreenWallpaperContainer", magnified_container);
1132 ::wm::SetChildWindowVisibilityChangesAnimated(lock_wallpaper_container);
1133 lock_wallpaper_container->SetLayoutManager(
1134 std::make_unique<FillLayoutManager>(lock_wallpaper_container));
1136 aura::Window* lock_screen_containers =
1137 CreateContainer(kShellWindowId_LockScreenContainersContainer,
1138 "LockScreenContainersContainer", magnified_container);
1139 aura::Window* lock_screen_related_containers = CreateContainer(
1140 kShellWindowId_LockScreenRelatedContainersContainer,
1141 "LockScreenRelatedContainersContainer", magnified_container);
1143 aura::Window* app_list_tablet_mode_container =
1144 CreateContainer(kShellWindowId_HomeScreenContainer, "HomeScreenContainer",
1145 non_lock_screen_containers);
1146 app_list_tablet_mode_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1149 CreateContainer(kShellWindowId_UnparentedContainer, "UnparentedContainer",
1150 non_lock_screen_containers);
1152 for (const auto& id : desks_util::GetDesksContainersIds()) {
1153 aura::Window* container = CreateContainer(
1154 id, desks_util::GetDeskContainerName(id), non_lock_screen_containers);
1155 ::wm::SetChildWindowVisibilityChangesAnimated(container);
1156 container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1157 container->SetProperty(kForceVisibleInMiniViewKey, true);
1158 window_util::SetChildrenUseExtendedHitRegionForWindow(container);
1160 // Hide the non-active containers.
1161 if (id != desks_util::GetActiveDeskContainerId())
1165 aura::Window* always_on_top_container =
1166 CreateContainer(kShellWindowId_AlwaysOnTopContainer,
1167 "AlwaysOnTopContainer", non_lock_screen_containers);
1168 ::wm::SetChildWindowVisibilityChangesAnimated(always_on_top_container);
1169 always_on_top_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1171 aura::Window* float_container =
1172 CreateContainer(kShellWindowId_FloatContainer, "FloatContainer",
1173 non_lock_screen_containers);
1174 wm::SetChildWindowVisibilityChangesAnimated(float_container);
1175 float_container->SetProperty(wm::kUsesScreenCoordinatesKey, true);
1176 window_util::SetChildrenUseExtendedHitRegionForWindow(float_container);
1178 aura::Window* app_list_container =
1179 CreateContainer(kShellWindowId_AppListContainer, "AppListContainer",
1180 non_lock_screen_containers);
1181 app_list_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1183 aura::Window* pip_container = CreateContainer(
1184 kShellWindowId_PipContainer, "PipContainer", non_lock_screen_containers);
1185 ::wm::SetChildWindowVisibilityChangesAnimated(pip_container);
1186 pip_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1188 aura::Window* arc_ime_parent_container = CreateContainer(
1189 kShellWindowId_ArcImeWindowParentContainer, "ArcImeWindowParentContainer",
1190 non_lock_screen_containers);
1191 arc_ime_parent_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1192 arc_ime_parent_container->SetLayoutManager(
1193 std::make_unique<ArcVirtualKeyboardContainerLayoutManager>(
1194 arc_ime_parent_container));
1195 aura::Window* arc_vk_container =
1196 CreateContainer(kShellWindowId_ArcVirtualKeyboardContainer,
1197 "ArcVirtualKeyboardContainer", arc_ime_parent_container);
1198 arc_vk_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1200 aura::Window* shelf_container_parent = lock_screen_related_containers;
1201 aura::Window* shelf_container = CreateContainer(
1202 kShellWindowId_ShelfContainer, "ShelfContainer", shelf_container_parent);
1203 shelf_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1204 shelf_container->SetProperty(kLockedToRootKey, true);
1206 aura::Window* shelf_bubble_container =
1207 CreateContainer(kShellWindowId_ShelfBubbleContainer,
1208 "ShelfBubbleContainer", non_lock_screen_containers);
1209 shelf_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1210 shelf_bubble_container->SetProperty(kLockedToRootKey, true);
1212 aura::Window* modal_container =
1213 CreateContainer(kShellWindowId_SystemModalContainer,
1214 "SystemModalContainer", non_lock_screen_containers);
1215 ::wm::SetChildWindowVisibilityChangesAnimated(modal_container);
1216 modal_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1217 window_util::SetChildrenUseExtendedHitRegionForWindow(modal_container);
1219 aura::Window* lock_container =
1220 CreateContainer(kShellWindowId_LockScreenContainer, "LockScreenContainer",
1221 lock_screen_containers);
1222 lock_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1224 aura::Window* lock_action_handler_container =
1225 CreateContainer(kShellWindowId_LockActionHandlerContainer,
1226 "LockActionHandlerContainer", lock_screen_containers);
1227 ::wm::SetChildWindowVisibilityChangesAnimated(lock_action_handler_container);
1228 lock_action_handler_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1231 aura::Window* lock_modal_container =
1232 CreateContainer(kShellWindowId_LockSystemModalContainer,
1233 "LockSystemModalContainer", lock_screen_containers);
1234 ::wm::SetChildWindowVisibilityChangesAnimated(lock_modal_container);
1235 lock_modal_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1236 window_util::SetChildrenUseExtendedHitRegionForWindow(lock_modal_container);
1238 aura::Window* power_menu_container =
1239 CreateContainer(kShellWindowId_PowerMenuContainer, "PowerMenuContainer",
1240 lock_screen_related_containers);
1241 power_menu_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1243 aura::Window* settings_bubble_container =
1244 CreateContainer(kShellWindowId_SettingBubbleContainer,
1245 "SettingBubbleContainer", lock_screen_related_containers);
1246 ::wm::SetChildWindowVisibilityChangesAnimated(settings_bubble_container);
1247 settings_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1248 settings_bubble_container->SetProperty(kLockedToRootKey, true);
1250 aura::Window* virtual_keyboard_parent_container = CreateContainer(
1251 kShellWindowId_ImeWindowParentContainer, "ImeWindowParentContainer",
1252 lock_screen_related_containers);
1253 virtual_keyboard_parent_container->SetProperty(
1254 ::wm::kUsesScreenCoordinatesKey, true);
1255 virtual_keyboard_parent_container->SetLayoutManager(
1256 std::make_unique<VirtualKeyboardContainerLayoutManager>(
1257 virtual_keyboard_parent_container));
1258 aura::Window* virtual_keyboard_container = CreateContainer(
1259 kShellWindowId_VirtualKeyboardContainer, "VirtualKeyboardContainer",
1260 virtual_keyboard_parent_container);
1261 virtual_keyboard_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1263 virtual_keyboard_container->SetLayoutManager(
1264 std::make_unique<keyboard::KeyboardLayoutManager>(
1265 keyboard::KeyboardUIController::Get()));
1267 aura::Window* accessibility_panel_container = CreateContainer(
1268 kShellWindowId_AccessibilityPanelContainer, "AccessibilityPanelContainer",
1269 lock_screen_related_containers);
1270 ::wm::SetChildWindowVisibilityChangesAnimated(accessibility_panel_container);
1271 accessibility_panel_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1273 accessibility_panel_container->SetProperty(kLockedToRootKey, true);
1274 accessibility_panel_container->SetLayoutManager(
1275 std::make_unique<AccessibilityPanelLayoutManager>());
1277 aura::Window* menu_container =
1278 CreateContainer(kShellWindowId_MenuContainer, "MenuContainer",
1279 lock_screen_related_containers);
1280 ::wm::SetChildWindowVisibilityChangesAnimated(menu_container);
1281 menu_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1283 aura::Window* accessibility_bubble_container = CreateContainer(
1284 kShellWindowId_AccessibilityBubbleContainer,
1285 "AccessibilityBubbleContainer", lock_screen_related_containers);
1286 accessibility_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1289 aura::Window* drag_drop_container = CreateContainer(
1290 kShellWindowId_DragImageAndTooltipContainer,
1291 "DragImageAndTooltipContainer", lock_screen_related_containers);
1292 ::wm::SetChildWindowVisibilityChangesAnimated(drag_drop_container);
1293 drag_drop_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1295 aura::Window* overlay_container =
1296 CreateContainer(kShellWindowId_OverlayContainer, "OverlayContainer",
1297 lock_screen_related_containers);
1298 overlay_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1299 overlay_container->SetLayoutManager(
1300 std::make_unique<OverlayLayoutManager>(overlay_container));
1302 if (chromeos::features::IsAmbientModeEnabled()) {
1303 aura::Window* ambient_container =
1304 CreateContainer(kShellWindowId_AmbientModeContainer,
1305 "AmbientModeContainer", lock_screen_related_containers);
1306 ::wm::SetChildWindowVisibilityChangesAnimated(ambient_container);
1307 ambient_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1308 ambient_container->SetLayoutManager(
1309 std::make_unique<FillLayoutManager>(ambient_container));
1312 aura::Window* mouse_cursor_container =
1313 CreateContainer(kShellWindowId_MouseCursorContainer,
1314 "MouseCursorContainer", magnified_container);
1315 mouse_cursor_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1317 aura::Window* always_on_top_wallpaper_container =
1318 CreateContainer(kShellWindowId_AlwaysOnTopWallpaperContainer,
1319 "AlwaysOnTopWallpaperContainer", magnified_container);
1320 always_on_top_wallpaper_container->SetLayoutManager(
1321 std::make_unique<FillLayoutManager>(always_on_top_wallpaper_container));
1323 CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
1324 "PowerButtonAnimationContainer", magnified_container);
1327 aura::Window* RootWindowController::CreateContainer(int window_id,
1329 aura::Window* parent) {
1330 aura::Window* window =
1331 new aura::Window(nullptr, aura::client::WINDOW_TYPE_UNKNOWN);
1332 window->Init(ui::LAYER_NOT_DRAWN);
1333 window->SetId(window_id);
1334 window->SetName(name);
1335 parent->AddChild(window);
1336 if (window_id != kShellWindowId_UnparentedContainer)
1338 root_window_layout_manager_->AddContainer(window);
1342 void RootWindowController::CreateSystemWallpaper(
1343 RootWindowType root_window_type) {
1344 SkColor color = SK_ColorBLACK;
1345 // The splash screen appears on the primary display at boot. If this is a
1346 // secondary monitor (either connected at boot or connected later) or if the
1347 // browser restarted for a second login then don't use the boot color.
1348 const bool is_boot_splash_screen =
1349 root_window_type == RootWindowType::PRIMARY &&
1350 base::CommandLine::ForCurrentProcess()->HasSwitch(
1351 switches::kFirstExecAfterBoot);
1352 if (is_boot_splash_screen)
1353 color = kChromeOsBootColor;
1355 std::make_unique<SystemWallpaperController>(GetRootWindow(), color);
1358 AccessibilityPanelLayoutManager*
1359 RootWindowController::GetAccessibilityPanelLayoutManager() const {
1360 aura::Window* container = const_cast<aura::Window*>(
1361 GetContainer(kShellWindowId_AccessibilityPanelContainer));
1362 auto* layout_manager = static_cast<AccessibilityPanelLayoutManager*>(
1363 container->layout_manager());
1364 return layout_manager;
1367 void RootWindowController::OnMenuClosed() {
1368 root_window_menu_model_adapter_.reset();
1369 sort_apps_submenu_.reset();
1370 shelf_->UpdateVisibilityState();