Revert "[M120 Migration]Fix for crash during chrome exit"
[platform/framework/web/chromium-efl.git] / ash / root_window_controller.cc
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.
4
5 #include "ash/root_window_controller.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <vector>
10
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"
112
113 namespace ash {
114 namespace {
115
116 bool IsInShelfContainer(aura::Window* container) {
117   if (!container) {
118     return false;
119   }
120   int id = container->GetId();
121   if (id == ash::kShellWindowId_ShelfContainer ||
122       id == ash::kShellWindowId_ShelfBubbleContainer) {
123     return true;
124   }
125   return IsInShelfContainer(container->parent());
126 }
127
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;
132
133   while (window) {
134     target_path.push_back(window);
135     window = window->parent();
136   }
137
138   while (blocking_container) {
139     blocking_path.push_back(blocking_container);
140     blocking_container = blocking_container->parent();
141   }
142
143   // The root window is put at the end so that we compare windows at
144   // the same depth.
145   while (!blocking_path.empty()) {
146     if (target_path.empty()) {
147       return false;
148     }
149
150     aura::Window* target = target_path.back();
151     target_path.pop_back();
152     aura::Window* blocking = blocking_path.back();
153     blocking_path.pop_back();
154
155     // Still on the same path, continue.
156     if (target == blocking) {
157       continue;
158     }
159
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()) {
163       return false;
164     }
165
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
171     // events.
172     return std::find(blocking_iter, windows.end(), target) != windows.end();
173   }
174
175   return true;
176 }
177
178 // Scales |value| that is originally between 0 and |src_max| to be between
179 // 0 and |dst_max|.
180 float ToRelativeValue(int value, int src_max, int dst_max) {
181   return static_cast<float>(value) / static_cast<float>(src_max) * dst_max;
182 }
183
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())));
193 }
194
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();
203
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);
208
209   gfx::Rect local_bounds;
210   if (update_bounds) {
211     local_bounds = state->window()->bounds();
212     MoveOriginRelativeToSize(src_size, dst_size, &local_bounds);
213     local_bounds.AdjustToFit(work_area_in_new_parent);
214   }
215
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);
220   }
221
222   new_parent->AddChild(window);
223
224   // Snapped windows have bounds handled by the layout manager in AddChild().
225   if (update_bounds) {
226     window->SetBounds(local_bounds);
227   }
228
229   if (has_restore_bounds) {
230     state->SetRestoreBoundsInParent(restore_bounds);
231   }
232 }
233
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,
247   };
248   constexpr int kExtraContainerIdsToMoveInUnifiedMode[] = {
249       kShellWindowId_LockScreenContainer,
250   };
251
252   // Desk container ids are different depends on whether Bento feature is
253   // enabled or not.
254   std::vector<int> container_ids = desks_util::GetDesksContainersIds();
255   for (const int id : kContainerIdsToMove) {
256     container_ids.emplace_back(id);
257   }
258
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);
265     }
266   }
267
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)) {
282         ++iter;
283       }
284       // If the entire window list is modal background windows then stop.
285       if (iter == src_container_children.rend()) {
286         break;
287       }
288
289       // |iter| is invalidated after ReparentWindow. Cache it to use afterwards.
290       aura::Window* const window = *iter;
291       ReparentWindow(window, dst_container);
292
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) {
301             found_window = true;
302             continue;
303           }
304
305           if (!found_window || window_iter->parent() != dst_container) {
306             continue;
307           }
308
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;
312           break;
313         }
314       }
315
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);
322       } else {
323         dst_container->StackChildAtBottom(window);
324       }
325     }
326   }
327 }
328
329 bool ShouldDestroyWindowInCloseChildWindows(aura::Window* window) {
330   return window->owned_by_parent();
331 }
332
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);
338   }
339   if (auto* float_controller = Shell::Get()->float_controller()) {
340     float_controller->ClearWorkspaceEventHandler(root);
341   }
342 }
343
344 class RootWindowTargeter : public aura::WindowTargeter {
345  public:
346   RootWindowTargeter() = default;
347
348   RootWindowTargeter(const RootWindowTargeter&) = delete;
349   RootWindowTargeter& operator=(const RootWindowTargeter&) = delete;
350
351   ~RootWindowTargeter() override = default;
352
353  protected:
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);
361
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.
365       //
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);
377       }
378     }
379     return aura::WindowTargeter::FindTargetForLocatedEvent(window, event);
380   }
381
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());
390   }
391
392  private:
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;
398       return true;
399     }
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;
403       return true;
404     }
405     // For other cases, reset the state
406     if (event->type() != ui::ET_MOUSE_CAPTURE_CHANGED) {
407       last_mouse_event_type_ = ui::ET_UNKNOWN;
408     }
409     return false;
410   }
411
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));
415   }
416
417   ui::EventType last_mouse_event_type_ = ui::ET_UNKNOWN;
418 };
419
420 class RootWindowMenuModelAdapter : public AppMenuModelAdapter {
421  public:
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,
426                              bool is_tablet_mode)
427       : AppMenuModelAdapter(std::string(),
428                             std::move(model),
429                             widget_owner,
430                             source_type,
431                             std::move(on_menu_closed_callback),
432                             is_tablet_mode) {}
433
434   RootWindowMenuModelAdapter(const RootWindowMenuModelAdapter&) = delete;
435   RootWindowMenuModelAdapter& operator=(const RootWindowMenuModelAdapter&) =
436       delete;
437
438   ~RootWindowMenuModelAdapter() override = default;
439
440  private:
441   // AppMenuModelAdapter overrides:
442   void RecordHistogramOnMenuClosed() override {
443     const base::TimeDelta user_journey_time =
444         base::TimeTicks::Now() - menu_open_time();
445
446     UMA_HISTOGRAM_TIMES("Apps.ContextMenuUserJourneyTime.Desktop",
447                         user_journey_time);
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",
452                           user_journey_time);
453       UMA_HISTOGRAM_ENUMERATION("Apps.ContextMenuShowSource.Desktop.TabletMode",
454                                 source_type(), ui::MENU_SOURCE_TYPE_LAST);
455     } else {
456       UMA_HISTOGRAM_TIMES(
457           "Apps.ContextMenuUserJourneyTime.Desktop.ClamshellMode",
458           user_journey_time);
459       UMA_HISTOGRAM_ENUMERATION(
460           "Apps.ContextMenuShowSource.Desktop.ClamshellMode", source_type(),
461           ui::MENU_SOURCE_TYPE_LAST);
462     }
463   }
464 };
465
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 {
469  public:
470   explicit FillLayoutManager(aura::Window* container) : container_(container) {}
471   ~FillLayoutManager() override = default;
472   FillLayoutManager(const FillLayoutManager&) = delete;
473   FillLayoutManager& operator=(const FillLayoutManager&) = delete;
474
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 {}
484
485  private:
486   void Relayout() {
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);
494       }
495     }
496   }
497
498   raw_ptr<aura::Window, ExperimentalAsh> container_;
499 };
500
501 }  // namespace
502
503 // static
504 std::vector<RootWindowController*>*
505     RootWindowController::root_window_controllers_ = nullptr;
506
507 RootWindowController::~RootWindowController() {
508   Shutdown();
509   DCHECK(!wallpaper_widget_controller_.get());
510   work_area_insets_.reset();
511   ash_host_.reset();
512   // The CaptureClient needs to be around for as long as the RootWindow is
513   // valid.
514   capture_client_.reset();
515   root_window_controllers_->erase(
516       base::ranges::find(*root_window_controllers_, this));
517 }
518
519 RootWindowController* RootWindowController::CreateForPrimaryDisplay(
520     AshWindowTreeHost* host) {
521   RootWindowController* controller = new RootWindowController(host);
522   controller->Init(RootWindowType::PRIMARY);
523   return controller;
524 }
525
526 RootWindowController* RootWindowController::CreateForSecondaryDisplay(
527     AshWindowTreeHost* host) {
528   RootWindowController* controller = new RootWindowController(host);
529   controller->Init(RootWindowType::SECONDARY);
530   return controller;
531 }
532
533 // static
534 RootWindowController* RootWindowController::ForWindow(
535     const aura::Window* window) {
536   DCHECK(window);
537   CHECK(Shell::HasInstance());
538   return GetRootWindowSettings(window->GetRootWindow())->controller;
539 }
540
541 // static
542 RootWindowController* RootWindowController::ForTargetRootWindow() {
543   CHECK(Shell::HasInstance());
544   return ForWindow(Shell::GetRootWindowForNewWindows());
545 }
546
547 aura::WindowTreeHost* RootWindowController::GetHost() {
548   return window_tree_host_;
549 }
550
551 const aura::WindowTreeHost* RootWindowController::GetHost() const {
552   return window_tree_host_;
553 }
554
555 aura::Window* RootWindowController::GetRootWindow() {
556   return GetHost()->window();
557 }
558
559 const aura::Window* RootWindowController::GetRootWindow() const {
560   return GetHost()->window();
561 }
562
563 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
564   return shelf_->shelf_layout_manager();
565 }
566
567 SystemModalContainerLayoutManager*
568 RootWindowController::GetSystemModalLayoutManager(aura::Window* window) {
569   aura::Window* modal_container = nullptr;
570   if (window) {
571     aura::Window* window_container = GetContainerForWindow(window);
572     if (window_container &&
573         window_container->GetId() >= kShellWindowId_LockScreenContainer) {
574       modal_container = GetContainer(kShellWindowId_LockSystemModalContainer);
575     } else {
576       modal_container = GetContainer(kShellWindowId_SystemModalContainer);
577     }
578   } else {
579     int modal_window_id =
580         Shell::Get()->session_controller()->IsUserSessionBlocked()
581             ? kShellWindowId_LockSystemModalContainer
582             : kShellWindowId_SystemModalContainer;
583     modal_container = GetContainer(modal_window_id);
584   }
585   return modal_container ? static_cast<SystemModalContainerLayoutManager*>(
586                                modal_container->layout_manager())
587                          : nullptr;
588 }
589
590 StatusAreaWidget* RootWindowController::GetStatusAreaWidget() {
591   ShelfWidget* shelf_widget = shelf_->shelf_widget();
592   return shelf_widget ? shelf_widget->status_area_widget() : nullptr;
593 }
594
595 bool RootWindowController::IsSystemTrayVisible() {
596   TrayBackgroundView* tray = GetStatusAreaWidget()->unified_system_tray();
597   return tray && tray->GetWidget()->IsVisible() && tray->GetVisible();
598 }
599
600 bool RootWindowController::CanWindowReceiveEvents(aura::Window* window) {
601   if (GetRootWindow() != window->GetRootWindow()) {
602     return false;
603   }
604
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());
613   }
614
615   if (modal_layout_manager && modal_layout_manager->has_window_dimmer()) {
616     blocking_container = modal_container;
617   } else {
618     modal_container = nullptr;  // Don't check modal dialogs.
619   }
620
621   // In normal session.
622   if (!blocking_container) {
623     return true;
624   }
625
626   if (!IsWindowAboveContainer(window, blocking_container)) {
627     return false;
628   }
629
630   if (modal_container) {
631     // If the window is in the target modal container, only allow the top most
632     // one.
633     if (modal_container->Contains(window)) {
634       return modal_layout_manager->IsPartOfActiveModalWindow(window);
635     }
636     // Don't allow shelf to process events if there is a visible modal dialog.
637     if (IsInShelfContainer(window->parent())) {
638       return false;
639     }
640   }
641   return true;
642 }
643
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()
654           ->dispatcher()
655           ->GetDefaultEventTargeter()
656           ->FindTargetForEvent(root_window, &test_event);
657   return static_cast<aura::Window*>(event_handler);
658 }
659
660 gfx::Point RootWindowController::GetLastMouseLocationInRoot() {
661   return window_tree_host_->dispatcher()->GetLastMouseLocationInRoot();
662 }
663
664 aura::Window* RootWindowController::GetContainer(int container_id) {
665   return GetRootWindow()->GetChildById(container_id);
666 }
667
668 const aura::Window* RootWindowController::GetContainer(int container_id) const {
669   return window_tree_host_->window()->GetChildById(container_id);
670 }
671
672 ScreenRotationAnimator* RootWindowController::GetScreenRotationAnimator() {
673   if (is_shutting_down_) {
674     return nullptr;
675   }
676
677   if (!screen_rotation_animator_) {
678     screen_rotation_animator_ =
679         std::make_unique<ScreenRotationAnimator>(GetRootWindow());
680   }
681
682   return screen_rotation_animator_.get();
683 }
684
685 void RootWindowController::Shutdown() {
686   is_shutting_down_ = true;
687
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();
691
692   aura::Window* root_window = GetRootWindow();
693   auto targeter = root_window->SetEventTargeter(
694       std::make_unique<aura::NullWindowTargeter>());
695
696   touch_exploration_manager_.reset();
697   wallpaper_widget_controller_.reset();
698   EndSplitViewOverviewSession(SplitViewOverviewSessionExitPoint::kShutdown);
699   CloseAmbientWidget(/*immediately=*/true);
700
701   CloseChildWindows();
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;
706   if (ash_host_) {
707     ash_host_->PrepareForShutdown();
708   }
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);
714
715   // The targeter may still on the stack, so delete it later.
716   if (targeter) {
717     base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(
718         FROM_HERE, std::move(targeter));
719   }
720 }
721
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_) {
726     return;
727   }
728   did_close_child_windows_ = true;
729
730   aura::Window* root = GetRootWindow();
731
732   Shell::Get()->desks_controller()->OnRootWindowClosing(root);
733
734   // Notify the keyboard controller before closing child windows and shutting
735   // down associated layout managers.
736   Shell::Get()->keyboard_controller()->OnRootWindowClosing(root);
737
738   OverviewController* overview_controller = Shell::Get()->overview_controller();
739   if (overview_controller && overview_controller->InOverviewSession()) {
740     overview_controller->overview_session()->OnRootWindowClosing(root);
741   }
742
743   shelf_->ShutdownShelfWidget();
744
745   ClearWorkspaceControllers(root);
746   always_on_top_controller_->ClearLayoutManagers();
747
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)) {
757         continue;
758       }
759       if (child->delegate()) {
760         toplevel_windows.Add(child);
761       } else {
762         non_toplevel_windows.Add(child);
763       }
764     }
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
770       // window.
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) {
775           continue;
776         }
777       }
778       delete toplevel_windows.Pop();
779     }
780   }
781
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)) {
788       delete child;
789     } else {
790       root->RemoveChild(child);
791     }
792   }
793
794   // Removing the containers destroys ShelfLayoutManager. ShelfWidget outlives
795   // ShelfLayoutManager because ShelfLayoutManager holds a pointer to it.
796   shelf_->DestroyShelfWidget();
797
798   ::wm::SetTooltipClient(GetRootWindow(), nullptr);
799 }
800
801 void RootWindowController::MoveWindowsTo(aura::Window* dst) {
802   // Suspend unnecessary updates of the shelf visibility indefinitely since it
803   // is going away.
804   if (GetShelfLayoutManager()) {
805     GetShelfLayoutManager()->SuspendVisibilityUpdateForShutdown();
806   }
807
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);
814
815   ReparentAllWindows(root, dst);
816 }
817
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()));
823   }
824
825   // TouchHudProjection manages its own lifetime.
826   if (command_line->HasSwitch(switches::kShowTaps)) {
827     touch_hud_projection_ = new TouchHudProjection(GetRootWindow());
828   }
829 }
830
831 aura::Window* RootWindowController::GetWindowForFullscreenMode() {
832   return GetWindowForFullscreenModeInRoot(GetRootWindow());
833 }
834
835 bool RootWindowController::IsInFullscreenMode() {
836   auto* window = GetWindowForFullscreenMode();
837   return window && WindowState::Get(window)->GetHideShelfWhenFullscreen();
838 }
839
840 void RootWindowController::SetTouchAccessibilityAnchorPoint(
841     const gfx::Point& anchor_point) {
842   if (touch_exploration_manager_) {
843     touch_exploration_manager_->SetTouchAccessibilityAnchorPoint(anchor_point);
844   }
845 }
846
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())
851                                  .id();
852
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)),
862           tablet_mode);
863
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(
881         REORDER_BY_COLOR,
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(
888         REORDER_SUBMENU,
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));
894
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));
903     } else {
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));
909     }
910   }
911
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);
918 }
919
920 void RootWindowController::HideContextMenu() {
921   if (root_window_menu_model_adapter_) {
922     root_window_menu_model_adapter_->Cancel();
923   }
924 }
925
926 void RootWindowController::HideContextMenuNoAnimation() {
927   if (!IsContextMenuShown()) {
928     return;
929   }
930
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();
936 }
937
938 bool RootWindowController::IsContextMenuShown() const {
939   return root_window_menu_model_adapter_ &&
940          root_window_menu_model_adapter_->IsShowingMenu();
941 }
942
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);
948   }
949 }
950
951 void RootWindowController::CreateAmbientWidget() {
952   DCHECK(!ambient_widget_);
953
954   auto* ambient_controller = Shell::Get()->ambient_controller();
955   if (ambient_controller) {
956     ambient_widget_ = ambient_controller->CreateWidget(
957         GetRootWindow()->GetChildById(kShellWindowId_AmbientModeContainer));
958   }
959 }
960
961 void RootWindowController::CloseAmbientWidget(bool immediately) {
962   if (ambient_widget_) {
963     if (immediately) {
964       ambient_widget_->CloseNow();
965     } else {
966       ambient_widget_->CloseWithReason(views::Widget::ClosedReason::kLostFocus);
967     }
968   }
969
970   ambient_widget_.reset();
971 }
972
973 bool RootWindowController::HasAmbientWidget() const {
974   return !!ambient_widget_;
975 }
976
977 AccessibilityPanelLayoutManager*
978 RootWindowController::GetAccessibilityPanelLayoutManagerForTest() {
979   return GetAccessibilityPanelLayoutManager();
980 }
981
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);
986 }
987
988 void RootWindowController::ClearSecurityCurtainWidgetController() {
989   security_curtain_widget_controller_ = nullptr;
990 }
991
992 curtain::SecurityCurtainWidgetController*
993 RootWindowController::security_curtain_widget_controller() {
994   return security_curtain_widget_controller_.get();
995 }
996
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);
1005 }
1006
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);
1012   }
1013   split_view_overview_session_.reset();
1014 }
1015
1016 void RootWindowController::SetScreenRotationAnimatorForTest(
1017     std::unique_ptr<ScreenRotationAnimator> animator) {
1018   screen_rotation_animator_ = std::move(animator);
1019 }
1020
1021 ////////////////////////////////////////////////////////////////////////////////
1022 // RootWindowController, private:
1023
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)) {
1031   DCHECK(ash_host_);
1032   DCHECK(window_tree_host_);
1033
1034   if (!root_window_controllers_) {
1035     root_window_controllers_ = new std::vector<RootWindowController*>;
1036   }
1037   root_window_controllers_->push_back(this);
1038
1039   aura::Window* root_window = GetRootWindow();
1040   GetRootWindowSettings(root_window)->controller = this;
1041
1042   window_parenting_controller_ =
1043       std::make_unique<WindowParentingController>(root_window);
1044   capture_client_ = std::make_unique<::wm::ScopedCaptureClient>(root_window);
1045 }
1046
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);
1053   auto old_targeter =
1054       root_window->SetEventTargeter(std::make_unique<RootWindowTargeter>());
1055   DCHECK(!old_targeter);
1056
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();
1060
1061   CreateContainers();
1062   CreateSystemWallpaper(root_window_type);
1063
1064   InitLayoutManagers(std::move(root_window_layout_manager));
1065   InitTouchHuds();
1066
1067   // `shelf_` was created in the constructor.
1068   shelf_->shelf_widget()->PostCreateShelf();
1069
1070   color_provider_source_ = std::make_unique<AshColorProviderSource>();
1071   if (Shell::GetPrimaryRootWindowController()
1072           ->GetSystemModalLayoutManager(nullptr)
1073           ->has_window_dimmer()) {
1074     GetSystemModalLayoutManager(nullptr)->CreateModalBackground();
1075   }
1076
1077   wallpaper_widget_controller_ =
1078       std::make_unique<WallpaperWidgetController>(root_window);
1079
1080   wallpaper_widget_controller_->Init(
1081       Shell::Get()->session_controller()->IsUserSessionBlocked());
1082   root_window_layout_manager_->OnWindowResized();
1083
1084   CreateAmbientWidget();
1085
1086   // Explicitly update the desks controller before notifying the ShellObservers.
1087   // This is to make sure the desks' states are correct before clients are
1088   // updated.
1089   shell->desks_controller()->OnRootWindowAdded(root_window);
1090
1091   if (root_window_type == RootWindowType::PRIMARY) {
1092     shell->keyboard_controller()->RebuildKeyboardIfEnabled();
1093   } else {
1094     window_tree_host_->Show();
1095
1096     // Notify shell observers about new root window.
1097     shell->OnRootWindowAdded(root_window);
1098   }
1099
1100   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1101           switches::kAshDisableTouchExplorationMode)) {
1102     touch_exploration_manager_ =
1103         std::make_unique<TouchExplorationManager>(this);
1104   }
1105 }
1106
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);
1114
1115   root->SetLayoutManager(std::move(root_window_layout_manager));
1116
1117   for (auto* container : desks_util::GetDesksContainers(root)) {
1118     // Installs WorkspaceLayoutManager on the container.
1119     SetWorkspaceController(container,
1120                            std::make_unique<WorkspaceController>(container));
1121   }
1122
1123   aura::Window* modal_container =
1124       GetContainer(kShellWindowId_SystemModalContainer);
1125   modal_container->SetLayoutManager(
1126       std::make_unique<SystemModalContainerLayoutManager>(modal_container));
1127
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));
1134
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()));
1144
1145   aura::Window* lock_container =
1146       GetContainer(kShellWindowId_LockScreenContainer);
1147   DCHECK(lock_container);
1148   lock_container->SetLayoutManager(
1149       std::make_unique<LockLayoutManager>(lock_container));
1150
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);
1158
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()));
1164 }
1165
1166 void RootWindowController::CreateContainers() {
1167   // CreateContainer() depends on root_window_layout_manager_.
1168   DCHECK(root_window_layout_manager_);
1169
1170   aura::Window* root = GetRootWindow();
1171
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
1177   // elements.
1178   aura::Window* screen_rotation_container =
1179       CreateContainer(kShellWindowId_ScreenAnimationContainer,
1180                       "ScreenAnimationContainer", root);
1181
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);
1189
1190   CreateContainer(kShellWindowId_DockedMagnifierContainer,
1191                   "DockedMagnifierContainer", screen_rotation_container);
1192
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.
1197
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));
1208
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);
1215
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));
1222
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);
1229
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,
1234                                               true);
1235
1236   CreateContainer(kShellWindowId_UnparentedContainer, "UnparentedContainer",
1237                   non_lock_screen_containers);
1238
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);
1246
1247     // Hide the non-active containers.
1248     if (id != desks_util::GetActiveDeskContainerId()) {
1249       container->Hide();
1250     }
1251   }
1252
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);
1258
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);
1265
1266   aura::Window* app_list_container =
1267       CreateContainer(kShellWindowId_AppListContainer, "AppListContainer",
1268                       non_lock_screen_containers);
1269   app_list_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1270
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);
1275
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);
1287
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);
1293
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);
1299
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);
1306
1307   aura::Window* lock_container =
1308       CreateContainer(kShellWindowId_LockScreenContainer, "LockScreenContainer",
1309                       lock_screen_containers);
1310   lock_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1311
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,
1317                                              true);
1318
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);
1325
1326   aura::Window* power_menu_container =
1327       CreateContainer(kShellWindowId_PowerMenuContainer, "PowerMenuContainer",
1328                       GetPowerMenuContainerParent(GetRootWindow()));
1329   power_menu_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1330
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);
1337
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);
1343
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,
1356                                           true);
1357   virtual_keyboard_container->SetLayoutManager(
1358       std::make_unique<keyboard::KeyboardLayoutManager>(
1359           keyboard::KeyboardUIController::Get()));
1360
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,
1366                                              true);
1367   accessibility_panel_container->SetProperty(kLockedToRootKey, true);
1368   accessibility_panel_container->SetLayoutManager(
1369       std::make_unique<AccessibilityPanelLayoutManager>());
1370
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);
1376
1377   aura::Window* accessibility_bubble_container = CreateContainer(
1378       kShellWindowId_AccessibilityBubbleContainer,
1379       "AccessibilityBubbleContainer", lock_screen_related_containers);
1380   accessibility_bubble_container->SetProperty(::wm::kUsesScreenCoordinatesKey,
1381                                               true);
1382
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);
1388
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));
1395
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));
1403
1404   aura::Window* mouse_cursor_container =
1405       CreateContainer(kShellWindowId_MouseCursorContainer,
1406                       "MouseCursorContainer", magnified_container);
1407   mouse_cursor_container->SetProperty(::wm::kUsesScreenCoordinatesKey, true);
1408
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));
1414
1415   CreateContainer(kShellWindowId_PowerButtonAnimationContainer,
1416                   "PowerButtonAnimationContainer", magnified_container);
1417
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));
1426   }
1427 }
1428
1429 aura::Window* RootWindowController::CreateContainer(int window_id,
1430                                                     const char* name,
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) {
1439     window->Show();
1440   }
1441   root_window_layout_manager_->AddContainer(window);
1442   return window;
1443 }
1444
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;
1457   }
1458   system_wallpaper_ =
1459       std::make_unique<SystemWallpaperController>(GetRootWindow(), color);
1460 }
1461
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;
1469 }
1470
1471 void RootWindowController::OnMenuClosed() {
1472   root_window_menu_model_adapter_.reset();
1473   sort_apps_submenu_.reset();
1474   shelf_->UpdateVisibilityState();
1475 }
1476
1477 }  // namespace ash