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.
5 #include "ash/wm/ash_focus_rules.h"
8 #include "ash/shell_window_ids.h"
9 #include "ash/wm/window_state.h"
10 #include "ui/aura/window.h"
16 // These are the list of container ids of containers which may contain windows
17 // that need to be activated in the order that they should be activated.
18 const int kWindowContainerIds
[] = {
19 kShellWindowId_OverlayContainer
,
20 kShellWindowId_LockSystemModalContainer
,
21 kShellWindowId_SettingBubbleContainer
,
22 kShellWindowId_LockScreenContainer
,
23 kShellWindowId_SystemModalContainer
,
24 kShellWindowId_AlwaysOnTopContainer
,
25 kShellWindowId_AppListContainer
,
26 kShellWindowId_DefaultContainer
,
28 // Docked, panel, launcher and status are intentionally checked after other
29 // containers even though these layers are higher. The user expects their
30 // windows to be focused before these elements.
31 kShellWindowId_DockedContainer
,
32 kShellWindowId_PanelContainer
,
33 kShellWindowId_ShelfContainer
,
34 kShellWindowId_StatusContainer
, };
36 bool BelongsToContainerWithEqualOrGreaterId(const aura::Window
* window
,
38 for (; window
; window
= window
->parent()) {
39 if (window
->id() >= container_id
)
47 ////////////////////////////////////////////////////////////////////////////////
48 // AshFocusRules, public:
50 AshFocusRules::AshFocusRules() {
53 AshFocusRules::~AshFocusRules() {
56 bool AshFocusRules::IsWindowConsideredActivatable(aura::Window
* window
) const {
57 // Only toplevel windows can be activated.
58 if (!IsToplevelWindow(window
))
61 // The window must be visible.
62 if (!IsWindowConsideredVisibleForActivation(window
))
68 ////////////////////////////////////////////////////////////////////////////////
69 // AshFocusRules, ::wm::FocusRules:
71 bool AshFocusRules::SupportsChildActivation(aura::Window
* window
) const {
72 if (window
->id() == kShellWindowId_DefaultContainer
)
75 for (size_t i
= 0; i
< arraysize(kWindowContainerIds
); i
++) {
76 if (window
->id() == kWindowContainerIds
[i
])
82 bool AshFocusRules::IsWindowConsideredVisibleForActivation(
83 aura::Window
* window
) const {
84 if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window
))
87 // Minimized windows are hidden in their minimized state, but they can always
89 if (wm::GetWindowState(window
)->IsMinimized())
92 return window
->TargetVisibility() &&
93 (window
->parent()->id() == kShellWindowId_DefaultContainer
||
94 window
->parent()->id() == kShellWindowId_LockScreenContainer
);
97 bool AshFocusRules::CanActivateWindow(aura::Window
* window
) const {
98 // Clearing activation is always permissible.
102 if (!BaseFocusRules::CanActivateWindow(window
))
105 if (Shell::GetInstance()->IsSystemModalWindowOpen()) {
106 return BelongsToContainerWithEqualOrGreaterId(
107 window
, kShellWindowId_SystemModalContainer
);
113 aura::Window
* AshFocusRules::GetNextActivatableWindow(
114 aura::Window
* ignore
) const {
117 int starting_container_index
= 0;
118 // If the container of the window losing focus is in the list, start from that
120 aura::Window
* root
= ignore
->GetRootWindow();
122 root
= Shell::GetTargetRootWindow();
123 int container_count
= static_cast<int>(arraysize(kWindowContainerIds
));
124 for (int i
= 0; ignore
&& i
< container_count
; i
++) {
125 aura::Window
* container
= Shell::GetContainer(root
, kWindowContainerIds
[i
]);
126 if (container
&& container
->Contains(ignore
)) {
127 starting_container_index
= i
;
132 // Look for windows to focus in |ignore|'s container. If none are found, we
133 // look in all the containers in front of |ignore|'s container, then all
135 aura::Window
* window
= NULL
;
136 for (int i
= starting_container_index
; !window
&& i
< container_count
; i
++)
137 window
= GetTopmostWindowToActivateForContainerIndex(i
, ignore
);
138 if (!window
&& starting_container_index
> 0) {
139 for (int i
= starting_container_index
- 1; !window
&& i
>= 0; i
--)
140 window
= GetTopmostWindowToActivateForContainerIndex(i
, ignore
);
145 ////////////////////////////////////////////////////////////////////////////////
146 // AshFocusRules, private:
148 aura::Window
* AshFocusRules::GetTopmostWindowToActivateForContainerIndex(
150 aura::Window
* ignore
) const {
151 aura::Window
* window
= NULL
;
152 aura::Window
* root
= ignore
? ignore
->GetRootWindow() : NULL
;
153 aura::Window::Windows containers
= Shell::GetContainersFromAllRootWindows(
154 kWindowContainerIds
[index
], root
);
155 for (aura::Window::Windows::const_iterator iter
= containers
.begin();
156 iter
!= containers
.end() && !window
; ++iter
) {
157 window
= GetTopmostWindowToActivateInContainer((*iter
), ignore
);
162 aura::Window
* AshFocusRules::GetTopmostWindowToActivateInContainer(
163 aura::Window
* container
,
164 aura::Window
* ignore
) const {
165 for (aura::Window::Windows::const_reverse_iterator i
=
166 container
->children().rbegin();
167 i
!= container
->children().rend();
169 WindowState
* window_state
= GetWindowState(*i
);
171 window_state
->CanActivate() &&
172 !window_state
->IsMinimized())