Enable compilation of angle_end2end_tests on Linux
[chromium-blink-merge.git] / ash / wm / ash_focus_rules.cc
blob58a71ebdd592cfc3a0df65fdeea706128f0ba17a
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/session/session_state_delegate.h"
8 #include "ash/shell.h"
9 #include "ash/shell_delegate.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/wm/mru_window_tracker.h"
12 #include "ash/wm/window_state.h"
13 #include "ui/aura/window.h"
15 namespace ash {
16 namespace wm {
17 namespace {
19 // These are the list of container ids of containers which may contain windows
20 // that need to be activated in the order that they should be activated.
21 const int kWindowContainerIds[] = {
22 kShellWindowId_OverlayContainer,
23 kShellWindowId_LockSystemModalContainer,
24 kShellWindowId_SettingBubbleContainer,
25 kShellWindowId_LockScreenContainer,
26 kShellWindowId_SystemModalContainer,
27 kShellWindowId_AlwaysOnTopContainer,
28 kShellWindowId_AppListContainer,
29 kShellWindowId_DefaultContainer,
31 // Docked, panel, launcher and status are intentionally checked after other
32 // containers even though these layers are higher. The user expects their
33 // windows to be focused before these elements.
34 kShellWindowId_DockedContainer,
35 kShellWindowId_PanelContainer,
36 kShellWindowId_ShelfContainer,
37 kShellWindowId_StatusContainer, };
39 bool BelongsToContainerWithEqualOrGreaterId(const aura::Window* window,
40 int container_id) {
41 for (; window; window = window->parent()) {
42 if (window->id() >= container_id)
43 return true;
45 return false;
48 } // namespace
50 ////////////////////////////////////////////////////////////////////////////////
51 // AshFocusRules, public:
53 AshFocusRules::AshFocusRules() {
56 AshFocusRules::~AshFocusRules() {
59 bool AshFocusRules::IsWindowConsideredActivatable(aura::Window* window) const {
60 // Only toplevel windows can be activated.
61 if (!IsToplevelWindow(window))
62 return false;
64 // The window must be visible.
65 if (!IsWindowConsideredVisibleForActivation(window))
66 return false;
68 return true;
71 ////////////////////////////////////////////////////////////////////////////////
72 // AshFocusRules, ::wm::FocusRules:
74 bool AshFocusRules::SupportsChildActivation(aura::Window* window) const {
75 if (window->id() == kShellWindowId_DefaultContainer)
76 return true;
78 for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) {
79 if (window->id() == kWindowContainerIds[i])
80 return true;
82 return false;
85 bool AshFocusRules::IsWindowConsideredVisibleForActivation(
86 aura::Window* window) const {
87 // If the |window| doesn't belong to the current active user and also doesn't
88 // show for the current active user, then it should not be activated.
89 SessionStateDelegate* delegate =
90 Shell::GetInstance()->session_state_delegate();
91 if (delegate->NumberOfLoggedInUsers() > 1) {
92 content::BrowserContext* active_browser_context =
93 Shell::GetInstance()->delegate()->GetActiveBrowserContext();
94 content::BrowserContext* owner_browser_context =
95 delegate->GetBrowserContextForWindow(window);
96 content::BrowserContext* shown_browser_context =
97 delegate->GetUserPresentingBrowserContextForWindow(window);
99 if (owner_browser_context && active_browser_context &&
100 owner_browser_context != active_browser_context &&
101 shown_browser_context != active_browser_context) {
102 return false;
106 if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window))
107 return true;
109 // Minimized windows are hidden in their minimized state, but they can always
110 // be activated.
111 if (wm::GetWindowState(window)->IsMinimized())
112 return true;
114 return window->TargetVisibility() &&
115 (window->parent()->id() == kShellWindowId_DefaultContainer ||
116 window->parent()->id() == kShellWindowId_LockScreenContainer);
119 bool AshFocusRules::CanActivateWindow(aura::Window* window) const {
120 // Clearing activation is always permissible.
121 if (!window)
122 return true;
124 if (!BaseFocusRules::CanActivateWindow(window))
125 return false;
127 if (Shell::GetInstance()->IsSystemModalWindowOpen()) {
128 return BelongsToContainerWithEqualOrGreaterId(
129 window, kShellWindowId_SystemModalContainer);
132 return true;
135 aura::Window* AshFocusRules::GetNextActivatableWindow(
136 aura::Window* ignore) const {
137 DCHECK(ignore);
139 // Start from the container of the most-recently-used window. If the list of
140 // MRU windows is empty, then start from the container of the window that just
141 // lost focus |ignore|.
142 ash::MruWindowTracker* mru = ash::Shell::GetInstance()->mru_window_tracker();
143 std::vector<aura::Window*> windows = mru->BuildMruWindowList();
144 aura::Window* starting_window = windows.empty() ? ignore : windows[0];
146 // Look for windows to focus in |starting_window|'s container. If none are
147 // found, we look in all the containers in front of |starting_window|'s
148 // container, then all behind.
149 int starting_container_index = 0;
150 aura::Window* root = starting_window->GetRootWindow();
151 if (!root)
152 root = Shell::GetTargetRootWindow();
153 int container_count = static_cast<int>(arraysize(kWindowContainerIds));
154 for (int i = 0; i < container_count; i++) {
155 aura::Window* container = Shell::GetContainer(root, kWindowContainerIds[i]);
156 if (container && container->Contains(starting_window)) {
157 starting_container_index = i;
158 break;
162 aura::Window* window = nullptr;
163 for (int i = starting_container_index; !window && i < container_count; i++)
164 window = GetTopmostWindowToActivateForContainerIndex(i, ignore);
165 if (!window && starting_container_index > 0) {
166 for (int i = starting_container_index - 1; !window && i >= 0; i--)
167 window = GetTopmostWindowToActivateForContainerIndex(i, ignore);
169 return window;
172 ////////////////////////////////////////////////////////////////////////////////
173 // AshFocusRules, private:
175 aura::Window* AshFocusRules::GetTopmostWindowToActivateForContainerIndex(
176 int index,
177 aura::Window* ignore) const {
178 aura::Window* window = NULL;
179 aura::Window* root = ignore ? ignore->GetRootWindow() : NULL;
180 aura::Window::Windows containers = Shell::GetContainersFromAllRootWindows(
181 kWindowContainerIds[index], root);
182 for (aura::Window::Windows::const_iterator iter = containers.begin();
183 iter != containers.end() && !window; ++iter) {
184 window = GetTopmostWindowToActivateInContainer((*iter), ignore);
186 return window;
189 aura::Window* AshFocusRules::GetTopmostWindowToActivateInContainer(
190 aura::Window* container,
191 aura::Window* ignore) const {
192 for (aura::Window::Windows::const_reverse_iterator i =
193 container->children().rbegin();
194 i != container->children().rend();
195 ++i) {
196 WindowState* window_state = GetWindowState(*i);
197 if (*i != ignore &&
198 window_state->CanActivate() &&
199 !window_state->IsMinimized())
200 return *i;
202 return NULL;
205 } // namespace wm
206 } // namespace ash