• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ash/wm/ash_focus_rules.h"
6 
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"
11 
12 namespace ash {
13 namespace wm {
14 namespace {
15 
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,
27 
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, };
35 
BelongsToContainerWithEqualOrGreaterId(const aura::Window * window,int container_id)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;
41   }
42   return false;
43 }
44 
45 }  // namespace
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 // AshFocusRules, public:
49 
AshFocusRules()50 AshFocusRules::AshFocusRules() {
51 }
52 
~AshFocusRules()53 AshFocusRules::~AshFocusRules() {
54 }
55 
56 ////////////////////////////////////////////////////////////////////////////////
57 // AshFocusRules, ::wm::FocusRules:
58 
SupportsChildActivation(aura::Window * window) const59 bool AshFocusRules::SupportsChildActivation(aura::Window* window) const {
60   if (window->id() == kShellWindowId_DefaultContainer)
61     return true;
62 
63   for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) {
64     if (window->id() == kWindowContainerIds[i])
65       return true;
66   }
67   return false;
68 }
69 
IsWindowConsideredVisibleForActivation(aura::Window * window) const70 bool AshFocusRules::IsWindowConsideredVisibleForActivation(
71     aura::Window* window) const {
72   if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window))
73     return true;
74 
75   // Minimized windows are hidden in their minimized state, but they can always
76   // be activated.
77   if (wm::GetWindowState(window)->IsMinimized())
78     return true;
79 
80   return window->TargetVisibility() &&
81          (window->parent()->id() == kShellWindowId_DefaultContainer ||
82           window->parent()->id() == kShellWindowId_LockScreenContainer);
83 }
84 
CanActivateWindow(aura::Window * window) const85 bool AshFocusRules::CanActivateWindow(aura::Window* window) const {
86   // Clearing activation is always permissible.
87   if (!window)
88     return true;
89 
90   if (!BaseFocusRules::CanActivateWindow(window))
91     return false;
92 
93   if (Shell::GetInstance()->IsSystemModalWindowOpen()) {
94     return BelongsToContainerWithEqualOrGreaterId(
95         window, kShellWindowId_SystemModalContainer);
96   }
97 
98   return true;
99 }
100 
GetNextActivatableWindow(aura::Window * ignore) const101 aura::Window* AshFocusRules::GetNextActivatableWindow(
102     aura::Window* ignore) const {
103   DCHECK(ignore);
104 
105   int starting_container_index = 0;
106   // If the container of the window losing focus is in the list, start from that
107   // container.
108   aura::Window* root = ignore->GetRootWindow();
109   if (!root)
110     root = Shell::GetTargetRootWindow();
111   int container_count = static_cast<int>(arraysize(kWindowContainerIds));
112   for (int i = 0; ignore && i < container_count; i++) {
113     aura::Window* container = Shell::GetContainer(root, kWindowContainerIds[i]);
114     if (container && container->Contains(ignore)) {
115       starting_container_index = i;
116       break;
117     }
118   }
119 
120   // Look for windows to focus in |ignore|'s container. If none are found, we
121   // look in all the containers in front of |ignore|'s container, then all
122   // behind.
123   aura::Window* window = NULL;
124   for (int i = starting_container_index; !window && i < container_count; i++)
125     window = GetTopmostWindowToActivateForContainerIndex(i, ignore);
126   if (!window && starting_container_index > 0) {
127     for (int i = starting_container_index - 1; !window && i >= 0; i--)
128       window = GetTopmostWindowToActivateForContainerIndex(i, ignore);
129   }
130   return window;
131 }
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 // AshFocusRules, private:
135 
GetTopmostWindowToActivateForContainerIndex(int index,aura::Window * ignore) const136 aura::Window* AshFocusRules::GetTopmostWindowToActivateForContainerIndex(
137     int index,
138     aura::Window* ignore) const {
139   aura::Window* window = NULL;
140   aura::Window* root = ignore ? ignore->GetRootWindow() : NULL;
141   aura::Window::Windows containers = Shell::GetContainersFromAllRootWindows(
142       kWindowContainerIds[index], root);
143   for (aura::Window::Windows::const_iterator iter = containers.begin();
144         iter != containers.end() && !window; ++iter) {
145     window = GetTopmostWindowToActivateInContainer((*iter), ignore);
146   }
147   return window;
148 }
149 
GetTopmostWindowToActivateInContainer(aura::Window * container,aura::Window * ignore) const150 aura::Window* AshFocusRules::GetTopmostWindowToActivateInContainer(
151     aura::Window* container,
152     aura::Window* ignore) const {
153   for (aura::Window::Windows::const_reverse_iterator i =
154            container->children().rbegin();
155        i != container->children().rend();
156        ++i) {
157     WindowState* window_state = GetWindowState(*i);
158     if (*i != ignore &&
159         window_state->CanActivate() &&
160         !window_state->IsMinimized())
161       return *i;
162   }
163   return NULL;
164 }
165 
166 }  // namespace wm
167 }  // namespace ash
168