focus_controller.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/focus_controller.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/auto_reset.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/activation_change_observer.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/aura_constants.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/capture_client.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/focus_change_observer.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/env.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/window_tracker.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/focus_rules.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace wm { 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// When a modal window is activated, we bring its entire transient parent chain 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to the front. This function must be called before the modal transient is 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// stacked at the top to ensure correct stacking order. 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackTransientParentsBelowModalWindow(aura::Window* window) { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_WINDOW) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) aura::Window* transient_parent = wm::GetTransientParent(window); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (transient_parent) { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) transient_parent->parent()->StackChildAtTop(transient_parent); 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) transient_parent = wm::GetTransientParent(transient_parent); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Stack's |window|'s layer above |relative_to|'s layer. 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackWindowLayerAbove(aura::Window* window, aura::Window* relative_to) { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Stack |window| above the last transient child of |relative_to| that shares 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the same parent. 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const aura::Window::Windows& window_transients( 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetTransientChildren(relative_to)); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (aura::Window::Windows::const_iterator i = window_transients.begin(); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i != window_transients.end(); ++i) { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* transient = *i; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (transient->parent() == relative_to->parent()) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) relative_to = transient; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window != relative_to) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window->layer()->parent()->StackAbove(window->layer(), 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) relative_to->layer()); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FocusController, public: 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FocusController::FocusController(FocusRules* rules) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : active_window_(NULL), 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focused_window_(NULL), 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) updating_focus_(false), 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) updating_activation_(false), 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rules_(rules), 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) observer_manager_(this) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(rules); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FocusController::~FocusController() { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FocusController, aura::client::ActivationClient implementation: 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::AddObserver( 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::ActivationChangeObserver* observer) { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activation_observers_.AddObserver(observer); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::RemoveObserver( 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::ActivationChangeObserver* observer) { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activation_observers_.RemoveObserver(observer); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::ActivateWindow(aura::Window* window) { 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FocusWindow(window); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::DeactivateWindow(aura::Window* window) { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FocusWindow(rules_->GetNextActivatableWindow(window)); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)aura::Window* FocusController::GetActiveWindow() { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return active_window_; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)aura::Window* FocusController::GetActivatableWindow(aura::Window* window) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rules_->GetActivatableWindow(window); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)aura::Window* FocusController::GetToplevelWindow(aura::Window* window) { 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rules_->GetToplevelWindow(window); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FocusController::OnWillFocusWindow(aura::Window* window, 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::Event* event) { 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FocusController::CanActivateWindow(aura::Window* window) const { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rules_->CanActivateWindow(window); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FocusController, aura::client::FocusClient implementation: 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::AddObserver( 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::FocusChangeObserver* observer) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focus_observers_.AddObserver(observer); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::RemoveObserver( 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::FocusChangeObserver* observer) { 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focus_observers_.RemoveObserver(observer); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::FocusWindow(aura::Window* window) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window && 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (window->Contains(focused_window_) || window->Contains(active_window_))) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // We should not be messing with the focus if the window has capture, unless 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // no has focus. 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (window && (aura::client::GetCaptureWindow(window) == window) && 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) focused_window_) { 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Focusing a window also activates its containing activatable window. Note 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that the rules could redirect activation activation and/or focus. 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* focusable = rules_->GetFocusableWindow(window); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* activatable = 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focusable ? rules_->GetActivatableWindow(focusable) : NULL; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need valid focusable/activatable windows in the event we're not clearing 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // focus. "Clearing focus" is inferred by whether or not |window| passed to 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // this function is non-NULL. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window && (!focusable || !activatable)) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK((focusable && activatable) || !window); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Activation change observers may change the focused window. If this happens 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we must not adjust the focus below since this will clobber that change. 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* last_focused_window = focused_window_; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!updating_activation_) 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetActiveWindow(window, activatable); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the window's ActivationChangeObserver shifted focus to a valid window, 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we don't want to focus the window we thought would be focused by default. 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool activation_changed_focus = last_focused_window != focused_window_; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) { 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (active_window_ && focusable) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(active_window_->Contains(focusable)); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFocusedWindow(focusable); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) { 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(window); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!active_window_) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!active_window_->Contains(window)) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFocusedWindow(window); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)aura::Window* FocusController::GetFocusedWindow() { 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return focused_window_; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FocusController, ui::EventHandler implementation: 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnKeyEvent(ui::KeyEvent* event) { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnMouseEvent(ui::MouseEvent* event) { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event->type() == ui::ET_MOUSE_PRESSED) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target())); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnScrollEvent(ui::ScrollEvent* event) { 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnTouchEvent(ui::TouchEvent* event) { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnGestureEvent(ui::GestureEvent* event) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event->type() == ui::ET_GESTURE_BEGIN && 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->details().touch_points() == 1) { 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target())); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FocusController, aura::WindowObserver implementation: 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnWindowVisibilityChanged(aura::Window* window, 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool visible) { 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!visible) { 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WindowLostFocusFromDispositionChange(window, window->parent()); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Despite the focus change, we need to keep the window being hidden 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stacked above the new window so it stays open on top as it animates away. 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* next_window = GetActiveWindow(); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (next_window && next_window->parent() == window->parent()) 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StackWindowLayerAbove(window, next_window); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnWindowDestroying(aura::Window* window) { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WindowLostFocusFromDispositionChange(window, window->parent()); 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnWindowHierarchyChanging( 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HierarchyChangeParams& params) { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (params.receiver == active_window_ && 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.target->Contains(params.receiver) && (!params.new_parent || 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::GetFocusClient(params.new_parent) != 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::GetFocusClient(params.receiver))) { 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::OnWindowHierarchyChanged( 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HierarchyChangeParams& params) { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (params.receiver == focused_window_ && 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.target->Contains(params.receiver) && (!params.new_parent || 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::GetFocusClient(params.new_parent) != 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::GetFocusClient(params.receiver))) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FocusController, private: 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::SetFocusedWindow(aura::Window* window) { 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (updating_focus_ || window == focused_window_) 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(rules_->CanFocusWindow(window)); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(window, rules_->GetFocusableWindow(window)); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<bool> updating_focus(&updating_focus_, true); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* lost_focus = focused_window_; 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Allow for the window losing focus to be deleted during dispatch. If it is 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // deleted pass NULL to observers instead of a deleted window. 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::WindowTracker window_tracker; 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (lost_focus) 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_tracker.Add(lost_focus); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (focused_window_ && observer_manager_.IsObserving(focused_window_) && 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focused_window_ != active_window_) { 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer_manager_.Remove(focused_window_); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focused_window_ = window; 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (focused_window_ && !observer_manager_.IsObserving(focused_window_)) 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer_manager_.Add(focused_window_); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(aura::client::FocusChangeObserver, 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focus_observers_, 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnWindowFocused(focused_window_, 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_tracker.Contains(lost_focus) ? 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) lost_focus : NULL)); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (window_tracker.Contains(lost_focus)) { 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::client::FocusChangeObserver* observer = 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::client::GetFocusChangeObserver(lost_focus); 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (observer) 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer->OnWindowFocused(focused_window_, lost_focus); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::client::FocusChangeObserver* observer = 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::client::GetFocusChangeObserver(focused_window_); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (observer) { 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer->OnWindowFocused( 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) focused_window_, 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_tracker.Contains(lost_focus) ? lost_focus : NULL); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FocusController::SetActiveWindow(aura::Window* requested_window, 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) aura::Window* window) { 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (updating_activation_) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (window == active_window_) { 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (requested_window) { 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) activation_observers_, 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnAttemptToReactivateWindow(requested_window, 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) active_window_)); 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(rules_->CanActivateWindow(window)); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(window, rules_->GetActivatableWindow(window)); 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<bool> updating_activation(&updating_activation_, true); 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* lost_activation = active_window_; 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Allow for the window losing activation to be deleted during dispatch. If 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // it is deleted pass NULL to observers instead of a deleted window. 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::WindowTracker window_tracker; 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (lost_activation) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_tracker.Add(lost_activation); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (active_window_ && observer_manager_.IsObserving(active_window_) && 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) focused_window_ != active_window_) { 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer_manager_.Remove(active_window_); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) active_window_ = window; 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (active_window_ && !observer_manager_.IsObserving(active_window_)) 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer_manager_.Add(active_window_); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (active_window_) { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StackTransientParentsBelowModalWindow(active_window_); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) active_window_->parent()->StackChildAtTop(active_window_); 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::client::ActivationChangeObserver* observer = NULL; 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (window_tracker.Contains(lost_activation)) { 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer = aura::client::GetActivationChangeObserver(lost_activation); 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (observer) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer->OnWindowActivated(active_window_, lost_activation); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) observer = aura::client::GetActivationChangeObserver(active_window_); 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (observer) { 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) observer->OnWindowActivated( 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) active_window_, 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_tracker.Contains(lost_activation) ? lost_activation : NULL); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activation_observers_, 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnWindowActivated(active_window_, 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_tracker.Contains(lost_activation) ? 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) lost_activation : NULL)); 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::WindowLostFocusFromDispositionChange( 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* window, 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* next) { 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A window's modality state will interfere with focus restoration during its 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // destruction. 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window->ClearProperty(aura::client::kModalKey); 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(beng): See if this function can be replaced by a call to 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // FocusWindow(). 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Activation adjustments are handled first in the event of a disposition 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // changed. If an activation change is necessary, focus is reset as part of 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that process so there's no point in updating focus independently. 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (window == active_window_) { 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* next_activatable = rules_->GetNextActivatableWindow(window); 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetActiveWindow(NULL, next_activatable); 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!(active_window_ && active_window_->Contains(focused_window_))) 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetFocusedWindow(next_activatable); 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (window->Contains(focused_window_)) { 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Active window isn't changing, but focused window might be. 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetFocusedWindow(rules_->GetFocusableWindow(next)); 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusController::WindowFocusedFromInputEvent(aura::Window* window) { 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Only focus |window| if it or any of its parents can be focused. Otherwise 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // FocusWindow() will focus the topmost window, which may not be the 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // currently focused one. 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rules_->CanFocusWindow(GetToplevelWindow(window))) 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FocusWindow(window); 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace wm 378