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