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