OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/wm/activation_controller.h" | 5 #include "ash/wm/activation_controller.h" |
6 | 6 |
7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
8 #include "ash/shell_window_ids.h" | 8 #include "ash/shell_window_ids.h" |
9 #include "ash/wm/window_modality_controller.h" | 9 #include "ash/wm/window_modality_controller.h" |
10 #include "ash/wm/window_util.h" | 10 #include "ash/wm/window_util.h" |
11 #include "base/auto_reset.h" | 11 #include "base/auto_reset.h" |
12 #include "ui/aura/client/activation_delegate.h" | 12 #include "ui/aura/client/activation_delegate.h" |
13 #include "ui/aura/client/aura_constants.h" | 13 #include "ui/aura/client/aura_constants.h" |
14 #include "ui/aura/env.h" | 14 #include "ui/aura/env.h" |
15 #include "ui/aura/root_window.h" | 15 #include "ui/aura/root_window.h" |
16 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
17 #include "ui/aura/window_delegate.h" | 17 #include "ui/aura/window_delegate.h" |
18 #include "ui/base/ui_base_types.h" | 18 #include "ui/base/ui_base_types.h" |
19 | 19 |
20 namespace ash { | 20 namespace ash { |
21 namespace internal { | 21 namespace internal { |
22 namespace { | 22 namespace { |
23 | 23 |
| 24 // These are the list of container ids of containers which may contain windows |
| 25 // that need to be activated in the order that they should be activated. |
| 26 const int kWindowContainerIds[] = { |
| 27 kShellWindowId_LockSystemModalContainer, |
| 28 kShellWindowId_LockScreenContainer, |
| 29 kShellWindowId_SystemModalContainer, |
| 30 kShellWindowId_AlwaysOnTopContainer, |
| 31 kShellWindowId_DefaultContainer, |
| 32 |
| 33 // Panel, launcher and status are intentionally checked after other |
| 34 // containers even though these layers are higher. The user expects their |
| 35 // windows to be focused before these elements. |
| 36 kShellWindowId_PanelContainer, |
| 37 kShellWindowId_LauncherContainer, |
| 38 kShellWindowId_StatusContainer, |
| 39 }; |
| 40 |
24 aura::Window* GetContainer(int id) { | 41 aura::Window* GetContainer(int id) { |
25 return Shell::GetInstance()->GetContainer(id); | 42 return Shell::GetInstance()->GetContainer(id); |
26 } | 43 } |
27 | 44 |
28 // Returns true if children of |window| can be activated. | 45 // Returns true if children of |window| can be activated. |
29 // These are the only containers in which windows can receive focus. | 46 // These are the only containers in which windows can receive focus. |
30 bool SupportsChildActivation(aura::Window* window) { | 47 bool SupportsChildActivation(aura::Window* window) { |
31 return window->id() == kShellWindowId_DefaultContainer || | 48 for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) { |
32 window->id() == kShellWindowId_AlwaysOnTopContainer || | 49 if (window->id() == kWindowContainerIds[i]) |
33 window->id() == kShellWindowId_PanelContainer || | 50 return true; |
34 window->id() == kShellWindowId_SystemModalContainer || | 51 } |
35 window->id() == kShellWindowId_StatusContainer || | 52 return false; |
36 window->id() == kShellWindowId_LauncherContainer || | |
37 window->id() == kShellWindowId_LockScreenContainer || | |
38 window->id() == kShellWindowId_LockSystemModalContainer; | |
39 } | 53 } |
40 | 54 |
41 // Returns true if |window| can be activated or deactivated. | 55 // Returns true if |window| can be activated or deactivated. |
42 // A window manager typically defines some notion of "top level window" that | 56 // A window manager typically defines some notion of "top level window" that |
43 // supports activation/deactivation. | 57 // supports activation/deactivation. |
44 bool CanActivateWindow(aura::Window* window) { | 58 bool CanActivateWindow(aura::Window* window) { |
45 return window && | 59 return window && |
46 window->IsVisible() && | 60 window->IsVisible() && |
47 (!aura::client::GetActivationDelegate(window) || | 61 (!aura::client::GetActivationDelegate(window) || |
48 aura::client::GetActivationDelegate(window)->ShouldActivate(NULL)) && | 62 aura::client::GetActivationDelegate(window)->ShouldActivate(NULL)) && |
(...skipping 13 matching lines...) Expand all Loading... |
62 transient_parent = transient_parent->transient_parent(); | 76 transient_parent = transient_parent->transient_parent(); |
63 } | 77 } |
64 } | 78 } |
65 | 79 |
66 } // namespace | 80 } // namespace |
67 | 81 |
68 //////////////////////////////////////////////////////////////////////////////// | 82 //////////////////////////////////////////////////////////////////////////////// |
69 // ActivationController, public: | 83 // ActivationController, public: |
70 | 84 |
71 ActivationController::ActivationController() | 85 ActivationController::ActivationController() |
72 : updating_activation_(false), | 86 : updating_activation_(false) { |
73 default_container_for_test_(NULL) { | |
74 aura::client::SetActivationClient(Shell::GetRootWindow(), this); | 87 aura::client::SetActivationClient(Shell::GetRootWindow(), this); |
75 aura::Env::GetInstance()->AddObserver(this); | 88 aura::Env::GetInstance()->AddObserver(this); |
76 Shell::GetRootWindow()->AddRootWindowObserver(this); | 89 Shell::GetRootWindow()->AddRootWindowObserver(this); |
77 } | 90 } |
78 | 91 |
79 ActivationController::~ActivationController() { | 92 ActivationController::~ActivationController() { |
80 Shell::GetRootWindow()->RemoveRootWindowObserver(this); | 93 Shell::GetRootWindow()->RemoveRootWindowObserver(this); |
81 aura::Env::GetInstance()->RemoveObserver(this); | 94 aura::Env::GetInstance()->RemoveObserver(this); |
82 } | 95 } |
83 | 96 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 //////////////////////////////////////////////////////////////////////////////// | 214 //////////////////////////////////////////////////////////////////////////////// |
202 // ActivationController, private: | 215 // ActivationController, private: |
203 | 216 |
204 void ActivationController::ActivateNextWindow(aura::Window* window) { | 217 void ActivationController::ActivateNextWindow(aura::Window* window) { |
205 if (wm::IsActiveWindow(window)) | 218 if (wm::IsActiveWindow(window)) |
206 ActivateWindow(GetTopmostWindowToActivate(window)); | 219 ActivateWindow(GetTopmostWindowToActivate(window)); |
207 } | 220 } |
208 | 221 |
209 aura::Window* ActivationController::GetTopmostWindowToActivate( | 222 aura::Window* ActivationController::GetTopmostWindowToActivate( |
210 aura::Window* ignore) const { | 223 aura::Window* ignore) const { |
211 const aura::Window* container = | 224 size_t current_container_index = 0; |
212 default_container_for_test_ ? default_container_for_test_ : | 225 // If the container of the window losing focus is in the list, start from that |
213 GetContainer(kShellWindowId_DefaultContainer); | 226 // container. |
214 // When destructing an active window that is in a container destructed after | 227 for (size_t i = 0; ignore && i < arraysize(kWindowContainerIds); i++) { |
215 // the default container during shell shutdown, |container| would be NULL | 228 aura::Window* container = GetContainer(kWindowContainerIds[i]); |
216 // because default container is destructed at this point. | 229 if (container && container->Contains(ignore)) { |
217 if (container) { | 230 current_container_index = i; |
218 for (aura::Window::Windows::const_reverse_iterator i = | 231 break; |
219 container->children().rbegin(); | |
220 i != container->children().rend(); | |
221 ++i) { | |
222 if (*i != ignore && CanActivateWindow(*i)) | |
223 return *i; | |
224 } | 232 } |
225 } | 233 } |
| 234 |
| 235 // Look for windows to focus in that container and below. |
| 236 aura::Window* window = NULL; |
| 237 for (; !window && current_container_index < arraysize(kWindowContainerIds); |
| 238 current_container_index++) { |
| 239 aura::Window* container = |
| 240 GetContainer(kWindowContainerIds[current_container_index]); |
| 241 if (container) |
| 242 window = GetTopmostWindowToActivateInContainer(container, ignore); |
| 243 } |
| 244 return window; |
| 245 } |
| 246 |
| 247 aura::Window* ActivationController::GetTopmostWindowToActivateInContainer( |
| 248 aura::Window* container, |
| 249 aura::Window* ignore) const { |
| 250 for (aura::Window::Windows::const_reverse_iterator i = |
| 251 container->children().rbegin(); |
| 252 i != container->children().rend(); |
| 253 ++i) { |
| 254 if (*i != ignore && CanActivateWindow(*i)) |
| 255 return *i; |
| 256 } |
226 return NULL; | 257 return NULL; |
227 } | 258 } |
228 | 259 |
229 } // namespace internal | 260 } // namespace internal |
230 } // namespace ash | 261 } // namespace ash |
OLD | NEW |