12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/wm/ash_focus_rules.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell_window_ids.h" 968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_state.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ash { 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace wm { 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// These are the list of container ids of containers which may contain windows 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that need to be activated in the order that they should be activated. 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kWindowContainerIds[] = { 19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_OverlayContainer, 20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_LockSystemModalContainer, 21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_SettingBubbleContainer, 22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_LockScreenContainer, 23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_SystemModalContainer, 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_AlwaysOnTopContainer, 25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_AppListContainer, 26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_DefaultContainer, 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Docked, panel, launcher and status are intentionally checked after other 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // containers even though these layers are higher. The user expects their 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // windows to be focused before these elements. 31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_DockedContainer, 32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_PanelContainer, 33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_ShelfContainer, 34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kShellWindowId_StatusContainer, }; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BelongsToContainerWithEqualOrGreaterId(const aura::Window* window, 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int container_id) { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (; window; window = window->parent()) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window->id() >= container_id) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// AshFocusRules, public: 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AshFocusRules::AshFocusRules() { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AshFocusRules::~AshFocusRules() { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// AshFocusRules, ::wm::FocusRules: 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AshFocusRules::SupportsChildActivation(aura::Window* window) const { 60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (window->id() == kShellWindowId_DefaultContainer) 612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return true; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < arraysize(kWindowContainerIds); i++) { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window->id() == kWindowContainerIds[i]) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AshFocusRules::IsWindowConsideredVisibleForActivation( 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* window) const { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window)) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Minimized windows are hidden in their minimized state, but they can always 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // be activated. 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (wm::GetWindowState(window)->IsMinimized()) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return window->TargetVisibility() && 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch (window->parent()->id() == kShellWindowId_DefaultContainer || 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch window->parent()->id() == kShellWindowId_LockScreenContainer); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AshFocusRules::CanActivateWindow(aura::Window* window) const { 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clearing activation is always permissible. 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!window) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!BaseFocusRules::CanActivateWindow(window)) 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (Shell::GetInstance()->IsSystemModalWindowOpen()) { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BelongsToContainerWithEqualOrGreaterId( 95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch window, kShellWindowId_SystemModalContainer); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)aura::Window* AshFocusRules::GetNextActivatableWindow( 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* ignore) const { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(ignore); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int starting_container_index = 0; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the container of the window losing focus is in the list, start from that 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // container. 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::Window* root = ignore->GetRootWindow(); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!root) 110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) root = Shell::GetTargetRootWindow(); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int container_count = static_cast<int>(arraysize(kWindowContainerIds)); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; ignore && i < container_count; i++) { 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* container = Shell::GetContainer(root, kWindowContainerIds[i]); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (container && container->Contains(ignore)) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) starting_container_index = i; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Look for windows to focus in |ignore|'s container. If none are found, we 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // look in all the containers in front of |ignore|'s container, then all 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // behind. 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* window = NULL; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = starting_container_index; !window && i < container_count; i++) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window = GetTopmostWindowToActivateForContainerIndex(i, ignore); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!window && starting_container_index > 0) { 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = starting_container_index - 1; !window && i >= 0; i--) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window = GetTopmostWindowToActivateForContainerIndex(i, ignore); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return window; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// AshFocusRules, private: 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)aura::Window* AshFocusRules::GetTopmostWindowToActivateForContainerIndex( 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index, 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* ignore) const { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* window = NULL; 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::Window* root = ignore ? ignore->GetRootWindow() : NULL; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window::Windows containers = Shell::GetContainersFromAllRootWindows( 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kWindowContainerIds[index], root); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (aura::Window::Windows::const_iterator iter = containers.begin(); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != containers.end() && !window; ++iter) { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window = GetTopmostWindowToActivateInContainer((*iter), ignore); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return window; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)aura::Window* AshFocusRules::GetTopmostWindowToActivateInContainer( 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* container, 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* ignore) const { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (aura::Window::Windows::const_reverse_iterator i = 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) container->children().rbegin(); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i != container->children().rend(); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++i) { 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) WindowState* window_state = GetWindowState(*i); 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (*i != ignore && 15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) window_state->CanActivate() && 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) !window_state->IsMinimized()) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *i; 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace wm 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace ash 168