1 // Copyright (c) 2012 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/wm/stacking_controller.h" 6 7 #include "ash/root_window_controller.h" 8 #include "ash/session_state_delegate.h" 9 #include "ash/shell.h" 10 #include "ash/shell_window_ids.h" 11 #include "ash/wm/always_on_top_controller.h" 12 #include "ash/wm/coordinate_conversion.h" 13 #include "ash/wm/window_state.h" 14 #include "ui/aura/client/aura_constants.h" 15 #include "ui/aura/root_window.h" 16 #include "ui/aura/window.h" 17 #include "ui/base/ui_base_types.h" 18 19 namespace ash { 20 namespace { 21 22 // Find a root window that matches the |bounds|. If the virtual screen 23 // coordinates is enabled and the bounds is specified, the root window 24 // that matches the window's bound will be used. Otherwise, it'll 25 // return the active root window. 26 aura::Window* FindContainerRoot(const gfx::Rect& bounds) { 27 if (bounds.x() == 0 && bounds.y() == 0 && bounds.IsEmpty()) 28 return Shell::GetTargetRootWindow(); 29 return wm::GetRootWindowMatching(bounds); 30 } 31 32 aura::Window* GetContainerById(aura::Window* root, int id) { 33 return Shell::GetContainer(root, id); 34 } 35 36 bool IsSystemModal(aura::Window* window) { 37 return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM; 38 } 39 40 bool HasTransientParentWindow(aura::Window* window) { 41 return window->transient_parent() && 42 window->transient_parent()->type() != aura::client::WINDOW_TYPE_UNKNOWN; 43 } 44 45 internal::AlwaysOnTopController* 46 GetAlwaysOnTopController(aura::Window* root_window) { 47 return internal::GetRootWindowController(root_window)-> 48 always_on_top_controller(); 49 } 50 51 } // namespace 52 53 //////////////////////////////////////////////////////////////////////////////// 54 // StackingController, public: 55 56 StackingController::StackingController() { 57 } 58 59 StackingController::~StackingController() { 60 } 61 62 //////////////////////////////////////////////////////////////////////////////// 63 // StackingController, aura::client::WindowTreeClient implementation: 64 65 aura::Window* StackingController::GetDefaultParent(aura::Window* context, 66 aura::Window* window, 67 const gfx::Rect& bounds) { 68 aura::Window* target_root = NULL; 69 if (window->transient_parent()) { 70 // Transient window should use the same root as its transient parent. 71 target_root = window->transient_parent()->GetRootWindow(); 72 } else { 73 target_root = FindContainerRoot(bounds); 74 } 75 76 switch (window->type()) { 77 case aura::client::WINDOW_TYPE_NORMAL: 78 case aura::client::WINDOW_TYPE_POPUP: 79 if (IsSystemModal(window)) 80 return GetSystemModalContainer(target_root, window); 81 else if (HasTransientParentWindow(window)) 82 return internal::RootWindowController::GetContainerForWindow( 83 window->transient_parent()); 84 return GetAlwaysOnTopController(target_root)->GetContainer(window); 85 case aura::client::WINDOW_TYPE_CONTROL: 86 return GetContainerById( 87 target_root, internal::kShellWindowId_UnparentedControlContainer); 88 case aura::client::WINDOW_TYPE_PANEL: 89 if (wm::GetWindowState(window)->panel_attached()) 90 return GetContainerById(target_root, 91 internal::kShellWindowId_PanelContainer); 92 else 93 return GetAlwaysOnTopController(target_root)->GetContainer(window); 94 case aura::client::WINDOW_TYPE_MENU: 95 return GetContainerById( 96 target_root, internal::kShellWindowId_MenuContainer); 97 case aura::client::WINDOW_TYPE_TOOLTIP: 98 return GetContainerById( 99 target_root, internal::kShellWindowId_DragImageAndTooltipContainer); 100 default: 101 NOTREACHED() << "Window " << window->id() 102 << " has unhandled type " << window->type(); 103 break; 104 } 105 return NULL; 106 } 107 108 //////////////////////////////////////////////////////////////////////////////// 109 // StackingController, private: 110 111 aura::Window* StackingController::GetSystemModalContainer( 112 aura::Window* root, 113 aura::Window* window) const { 114 DCHECK(IsSystemModal(window)); 115 116 // If screen lock is not active and user session is active, 117 // all modal windows are placed into the normal modal container. 118 // In case of missing transient parent (it could happen for alerts from 119 // background pages) assume that the window belongs to user session. 120 SessionStateDelegate* session_state_delegate = 121 Shell::GetInstance()->session_state_delegate(); 122 if (!session_state_delegate->IsUserSessionBlocked() || 123 !window->transient_parent()) { 124 return GetContainerById(root, 125 internal::kShellWindowId_SystemModalContainer); 126 } 127 128 // Otherwise those that originate from LockScreen container and above are 129 // placed in the screen lock modal container. 130 int window_container_id = window->transient_parent()->parent()->id(); 131 aura::Window* container = NULL; 132 if (window_container_id < internal::kShellWindowId_LockScreenContainer) { 133 container = GetContainerById( 134 root, internal::kShellWindowId_SystemModalContainer); 135 } else { 136 container = GetContainerById( 137 root, internal::kShellWindowId_LockSystemModalContainer); 138 } 139 140 return container; 141 } 142 143 } // namespace ash 144