Move action_runner.py out of actions folder prior to moving actions to internal.
[chromium-blink-merge.git] / ash / wm / ash_focus_rules.cc
blob66fe0b22b1af60d8899462307f8b8c7d51f10508
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/mru_window_tracker.h"
10 #include "ash/wm/window_state.h"
11 #include "ui/aura/window.h"
13 namespace ash {
14 namespace wm {
15 namespace {
17 // These are the list of container ids of containers which may contain windows
18 // that need to be activated in the order that they should be activated.
19 const int kWindowContainerIds[] = {
20 kShellWindowId_OverlayContainer,
21 kShellWindowId_LockSystemModalContainer,
22 kShellWindowId_SettingBubbleContainer,
23 kShellWindowId_LockScreenContainer,
24 kShellWindowId_SystemModalContainer,
25 kShellWindowId_AlwaysOnTopContainer,
26 kShellWindowId_AppListContainer,
27 kShellWindowId_DefaultContainer,
29 // Docked, panel, launcher and status are intentionally checked after other
30 // containers even though these layers are higher. The user expects their
31 // windows to be focused before these elements.
32 kShellWindowId_DockedContainer,
33 kShellWindowId_PanelContainer,
34 kShellWindowId_ShelfContainer,
35 kShellWindowId_StatusContainer, };
37 bool BelongsToContainerWithEqualOrGreaterId(const aura::Window* window,
38 int container_id) {
39 for (; window; window = window->parent()) {
40 if (window->id() >= container_id)
41 return true;
43 return false;
46 } // namespace
48 ////////////////////////////////////////////////////////////////////////////////
49 // AshFocusRules, public:
51 AshFocusRules::AshFocusRules() : is_shutting_down_(false) {
52 ash::Shell::GetInstance()->AddShellObserver(this);
55 AshFocusRules::~AshFocusRules() {
56 ash::Shell::GetInstance()->RemoveShellObserver(this);
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 (BaseFocusRules::IsWindowConsideredVisibleForActivation(window))
88 return true;
90 // Minimized windows are hidden in their minimized state, but they can always
91 // be activated.
92 if (wm::GetWindowState(window)->IsMinimized())
93 return true;
95 return window->TargetVisibility() &&
96 (window->parent()->id() == kShellWindowId_DefaultContainer ||
97 window->parent()->id() == kShellWindowId_LockScreenContainer);
100 bool AshFocusRules::CanActivateWindow(aura::Window* window) const {
101 // Clearing activation is always permissible.
102 if (!window)
103 return true;
105 if (!BaseFocusRules::CanActivateWindow(window))
106 return false;
108 if (Shell::GetInstance()->IsSystemModalWindowOpen()) {
109 return BelongsToContainerWithEqualOrGreaterId(
110 window, kShellWindowId_SystemModalContainer);
113 return true;
116 aura::Window* AshFocusRules::GetNextActivatableWindow(
117 aura::Window* ignore) const {
118 if (is_shutting_down_)
119 return nullptr;
121 DCHECK(ignore);
123 // Start from the container of the most-recently-used window. If the list of
124 // MRU windows is empty, then start from the container of the window that just
125 // lost focus |ignore|.
126 ash::MruWindowTracker* mru = ash::Shell::GetInstance()->mru_window_tracker();
127 std::vector<aura::Window*> windows = mru->BuildMruWindowList();
128 aura::Window* starting_window = windows.empty() ? ignore : windows[0];
130 // Look for windows to focus in |starting_window|'s container. If none are
131 // found, we look in all the containers in front of |starting_window|'s
132 // container, then all behind.
133 int starting_container_index = 0;
134 aura::Window* root = starting_window->GetRootWindow();
135 if (!root)
136 root = Shell::GetTargetRootWindow();
137 int container_count = static_cast<int>(arraysize(kWindowContainerIds));
138 for (int i = 0; i < container_count; i++) {
139 aura::Window* container = Shell::GetContainer(root, kWindowContainerIds[i]);
140 if (container && container->Contains(starting_window)) {
141 starting_container_index = i;
142 break;
146 aura::Window* window = nullptr;
147 for (int i = starting_container_index; !window && i < container_count; i++)
148 window = GetTopmostWindowToActivateForContainerIndex(i, ignore);
149 if (!window && starting_container_index > 0) {
150 for (int i = starting_container_index - 1; !window && i >= 0; i--)
151 window = GetTopmostWindowToActivateForContainerIndex(i, ignore);
153 return window;
156 ////////////////////////////////////////////////////////////////////////////////
157 // AshFocusRules, private:
159 aura::Window* AshFocusRules::GetTopmostWindowToActivateForContainerIndex(
160 int index,
161 aura::Window* ignore) const {
162 aura::Window* window = NULL;
163 aura::Window* root = ignore ? ignore->GetRootWindow() : NULL;
164 aura::Window::Windows containers = Shell::GetContainersFromAllRootWindows(
165 kWindowContainerIds[index], root);
166 for (aura::Window::Windows::const_iterator iter = containers.begin();
167 iter != containers.end() && !window; ++iter) {
168 window = GetTopmostWindowToActivateInContainer((*iter), ignore);
170 return window;
173 aura::Window* AshFocusRules::GetTopmostWindowToActivateInContainer(
174 aura::Window* container,
175 aura::Window* ignore) const {
176 for (aura::Window::Windows::const_reverse_iterator i =
177 container->children().rbegin();
178 i != container->children().rend();
179 ++i) {
180 WindowState* window_state = GetWindowState(*i);
181 if (*i != ignore &&
182 window_state->CanActivate() &&
183 !window_state->IsMinimized())
184 return *i;
186 return NULL;
189 void AshFocusRules::OnAppTerminating() {
190 is_shutting_down_ = true;
193 } // namespace wm
194 } // namespace ash