OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ash/root_window_controller.h" | |
6 | |
7 #include "ash/aura/wm_window_aura.h" | |
8 #include "ash/common/session/session_state_delegate.h" | |
9 #include "ash/common/shelf/shelf_layout_manager.h" | |
10 #include "ash/common/shelf/shelf_widget.h" | |
11 #include "ash/common/shelf/wm_shelf.h" | |
12 #include "ash/common/shell_delegate.h" | |
13 #include "ash/common/system/status_area_widget.h" | |
14 #include "ash/common/wallpaper/wallpaper_delegate.h" | |
15 #include "ash/common/wallpaper/wallpaper_widget_controller.h" | |
16 #include "ash/common/wm/always_on_top_controller.h" | |
17 #include "ash/common/wm/container_finder.h" | |
18 #include "ash/common/wm/dock/docked_window_layout_manager.h" | |
19 #include "ash/common/wm/lock_layout_manager.h" | |
20 #include "ash/common/wm/panels/panel_layout_manager.h" | |
21 #include "ash/common/wm/root_window_layout_manager.h" | |
22 #include "ash/common/wm/system_modal_container_layout_manager.h" | |
23 #include "ash/common/wm/window_state.h" | |
24 #include "ash/common/wm/wm_snap_to_pixel_layout_manager.h" | |
25 #include "ash/common/wm/workspace/workspace_layout_manager.h" | |
26 #include "ash/common/wm/workspace_controller.h" | |
27 #include "ash/common/wm_shell.h" | |
28 #include "ash/common/wm_window.h" | |
29 #include "ash/public/cpp/shell_window_ids.h" | |
30 #include "ash/root_window_controller.h" | |
31 #include "ash/shell.h" | |
32 #include "base/memory/ptr_util.h" | |
33 #include "ui/aura/env.h" | |
34 #include "ui/aura/mus/window_mus.h" | |
35 #include "ui/aura/mus/window_tree_client.h" | |
36 #include "ui/aura/window.h" | |
37 #include "ui/aura/window_event_dispatcher.h" | |
38 #include "ui/aura/window_tree_host.h" | |
39 #include "ui/base/models/menu_model.h" | |
40 #include "ui/events/event_targeter.h" | |
41 #include "ui/events/event_utils.h" | |
42 #include "ui/views/controls/menu/menu_model_adapter.h" | |
43 #include "ui/views/controls/menu/menu_runner.h" | |
44 #include "ui/wm/core/coordinate_conversion.h" | |
45 | |
46 // TODO(sky): this file is temporary and here to make review easier. The | |
47 // contents of this file will be folded into root_window_controller.cc shortly. | |
48 namespace ash { | |
49 namespace { | |
50 | |
51 // Scales |value| that is originally between 0 and |src_max| to be between | |
52 // 0 and |dst_max|. | |
53 float ToRelativeValue(int value, int src_max, int dst_max) { | |
54 return static_cast<float>(value) / static_cast<float>(src_max) * dst_max; | |
55 } | |
56 | |
57 // Uses ToRelativeValue() to scale the origin of |bounds_in_out|. The | |
58 // width/height are not changed. | |
59 void MoveOriginRelativeToSize(const gfx::Size& src_size, | |
60 const gfx::Size& dst_size, | |
61 gfx::Rect* bounds_in_out) { | |
62 gfx::Point origin = bounds_in_out->origin(); | |
63 bounds_in_out->set_origin(gfx::Point( | |
64 ToRelativeValue(origin.x(), src_size.width(), dst_size.width()), | |
65 ToRelativeValue(origin.y(), src_size.height(), dst_size.height()))); | |
66 } | |
67 | |
68 // Reparents |window| to |new_parent|. | |
69 // TODO(sky): This should take an aura::Window. http://crbug.com/671246. | |
70 void ReparentWindow(WmWindow* window, WmWindow* new_parent) { | |
71 const gfx::Size src_size = window->GetParent()->GetBounds().size(); | |
72 const gfx::Size dst_size = new_parent->GetBounds().size(); | |
73 // Update the restore bounds to make it relative to the display. | |
74 wm::WindowState* state = window->GetWindowState(); | |
75 gfx::Rect restore_bounds; | |
76 bool has_restore_bounds = state->HasRestoreBounds(); | |
77 | |
78 bool update_bounds = | |
79 (state->IsNormalOrSnapped() || state->IsMinimized()) && | |
80 new_parent->GetShellWindowId() != kShellWindowId_DockedContainer; | |
81 gfx::Rect local_bounds; | |
82 if (update_bounds) { | |
83 local_bounds = state->window()->GetBounds(); | |
84 MoveOriginRelativeToSize(src_size, dst_size, &local_bounds); | |
85 } | |
86 | |
87 if (has_restore_bounds) { | |
88 restore_bounds = state->GetRestoreBoundsInParent(); | |
89 MoveOriginRelativeToSize(src_size, dst_size, &restore_bounds); | |
90 } | |
91 | |
92 new_parent->AddChild(window); | |
93 | |
94 // Docked windows have bounds handled by the layout manager in AddChild(). | |
95 if (update_bounds) | |
96 window->SetBounds(local_bounds); | |
97 | |
98 if (has_restore_bounds) | |
99 state->SetRestoreBoundsInParent(restore_bounds); | |
100 } | |
101 | |
102 // Reparents the appropriate set of windows from |src| to |dst|. | |
103 // TODO(sky): This should take an aura::Window. http://crbug.com/671246. | |
104 void ReparentAllWindows(WmWindow* src, WmWindow* dst) { | |
105 // Set of windows to move. | |
106 const int kContainerIdsToMove[] = { | |
107 kShellWindowId_DefaultContainer, | |
108 kShellWindowId_DockedContainer, | |
109 kShellWindowId_PanelContainer, | |
110 kShellWindowId_AlwaysOnTopContainer, | |
111 kShellWindowId_SystemModalContainer, | |
112 kShellWindowId_LockSystemModalContainer, | |
113 kShellWindowId_UnparentedControlContainer, | |
114 kShellWindowId_OverlayContainer, | |
115 }; | |
116 const int kExtraContainerIdsToMoveInUnifiedMode[] = { | |
117 kShellWindowId_LockScreenContainer, | |
118 kShellWindowId_LockScreenWallpaperContainer, | |
119 }; | |
120 std::vector<int> container_ids( | |
121 kContainerIdsToMove, | |
122 kContainerIdsToMove + arraysize(kContainerIdsToMove)); | |
123 // Check the display mode as this is also necessary when trasitioning between | |
124 // mirror and unified mode. | |
125 if (WmShell::Get()->IsInUnifiedModeIgnoreMirroring()) { | |
126 for (int id : kExtraContainerIdsToMoveInUnifiedMode) | |
127 container_ids.push_back(id); | |
128 } | |
129 | |
130 for (int id : container_ids) { | |
131 WmWindow* src_container = src->GetChildByShellWindowId(id); | |
132 WmWindow* dst_container = dst->GetChildByShellWindowId(id); | |
133 while (!src_container->GetChildren().empty()) { | |
134 // Restart iteration from the source container windows each time as they | |
135 // may change as a result of moving other windows. | |
136 WmWindow::Windows src_container_children = src_container->GetChildren(); | |
137 WmWindow::Windows::const_iterator iter = src_container_children.begin(); | |
138 while (iter != src_container_children.end() && | |
139 SystemModalContainerLayoutManager::IsModalBackground(*iter)) { | |
140 ++iter; | |
141 } | |
142 // If the entire window list is modal background windows then stop. | |
143 if (iter == src_container_children.end()) | |
144 break; | |
145 ReparentWindow(*iter, dst_container); | |
146 } | |
147 } | |
148 } | |
149 | |
150 // Creates a new window for use as a container. | |
151 // TODO(sky): This should create an aura::Window. http://crbug.com/671246. | |
152 WmWindow* CreateContainer(int window_id, const char* name, WmWindow* parent) { | |
153 WmWindow* window = WmShell::Get()->NewWindow(ui::wm::WINDOW_TYPE_UNKNOWN, | |
154 ui::LAYER_NOT_DRAWN); | |
155 window->SetShellWindowId(window_id); | |
156 window->SetName(name); | |
157 parent->AddChild(window); | |
158 if (window_id != kShellWindowId_UnparentedControlContainer) | |
159 window->Show(); | |
160 return window; | |
161 } | |
162 | |
163 // TODO(sky): This should take an aura::Window. http://crbug.com/671246. | |
164 bool ShouldDestroyWindowInCloseChildWindows(WmWindow* window) { | |
165 if (!WmWindowAura::GetAuraWindow(window)->owned_by_parent()) | |
166 return false; | |
167 | |
168 if (!WmShell::Get()->IsRunningInMash()) | |
169 return true; | |
170 | |
171 aura::WindowMus* window_mus = | |
172 aura::WindowMus::Get(WmWindowAura::GetAuraWindow(window)); | |
173 return Shell::window_tree_client()->WasCreatedByThisClient(window_mus) || | |
174 Shell::window_tree_client()->IsRoot(window_mus); | |
175 } | |
176 | |
177 } // namespace | |
178 | |
179 void RootWindowController::SetWallpaperWidgetController( | |
180 WallpaperWidgetController* controller) { | |
181 wallpaper_widget_controller_.reset(controller); | |
182 } | |
183 | |
184 void RootWindowController::SetAnimatingWallpaperWidgetController( | |
185 AnimatingWallpaperWidgetController* controller) { | |
186 if (animating_wallpaper_widget_controller_.get()) | |
187 animating_wallpaper_widget_controller_->StopAnimating(); | |
188 animating_wallpaper_widget_controller_.reset(controller); | |
189 } | |
190 | |
191 wm::WorkspaceWindowState RootWindowController::GetWorkspaceWindowState() { | |
192 return workspace_controller_ ? workspace_controller()->GetWindowState() | |
193 : wm::WORKSPACE_WINDOW_STATE_DEFAULT; | |
194 } | |
195 | |
196 SystemModalContainerLayoutManager* | |
197 RootWindowController::GetSystemModalLayoutManager(WmWindow* window) { | |
198 WmWindow* modal_container = nullptr; | |
199 if (window) { | |
200 WmWindow* window_container = wm::GetContainerForWindow(window); | |
201 if (window_container && | |
202 window_container->GetShellWindowId() >= | |
203 kShellWindowId_LockScreenContainer) { | |
204 modal_container = GetWmContainer(kShellWindowId_LockSystemModalContainer); | |
205 } else { | |
206 modal_container = GetWmContainer(kShellWindowId_SystemModalContainer); | |
207 } | |
208 } else { | |
209 int modal_window_id = | |
210 WmShell::Get()->GetSessionStateDelegate()->IsUserSessionBlocked() | |
211 ? kShellWindowId_LockSystemModalContainer | |
212 : kShellWindowId_SystemModalContainer; | |
213 modal_container = GetWmContainer(modal_window_id); | |
214 } | |
215 return modal_container ? static_cast<SystemModalContainerLayoutManager*>( | |
216 modal_container->GetLayoutManager()) | |
217 : nullptr; | |
218 } | |
219 | |
220 bool RootWindowController::HasShelf() { | |
221 return wm_shelf_->shelf_widget() != nullptr; | |
222 } | |
223 | |
224 WmShelf* RootWindowController::GetShelf() { | |
225 return wm_shelf_.get(); | |
226 } | |
227 | |
228 void RootWindowController::CreateShelf() { | |
229 if (wm_shelf_->IsShelfInitialized()) | |
230 return; | |
231 wm_shelf_->InitializeShelf(); | |
232 | |
233 if (panel_layout_manager_) | |
234 panel_layout_manager_->SetShelf(wm_shelf_.get()); | |
235 if (docked_window_layout_manager_) { | |
236 docked_window_layout_manager_->SetShelf(wm_shelf_.get()); | |
237 if (wm_shelf_->shelf_layout_manager()) | |
238 docked_window_layout_manager_->AddObserver( | |
239 wm_shelf_->shelf_layout_manager()); | |
240 } | |
241 | |
242 // Notify shell observers that the shelf has been created. | |
243 // TODO(jamescook): Move this into WmShelf::InitializeShelf(). This will | |
244 // require changing AttachedPanelWidgetTargeter's access to WmShelf. | |
245 WmShell::Get()->NotifyShelfCreatedForRootWindow( | |
246 WmWindowAura::Get(GetRootWindow())); | |
247 | |
248 wm_shelf_->shelf_widget()->PostCreateShelf(); | |
249 } | |
250 | |
251 void RootWindowController::ShowShelf() { | |
252 if (!wm_shelf_->IsShelfInitialized()) | |
253 return; | |
254 // TODO(jamescook): Move this into WmShelf. | |
255 wm_shelf_->shelf_widget()->SetShelfVisibility(true); | |
256 wm_shelf_->shelf_widget()->status_area_widget()->Show(); | |
257 } | |
258 | |
259 const WmWindow* RootWindowController::GetWindow() const { | |
260 return WmWindowAura::Get(GetRootWindow()); | |
261 } | |
262 | |
263 const WmWindow* RootWindowController::GetWmContainer(int container_id) const { | |
264 const aura::Window* window = GetContainer(container_id); | |
265 return WmWindowAura::Get(window); | |
266 } | |
267 | |
268 void RootWindowController::ConfigureWidgetInitParamsForContainer( | |
269 views::Widget* widget, | |
270 int shell_container_id, | |
271 views::Widget::InitParams* init_params) { | |
272 init_params->parent = GetContainer(shell_container_id); | |
273 } | |
274 | |
275 WmWindow* RootWindowController::FindEventTarget( | |
276 const gfx::Point& location_in_screen) { | |
277 gfx::Point location_in_root(location_in_screen); | |
278 aura::Window* root_window = GetRootWindow(); | |
279 ::wm::ConvertPointFromScreen(root_window, &location_in_root); | |
280 ui::MouseEvent test_event(ui::ET_MOUSE_MOVED, location_in_root, | |
281 location_in_root, ui::EventTimeForNow(), | |
282 ui::EF_NONE, ui::EF_NONE); | |
283 ui::EventTarget* event_handler = | |
284 static_cast<ui::EventTarget*>(root_window) | |
285 ->GetEventTargeter() | |
286 ->FindTargetForEvent(root_window, &test_event); | |
287 return WmWindowAura::Get(static_cast<aura::Window*>(event_handler)); | |
288 } | |
289 | |
290 gfx::Point RootWindowController::GetLastMouseLocationInRoot() { | |
291 return window_tree_host_->dispatcher()->GetLastMouseLocationInRoot(); | |
292 } | |
293 | |
294 void RootWindowController::ShowContextMenu(const gfx::Point& location_in_screen, | |
295 ui::MenuSourceType source_type) { | |
296 ShellDelegate* delegate = WmShell::Get()->delegate(); | |
297 DCHECK(delegate); | |
298 menu_model_.reset(delegate->CreateContextMenu(wm_shelf_.get(), nullptr)); | |
299 if (!menu_model_) | |
300 return; | |
301 | |
302 menu_model_adapter_ = base::MakeUnique<views::MenuModelAdapter>( | |
303 menu_model_.get(), | |
304 base::Bind(&RootWindowController::OnMenuClosed, base::Unretained(this))); | |
305 | |
306 // The wallpaper controller may not be set yet if the user clicked on the | |
307 // status area before the initial animation completion. See crbug.com/222218 | |
308 if (!wallpaper_widget_controller()) | |
309 return; | |
310 | |
311 menu_runner_ = base::MakeUnique<views::MenuRunner>( | |
312 menu_model_adapter_->CreateMenu(), | |
313 views::MenuRunner::CONTEXT_MENU | views::MenuRunner::ASYNC); | |
314 ignore_result( | |
315 menu_runner_->RunMenuAt(wallpaper_widget_controller()->widget(), nullptr, | |
316 gfx::Rect(location_in_screen, gfx::Size()), | |
317 views::MENU_ANCHOR_TOPLEFT, source_type)); | |
318 } | |
319 | |
320 void RootWindowController::UpdateAfterLoginStatusChange(LoginStatus status) { | |
321 StatusAreaWidget* status_area_widget = | |
322 wm_shelf_->shelf_widget()->status_area_widget(); | |
323 if (status_area_widget) | |
324 status_area_widget->UpdateAfterLoginStatusChange(status); | |
325 } | |
326 | |
327 void RootWindowController::MoveWindowsTo(aura::Window* dst) { | |
328 // Clear the workspace controller, so it doesn't incorrectly update the shelf. | |
329 workspace_controller_.reset(); | |
330 ReparentAllWindows(GetWindow(), WmWindowAura::Get(dst)); | |
331 } | |
332 | |
333 void RootWindowController::CreateContainers() { | |
334 WmWindow* root = GetWindow(); | |
335 // These containers are just used by PowerButtonController to animate groups | |
336 // of containers simultaneously without messing up the current transformations | |
337 // on those containers. These are direct children of the root window; all of | |
338 // the other containers are their children. | |
339 | |
340 // The wallpaper container is not part of the lock animation, so it is not | |
341 // included in those animate groups. When the screen is locked, the wallpaper | |
342 // is moved to the lock screen wallpaper container (and moved back on unlock). | |
343 // Ensure that there's an opaque layer occluding the non-lock-screen layers. | |
344 WmWindow* wallpaper_container = CreateContainer( | |
345 kShellWindowId_WallpaperContainer, "WallpaperContainer", root); | |
346 wallpaper_container->SetChildWindowVisibilityChangesAnimated(); | |
347 | |
348 WmWindow* non_lock_screen_containers = | |
349 CreateContainer(kShellWindowId_NonLockScreenContainersContainer, | |
350 "NonLockScreenContainersContainer", root); | |
351 // Clip all windows inside this container, as half pixel of the window's | |
352 // texture may become visible when the screen is scaled. crbug.com/368591. | |
353 non_lock_screen_containers->SetMasksToBounds(true); | |
354 | |
355 WmWindow* lock_wallpaper_containers = | |
356 CreateContainer(kShellWindowId_LockScreenWallpaperContainer, | |
357 "LockScreenWallpaperContainer", root); | |
358 lock_wallpaper_containers->SetChildWindowVisibilityChangesAnimated(); | |
359 | |
360 WmWindow* lock_screen_containers = | |
361 CreateContainer(kShellWindowId_LockScreenContainersContainer, | |
362 "LockScreenContainersContainer", root); | |
363 WmWindow* lock_screen_related_containers = | |
364 CreateContainer(kShellWindowId_LockScreenRelatedContainersContainer, | |
365 "LockScreenRelatedContainersContainer", root); | |
366 | |
367 CreateContainer(kShellWindowId_UnparentedControlContainer, | |
368 "UnparentedControlContainer", non_lock_screen_containers); | |
369 | |
370 WmWindow* default_container = | |
371 CreateContainer(kShellWindowId_DefaultContainer, "DefaultContainer", | |
372 non_lock_screen_containers); | |
373 default_container->SetChildWindowVisibilityChangesAnimated(); | |
374 default_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
375 default_container->SetBoundsInScreenBehaviorForChildren( | |
376 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
377 default_container->SetChildrenUseExtendedHitRegion(); | |
378 | |
379 WmWindow* always_on_top_container = | |
380 CreateContainer(kShellWindowId_AlwaysOnTopContainer, | |
381 "AlwaysOnTopContainer", non_lock_screen_containers); | |
382 always_on_top_container->SetChildWindowVisibilityChangesAnimated(); | |
383 always_on_top_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
384 always_on_top_container->SetBoundsInScreenBehaviorForChildren( | |
385 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
386 | |
387 WmWindow* docked_container = | |
388 CreateContainer(kShellWindowId_DockedContainer, "DockedContainer", | |
389 non_lock_screen_containers); | |
390 docked_container->SetChildWindowVisibilityChangesAnimated(); | |
391 docked_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
392 docked_container->SetBoundsInScreenBehaviorForChildren( | |
393 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
394 docked_container->SetChildrenUseExtendedHitRegion(); | |
395 | |
396 WmWindow* shelf_container = | |
397 CreateContainer(kShellWindowId_ShelfContainer, "ShelfContainer", | |
398 non_lock_screen_containers); | |
399 shelf_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
400 shelf_container->SetBoundsInScreenBehaviorForChildren( | |
401 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
402 shelf_container->SetLockedToRoot(true); | |
403 | |
404 WmWindow* panel_container = | |
405 CreateContainer(kShellWindowId_PanelContainer, "PanelContainer", | |
406 non_lock_screen_containers); | |
407 panel_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
408 panel_container->SetBoundsInScreenBehaviorForChildren( | |
409 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
410 | |
411 WmWindow* shelf_bubble_container = | |
412 CreateContainer(kShellWindowId_ShelfBubbleContainer, | |
413 "ShelfBubbleContainer", non_lock_screen_containers); | |
414 shelf_bubble_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
415 shelf_bubble_container->SetBoundsInScreenBehaviorForChildren( | |
416 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
417 shelf_bubble_container->SetLockedToRoot(true); | |
418 | |
419 WmWindow* app_list_container = | |
420 CreateContainer(kShellWindowId_AppListContainer, "AppListContainer", | |
421 non_lock_screen_containers); | |
422 app_list_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
423 app_list_container->SetBoundsInScreenBehaviorForChildren( | |
424 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
425 | |
426 WmWindow* modal_container = | |
427 CreateContainer(kShellWindowId_SystemModalContainer, | |
428 "SystemModalContainer", non_lock_screen_containers); | |
429 modal_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
430 modal_container->SetChildWindowVisibilityChangesAnimated(); | |
431 modal_container->SetBoundsInScreenBehaviorForChildren( | |
432 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
433 modal_container->SetChildrenUseExtendedHitRegion(); | |
434 | |
435 // TODO(beng): Figure out if we can make this use | |
436 // SystemModalContainerEventFilter instead of stops_event_propagation. | |
437 WmWindow* lock_container = | |
438 CreateContainer(kShellWindowId_LockScreenContainer, "LockScreenContainer", | |
439 lock_screen_containers); | |
440 lock_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
441 lock_container->SetBoundsInScreenBehaviorForChildren( | |
442 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
443 // TODO(beng): stopsevents | |
444 | |
445 WmWindow* lock_modal_container = | |
446 CreateContainer(kShellWindowId_LockSystemModalContainer, | |
447 "LockSystemModalContainer", lock_screen_containers); | |
448 lock_modal_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
449 lock_modal_container->SetChildWindowVisibilityChangesAnimated(); | |
450 lock_modal_container->SetBoundsInScreenBehaviorForChildren( | |
451 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
452 lock_modal_container->SetChildrenUseExtendedHitRegion(); | |
453 | |
454 WmWindow* status_container = | |
455 CreateContainer(kShellWindowId_StatusContainer, "StatusContainer", | |
456 lock_screen_related_containers); | |
457 status_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
458 status_container->SetBoundsInScreenBehaviorForChildren( | |
459 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
460 status_container->SetLockedToRoot(true); | |
461 | |
462 WmWindow* settings_bubble_container = | |
463 CreateContainer(kShellWindowId_SettingBubbleContainer, | |
464 "SettingBubbleContainer", lock_screen_related_containers); | |
465 settings_bubble_container->SetChildWindowVisibilityChangesAnimated(); | |
466 settings_bubble_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
467 settings_bubble_container->SetBoundsInScreenBehaviorForChildren( | |
468 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
469 settings_bubble_container->SetLockedToRoot(true); | |
470 | |
471 WmWindow* virtual_keyboard_parent_container = CreateContainer( | |
472 kShellWindowId_ImeWindowParentContainer, "VirtualKeyboardParentContainer", | |
473 lock_screen_related_containers); | |
474 virtual_keyboard_parent_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
475 virtual_keyboard_parent_container->SetBoundsInScreenBehaviorForChildren( | |
476 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
477 | |
478 WmWindow* menu_container = | |
479 CreateContainer(kShellWindowId_MenuContainer, "MenuContainer", | |
480 lock_screen_related_containers); | |
481 menu_container->SetChildWindowVisibilityChangesAnimated(); | |
482 menu_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
483 menu_container->SetBoundsInScreenBehaviorForChildren( | |
484 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
485 | |
486 WmWindow* drag_drop_container = CreateContainer( | |
487 kShellWindowId_DragImageAndTooltipContainer, | |
488 "DragImageAndTooltipContainer", lock_screen_related_containers); | |
489 drag_drop_container->SetChildWindowVisibilityChangesAnimated(); | |
490 drag_drop_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
491 drag_drop_container->SetBoundsInScreenBehaviorForChildren( | |
492 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
493 | |
494 WmWindow* overlay_container = | |
495 CreateContainer(kShellWindowId_OverlayContainer, "OverlayContainer", | |
496 lock_screen_related_containers); | |
497 overlay_container->SetSnapsChildrenToPhysicalPixelBoundary(); | |
498 overlay_container->SetBoundsInScreenBehaviorForChildren( | |
499 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
500 | |
501 WmWindow* mouse_cursor_container = CreateContainer( | |
502 kShellWindowId_MouseCursorContainer, "MouseCursorContainer", root); | |
503 mouse_cursor_container->SetBoundsInScreenBehaviorForChildren( | |
504 WmWindow::BoundsInScreenBehavior::USE_SCREEN_COORDINATES); | |
505 | |
506 CreateContainer(kShellWindowId_PowerButtonAnimationContainer, | |
507 "PowerButtonAnimationContainer", root); | |
508 } | |
509 | |
510 void RootWindowController::CreateLayoutManagers() { | |
511 GetShelf()->CreateShelfWidget(GetWindow()); | |
512 | |
513 WmWindow* root = GetWindow(); | |
514 root_window_layout_manager_ = new wm::RootWindowLayoutManager(root); | |
515 root->SetLayoutManager(base::WrapUnique(root_window_layout_manager_)); | |
516 | |
517 WmWindow* default_container = GetWmContainer(kShellWindowId_DefaultContainer); | |
518 // Installs WorkspaceLayoutManager on |default_container|. | |
519 workspace_controller_.reset(new WorkspaceController(default_container)); | |
520 | |
521 WmWindow* modal_container = | |
522 GetWmContainer(kShellWindowId_SystemModalContainer); | |
523 DCHECK(modal_container); | |
524 modal_container->SetLayoutManager( | |
525 base::MakeUnique<SystemModalContainerLayoutManager>(modal_container)); | |
526 | |
527 WmWindow* lock_modal_container = | |
528 GetWmContainer(kShellWindowId_LockSystemModalContainer); | |
529 DCHECK(lock_modal_container); | |
530 lock_modal_container->SetLayoutManager( | |
531 base::MakeUnique<SystemModalContainerLayoutManager>( | |
532 lock_modal_container)); | |
533 | |
534 WmWindow* lock_container = GetWmContainer(kShellWindowId_LockScreenContainer); | |
535 DCHECK(lock_container); | |
536 lock_container->SetLayoutManager( | |
537 base::MakeUnique<LockLayoutManager>(lock_container)); | |
538 | |
539 WmWindow* always_on_top_container = | |
540 GetWmContainer(kShellWindowId_AlwaysOnTopContainer); | |
541 DCHECK(always_on_top_container); | |
542 always_on_top_controller_ = | |
543 base::MakeUnique<AlwaysOnTopController>(always_on_top_container); | |
544 | |
545 // Create Docked windows layout manager | |
546 WmWindow* docked_container = GetWmContainer(kShellWindowId_DockedContainer); | |
547 docked_window_layout_manager_ = | |
548 new DockedWindowLayoutManager(docked_container); | |
549 docked_container->SetLayoutManager( | |
550 base::WrapUnique(docked_window_layout_manager_)); | |
551 | |
552 // Create Panel layout manager | |
553 WmWindow* panel_container = GetWmContainer(kShellWindowId_PanelContainer); | |
554 panel_layout_manager_ = new PanelLayoutManager(panel_container); | |
555 panel_container->SetLayoutManager(base::WrapUnique(panel_layout_manager_)); | |
556 | |
557 wm::WmSnapToPixelLayoutManager::InstallOnContainers(root); | |
558 } | |
559 | |
560 void RootWindowController::ResetRootForNewWindowsIfNecessary() { | |
561 WmShell* shell = WmShell::Get(); | |
562 // Change the target root window before closing child windows. If any child | |
563 // being removed triggers a relayout of the shelf it will try to build a | |
564 // window list adding windows from the target root window's containers which | |
565 // may have already gone away. | |
566 WmWindow* root = GetWindow(); | |
567 if (shell->GetRootWindowForNewWindows() == root) { | |
568 // The root window for new windows is being destroyed. Switch to the primary | |
569 // root window if possible. | |
570 WmWindow* primary_root = shell->GetPrimaryRootWindow(); | |
571 shell->set_root_window_for_new_windows(primary_root == root ? nullptr | |
572 : primary_root); | |
573 } | |
574 } | |
575 | |
576 // TODO(sky): fold into CloseChildWindows() when move back. | |
577 void RootWindowController::CloseChildWindowsImpl() { | |
578 // NOTE: this may be called multiple times. | |
579 | |
580 // |panel_layout_manager_| needs to be shut down before windows are destroyed. | |
581 if (panel_layout_manager_) { | |
582 panel_layout_manager_->Shutdown(); | |
583 panel_layout_manager_ = nullptr; | |
584 } | |
585 | |
586 // |docked_window_layout_manager_| needs to be shut down before windows are | |
587 // destroyed. | |
588 if (docked_window_layout_manager_) { | |
589 docked_window_layout_manager_->Shutdown(); | |
590 docked_window_layout_manager_ = nullptr; | |
591 } | |
592 | |
593 WmShelf* shelf = GetShelf(); | |
594 shelf->ShutdownShelfWidget(); | |
595 | |
596 workspace_controller_.reset(); | |
597 | |
598 // Explicitly destroy top level windows. We do this because such windows may | |
599 // query the RootWindow for state. | |
600 WmWindowTracker non_toplevel_windows; | |
601 WmWindow* root = GetWindow(); | |
602 non_toplevel_windows.Add(root); | |
603 while (!non_toplevel_windows.windows().empty()) { | |
604 WmWindow* non_toplevel_window = non_toplevel_windows.Pop(); | |
605 WmWindowTracker toplevel_windows; | |
606 for (WmWindow* child : non_toplevel_window->GetChildren()) { | |
607 if (!ShouldDestroyWindowInCloseChildWindows(child)) | |
608 continue; | |
609 if (child->HasNonClientArea()) | |
610 toplevel_windows.Add(child); | |
611 else | |
612 non_toplevel_windows.Add(child); | |
613 } | |
614 while (!toplevel_windows.windows().empty()) | |
615 toplevel_windows.Pop()->Destroy(); | |
616 } | |
617 // And then remove the containers. | |
618 while (!root->GetChildren().empty()) { | |
619 WmWindow* child = root->GetChildren()[0]; | |
620 if (ShouldDestroyWindowInCloseChildWindows(child)) | |
621 child->Destroy(); | |
622 else | |
623 root->RemoveChild(child); | |
624 } | |
625 | |
626 shelf->DestroyShelfWidget(); | |
627 | |
628 // CloseChildWindows() may be called twice during the shutdown of ash | |
629 // unittests. Avoid notifying WmShelf that the shelf has been destroyed twice. | |
630 if (shelf->IsShelfInitialized()) | |
631 shelf->ShutdownShelf(); | |
632 } | |
633 | |
634 void RootWindowController::OnMenuClosed() { | |
635 menu_runner_.reset(); | |
636 menu_model_adapter_.reset(); | |
637 menu_model_.reset(); | |
638 wm_shelf_->UpdateVisibilityState(); | |
639 } | |
640 | |
641 } // namespace ash | |
OLD | NEW |