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/root_window_controller.h" |
7 #include "ash/shell.h" | 8 #include "ash/shell.h" |
8 #include "ash/shell_window_ids.h" | 9 #include "ash/shell_window_ids.h" |
| 10 #include "ash/wm/property_util.h" |
9 #include "ash/wm/window_modality_controller.h" | 11 #include "ash/wm/window_modality_controller.h" |
10 #include "ash/wm/window_util.h" | 12 #include "ash/wm/window_util.h" |
| 13 #include "ash/wm/workspace_controller.h" |
11 #include "base/auto_reset.h" | 14 #include "base/auto_reset.h" |
12 #include "ui/aura/client/activation_change_observer.h" | 15 #include "ui/aura/client/activation_change_observer.h" |
13 #include "ui/aura/client/activation_delegate.h" | 16 #include "ui/aura/client/activation_delegate.h" |
14 #include "ui/aura/client/aura_constants.h" | 17 #include "ui/aura/client/aura_constants.h" |
15 #include "ui/aura/env.h" | 18 #include "ui/aura/env.h" |
16 #include "ui/aura/focus_manager.h" | 19 #include "ui/aura/focus_manager.h" |
17 #include "ui/aura/root_window.h" | 20 #include "ui/aura/root_window.h" |
18 #include "ui/aura/window.h" | 21 #include "ui/aura/window.h" |
19 #include "ui/aura/window_delegate.h" | 22 #include "ui/aura/window_delegate.h" |
20 #include "ui/base/ui_base_types.h" | 23 #include "ui/base/ui_base_types.h" |
21 #include "ui/compositor/layer.h" | 24 #include "ui/compositor/layer.h" |
22 | 25 |
23 namespace ash { | 26 namespace ash { |
24 namespace internal { | 27 namespace internal { |
25 namespace { | 28 namespace { |
26 | 29 |
27 // These are the list of container ids of containers which may contain windows | 30 // These are the list of container ids of containers which may contain windows |
28 // that need to be activated in the order that they should be activated. | 31 // that need to be activated in the order that they should be activated. |
29 const int kWindowContainerIds[] = { | 32 const int kWindowContainerIds[] = { |
30 kShellWindowId_LockSystemModalContainer, | 33 kShellWindowId_LockSystemModalContainer, |
31 kShellWindowId_SettingBubbleContainer, | 34 kShellWindowId_SettingBubbleContainer, |
32 kShellWindowId_LockScreenContainer, | 35 kShellWindowId_LockScreenContainer, |
33 kShellWindowId_SystemModalContainer, | 36 kShellWindowId_SystemModalContainer, |
34 kShellWindowId_AlwaysOnTopContainer, | 37 kShellWindowId_AlwaysOnTopContainer, |
35 kShellWindowId_AppListContainer, | 38 kShellWindowId_AppListContainer, |
| 39 // TODO(sky): defaultcontainer shouldn't be in the list with workspace2. |
36 kShellWindowId_DefaultContainer, | 40 kShellWindowId_DefaultContainer, |
37 | 41 |
38 // Panel, launcher and status are intentionally checked after other | 42 // Panel, launcher and status are intentionally checked after other |
39 // containers even though these layers are higher. The user expects their | 43 // containers even though these layers are higher. The user expects their |
40 // windows to be focused before these elements. | 44 // windows to be focused before these elements. |
41 kShellWindowId_PanelContainer, | 45 kShellWindowId_PanelContainer, |
42 kShellWindowId_LauncherContainer, | 46 kShellWindowId_LauncherContainer, |
43 kShellWindowId_StatusContainer, | 47 kShellWindowId_StatusContainer, |
44 }; | 48 }; |
45 | 49 |
46 // Returns true if children of |window| can be activated. | 50 // Returns true if children of |window| can be activated. |
47 // These are the only containers in which windows can receive focus. | 51 // These are the only containers in which windows can receive focus. |
48 bool SupportsChildActivation(aura::Window* window) { | 52 bool SupportsChildActivation(aura::Window* window) { |
| 53 // TODO(sky): straighten this out when workspace2 is the default. |
| 54 // kShellWindowId_WorkspaceContainer isn't in |kWindowContainerIds| since it |
| 55 // needs to be special cased in GetTopmostWindowToActivate(). |
| 56 if (window->id() == kShellWindowId_WorkspaceContainer) |
| 57 return true; |
| 58 |
49 for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) { | 59 for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) { |
50 if (window->id() == kWindowContainerIds[i]) | 60 if (window->id() == kWindowContainerIds[i] && |
| 61 (window->id() != kShellWindowId_DefaultContainer || |
| 62 !WorkspaceController::IsWorkspace2Enabled())) { |
51 return true; | 63 return true; |
| 64 } |
52 } | 65 } |
53 return false; | 66 return false; |
54 } | 67 } |
55 | 68 |
56 bool HasModalTransientChild(aura::Window* window) { | 69 bool HasModalTransientChild(aura::Window* window) { |
57 aura::Window::Windows::const_iterator it; | 70 aura::Window::Windows::const_iterator it; |
58 for (it = window->transient_children().begin(); | 71 for (it = window->transient_children().begin(); |
59 it != window->transient_children().end(); | 72 it != window->transient_children().end(); |
60 ++it) { | 73 ++it) { |
61 if ((*it)->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW) | 74 if ((*it)->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW) |
62 return true; | 75 return true; |
63 } | 76 } |
64 return false; | 77 return false; |
65 } | 78 } |
66 | 79 |
67 // See description in VisibilityMatches. | 80 // See description in VisibilityMatches. |
68 enum ActivateVisibilityType { | 81 enum ActivateVisibilityType { |
69 TARGET_VISIBILITY, | 82 TARGET_VISIBILITY, |
70 CURRENT_VISIBILITY, | 83 CURRENT_VISIBILITY, |
71 }; | 84 }; |
72 | 85 |
73 // Used by CanActivateWindowWithEvent() to test the visibility of a window. | 86 // Used by CanActivateWindowWithEvent() to test the visibility of a window. |
74 // This is used by two distinct code paths: | 87 // This is used by two distinct code paths: |
75 // . when activating from an event we only care about the actual visibility. | 88 // . when activating from an event we only care about the actual visibility. |
76 // . when activating because of a keyboard accelerator, in which case we | 89 // . when activating because of a keyboard accelerator, in which case we |
77 // care about the TargetVisibility. | 90 // care about the TargetVisibility. |
78 bool VisibilityMatches(aura::Window* window, ActivateVisibilityType type) { | 91 bool VisibilityMatches(aura::Window* window, ActivateVisibilityType type) { |
79 bool visible = (type == CURRENT_VISIBILITY) ? window->IsVisible() : | 92 bool visible = (type == CURRENT_VISIBILITY) ? window->IsVisible() : |
80 window->TargetVisibility(); | 93 window->TargetVisibility(); |
81 return visible || wm::IsWindowMinimized(window); | 94 return visible || wm::IsWindowMinimized(window) || |
| 95 (window->TargetVisibility() && |
| 96 window->parent()->id() == kShellWindowId_WorkspaceContainer); |
82 } | 97 } |
83 | 98 |
84 // Returns true if |window| can be activated or deactivated. | 99 // Returns true if |window| can be activated or deactivated. |
85 // A window manager typically defines some notion of "top level window" that | 100 // A window manager typically defines some notion of "top level window" that |
86 // supports activation/deactivation. | 101 // supports activation/deactivation. |
87 bool CanActivateWindowWithEvent(aura::Window* window, | 102 bool CanActivateWindowWithEvent(aura::Window* window, |
88 const ui::Event* event, | 103 const ui::Event* event, |
89 ActivateVisibilityType visibility_type) { | 104 ActivateVisibilityType visibility_type) { |
90 return window && | 105 return window && |
91 VisibilityMatches(window, visibility_type) && | 106 VisibilityMatches(window, visibility_type) && |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 | 258 |
244 AutoReset<bool> in_activate_window(&updating_activation_, true); | 259 AutoReset<bool> in_activate_window(&updating_activation_, true); |
245 // Nothing may actually have changed. | 260 // Nothing may actually have changed. |
246 if (active_window_ == window) | 261 if (active_window_ == window) |
247 return; | 262 return; |
248 // The stacking client may impose rules on what window configurations can be | 263 // The stacking client may impose rules on what window configurations can be |
249 // activated or deactivated. | 264 // activated or deactivated. |
250 if (window && !CanActivateWindowWithEvent(window, event, CURRENT_VISIBILITY)) | 265 if (window && !CanActivateWindowWithEvent(window, event, CURRENT_VISIBILITY)) |
251 return; | 266 return; |
252 | 267 |
| 268 // Make sure the workspace manager switches to the workspace for window. |
| 269 // Without this CanReceiveEvents() below returns false and activation never |
| 270 // changes. CanReceiveEvents() returns false if |window| isn't in the active |
| 271 // workspace, in which case its parent is not visible. |
| 272 // TODO(sky): if I instead change the opacity of the parent this isn't an |
| 273 // issue, but will make animations trickier... Consider which one is better. |
| 274 if (window) { |
| 275 internal::RootWindowController* root_window_controller = |
| 276 GetRootWindowController(window->GetRootWindow()); |
| 277 root_window_controller->workspace_controller()-> |
| 278 SetActiveWorkspaceByWindow(window); |
| 279 } |
| 280 |
253 // Restore minimized window. This needs to be done before CanReceiveEvents() | 281 // Restore minimized window. This needs to be done before CanReceiveEvents() |
254 // is called as that function checks window visibility. | 282 // is called as that function checks window visibility. |
255 if (window && wm::IsWindowMinimized(window)) | 283 if (window && wm::IsWindowMinimized(window)) |
256 window->Show(); | 284 window->Show(); |
257 | 285 |
258 // If the screen is locked, just bring the window to top so that | 286 // If the screen is locked, just bring the window to top so that |
259 // it will be activated when the lock window is destroyed. | 287 // it will be activated when the lock window is destroyed. |
260 if (window && !window->CanReceiveEvents()) { | 288 if (window && !window->CanReceiveEvents()) { |
261 StackTransientParentsBelowModalWindow(window); | 289 StackTransientParentsBelowModalWindow(window); |
262 window->parent()->StackChildAtTop(window); | 290 window->parent()->StackChildAtTop(window); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 if (container && container->Contains(ignore)) { | 342 if (container && container->Contains(ignore)) { |
315 current_container_index = i; | 343 current_container_index = i; |
316 break; | 344 break; |
317 } | 345 } |
318 } | 346 } |
319 | 347 |
320 // Look for windows to focus in that container and below. | 348 // Look for windows to focus in that container and below. |
321 aura::Window* window = NULL; | 349 aura::Window* window = NULL; |
322 for (; !window && current_container_index < arraysize(kWindowContainerIds); | 350 for (; !window && current_container_index < arraysize(kWindowContainerIds); |
323 current_container_index++) { | 351 current_container_index++) { |
324 | |
325 aura::Window::Windows containers = | 352 aura::Window::Windows containers = |
326 Shell::GetAllContainers(kWindowContainerIds[current_container_index]); | 353 Shell::GetAllContainers(kWindowContainerIds[current_container_index]); |
327 for (aura::Window::Windows::const_iterator iter = containers.begin(); | 354 for (aura::Window::Windows::const_iterator iter = containers.begin(); |
328 iter != containers.end(); | 355 iter != containers.end() && !window; ++iter) { |
329 ++iter) { | |
330 window = GetTopmostWindowToActivateInContainer((*iter), ignore); | 356 window = GetTopmostWindowToActivateInContainer((*iter), ignore); |
331 } | 357 } |
332 } | 358 } |
333 return window; | 359 return window; |
334 } | 360 } |
335 | 361 |
336 aura::Window* ActivationController::GetTopmostWindowToActivateInContainer( | 362 aura::Window* ActivationController::GetTopmostWindowToActivateInContainer( |
337 aura::Window* container, | 363 aura::Window* container, |
338 aura::Window* ignore) const { | 364 aura::Window* ignore) const { |
| 365 // Workspace2 has an extra level of windows that needs to be special cased. |
| 366 if (container->id() == kShellWindowId_DefaultContainer && |
| 367 WorkspaceController::IsWorkspace2Enabled()) { |
| 368 for (aura::Window::Windows::const_reverse_iterator i = |
| 369 container->children().rbegin(); |
| 370 i != container->children().rend(); ++i) { |
| 371 if ((*i)->IsVisible()) { |
| 372 aura::Window* window = GetTopmostWindowToActivateInContainer( |
| 373 *i, ignore); |
| 374 if (window) |
| 375 return window; |
| 376 } |
| 377 } |
| 378 return NULL; |
| 379 } |
339 for (aura::Window::Windows::const_reverse_iterator i = | 380 for (aura::Window::Windows::const_reverse_iterator i = |
340 container->children().rbegin(); | 381 container->children().rbegin(); |
341 i != container->children().rend(); | 382 i != container->children().rend(); |
342 ++i) { | 383 ++i) { |
343 if (*i != ignore && | 384 if (*i != ignore && |
344 CanActivateWindowWithEvent(*i, NULL, CURRENT_VISIBILITY) && | 385 CanActivateWindowWithEvent(*i, NULL, CURRENT_VISIBILITY) && |
345 !wm::IsWindowMinimized(*i)) | 386 !wm::IsWindowMinimized(*i)) |
346 return *i; | 387 return *i; |
347 } | 388 } |
348 return NULL; | 389 return NULL; |
349 } | 390 } |
350 | 391 |
351 } // namespace internal | 392 } // namespace internal |
352 } // namespace ash | 393 } // namespace ash |
OLD | NEW |