Added llvm into exceptions as we can't add README.chromium into 3rd party repository
[chromium-blink-merge.git] / ash / wm / ash_focus_rules.cc
blob6bcae35c95aa352baa060f1c1d3c6c0f99bcf761
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"
7 #include "ash/shell.h"
8 #include "ash/shell_window_ids.h"
9 #include "ash/wm/window_state.h"
10 #include "ui/aura/window.h"
12 namespace ash {
13 namespace wm {
14 namespace {
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,
37 int container_id) {
38 for (; window; window = window->parent()) {
39 if (window->id() >= container_id)
40 return true;
42 return false;
45 } // namespace
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))
59 return false;
61 // The window must be visible.
62 if (!IsWindowConsideredVisibleForActivation(window))
63 return false;
65 return true;
68 ////////////////////////////////////////////////////////////////////////////////
69 // AshFocusRules, ::wm::FocusRules:
71 bool AshFocusRules::SupportsChildActivation(aura::Window* window) const {
72 if (window->id() == kShellWindowId_DefaultContainer)
73 return true;
75 for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) {
76 if (window->id() == kWindowContainerIds[i])
77 return true;
79 return false;
82 bool AshFocusRules::IsWindowConsideredVisibleForActivation(
83 aura::Window* window) const {
84 if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window))
85 return true;
87 // Minimized windows are hidden in their minimized state, but they can always
88 // be activated.
89 if (wm::GetWindowState(window)->IsMinimized())
90 return true;
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.
99 if (!window)
100 return true;
102 if (!BaseFocusRules::CanActivateWindow(window))
103 return false;
105 if (Shell::GetInstance()->IsSystemModalWindowOpen()) {
106 return BelongsToContainerWithEqualOrGreaterId(
107 window, kShellWindowId_SystemModalContainer);
110 return true;
113 aura::Window* AshFocusRules::GetNextActivatableWindow(
114 aura::Window* ignore) const {
115 DCHECK(ignore);
117 int starting_container_index = 0;
118 // If the container of the window losing focus is in the list, start from that
119 // container.
120 aura::Window* root = ignore->GetRootWindow();
121 if (!root)
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;
128 break;
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
134 // behind.
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);
142 return window;
145 ////////////////////////////////////////////////////////////////////////////////
146 // AshFocusRules, private:
148 aura::Window* AshFocusRules::GetTopmostWindowToActivateForContainerIndex(
149 int index,
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);
159 return window;
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();
168 ++i) {
169 WindowState* window_state = GetWindowState(*i);
170 if (*i != ignore &&
171 window_state->CanActivate() &&
172 !window_state->IsMinimized())
173 return *i;
175 return NULL;
178 } // namespace wm
179 } // namespace ash