| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/aura/focus_manager.h" |
| |
| #include "ui/aura/client/activation_client.h" |
| #include "ui/aura/client/focus_change_observer.h" |
| #include "ui/aura/root_window.h" |
| #include "ui/aura/window_delegate.h" |
| |
| namespace aura { |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // FocusManager, public: |
| |
| FocusManager::FocusManager() : focused_window_(NULL) { |
| } |
| |
| FocusManager::~FocusManager() { |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // FocusManager, client::FocusClient implementation: |
| |
| void FocusManager::AddObserver(client::FocusChangeObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void FocusManager::RemoveObserver(client::FocusChangeObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| void FocusManager::FocusWindow(Window* focused_window) { |
| if (focused_window == focused_window_) |
| return; |
| if (focused_window && !focused_window->CanFocus()) |
| return; |
| // The NULL-check of |focused_window| is essential here before asking the |
| // activation client, since it is valid to clear the focus by calling |
| // SetFocusedWindow() to NULL. |
| |
| if (focused_window) { |
| RootWindow* root = focused_window->GetRootWindow(); |
| DCHECK(root); |
| if (client::GetActivationClient(root) && |
| !client::GetActivationClient(root)->OnWillFocusWindow( |
| focused_window, NULL)) { |
| return; |
| } |
| } |
| |
| Window* old_focused_window = focused_window_; |
| focused_window_ = focused_window; |
| |
| FOR_EACH_OBSERVER(client::FocusChangeObserver, observers_, |
| OnWindowFocused(focused_window, old_focused_window)); |
| client::FocusChangeObserver* observer = |
| client::GetFocusChangeObserver(old_focused_window); |
| if (observer) |
| observer->OnWindowFocused(focused_window_, old_focused_window); |
| observer = client::GetFocusChangeObserver(focused_window_); |
| if (observer) |
| observer->OnWindowFocused(focused_window_, old_focused_window); |
| } |
| |
| void FocusManager::ResetFocusWithinActiveWindow(Window* window) { |
| FocusWindow(window); |
| } |
| |
| Window* FocusManager::GetFocusedWindow() { |
| return focused_window_; |
| } |
| |
| void FocusManager::OnWindowHiddenInRootWindow( |
| aura::Window* window, |
| aura::RootWindow* root_window, |
| bool destroyed) { |
| Window* focused_window = |
| client::GetFocusClient(root_window)->GetFocusedWindow(); |
| if (window->Contains(focused_window)) { |
| Window* focus_to = window->transient_parent(); |
| if (focus_to) { |
| // Has to be removed from the transient parent before focusing, |
| // otherwise |window| will be focused again. |
| if (destroyed) |
| focus_to->RemoveTransientChild(window); |
| } else { |
| // If the invisible view has no visible transient window, focus to the |
| // topmost visible parent window. |
| focus_to = window->parent(); |
| } |
| if (focus_to && |
| (!focus_to->IsVisible() || |
| !focus_to->CanFocus() || |
| (client::GetActivationClient(root_window) && |
| !client::GetActivationClient(root_window)->OnWillFocusWindow( |
| focus_to, NULL)))) { |
| focus_to = NULL; |
| } |
| client::GetFocusClient(root_window)->FocusWindow(focus_to); |
| } |
| } |
| |
| } // namespace aura |