Chromium Code Reviews| Index: ui/aura_shell/activation_controller.cc |
| =================================================================== |
| --- ui/aura_shell/activation_controller.cc (revision 0) |
| +++ ui/aura_shell/activation_controller.cc (revision 0) |
| @@ -0,0 +1,187 @@ |
| +// Copyright (c) 2011 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_shell/activation_controller.h" |
| + |
| +#include "base/auto_reset.h" |
| +#include "ui/aura/client/activation_delegate.h" |
| +#include "ui/aura/client/aura_constants.h" |
| +#include "ui/aura/root_window.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/aura/window_delegate.h" |
| +#include "ui/aura_shell/shell.h" |
| +#include "ui/aura_shell/shell_window_ids.h" |
| +#include "ui/aura_shell/window_util.h" |
| + |
| +namespace aura_shell { |
| +namespace internal { |
| +namespace { |
| + |
| +aura::Window* GetContainer(int id) { |
| + return Shell::GetInstance()->GetContainer(id); |
| +} |
| + |
| +aura::ActivationDelegate* GetActivationDelegate(aura::Window* window) { |
| + return reinterpret_cast<aura::ActivationDelegate*>( |
| + window->GetProperty(aura::kActivationDelegateKey)); |
| +} |
| + |
| +// Returns true if children of |window| can be activated. |
| +bool SupportsChildActivation(aura::Window* window) { |
| + return window->id() == kShellWindowId_DefaultContainer || |
| + window->id() == kShellWindowId_AlwaysOnTopContainer || |
| + window->id() == kShellWindowId_ModalContainer || |
| + window->id() == kShellWindowId_LockModalContainer; |
| +} |
| + |
| +// Returns true if |window| can be activated or deactivated. |
| +// A window manager typically defines some notion of "top level window" that |
| +// supports activation/deactivation. |
| +bool CanActivateWindow(aura::Window* window) { |
| + return window && |
| + window->IsVisible() && |
| + (!GetActivationDelegate(window) || |
| + GetActivationDelegate(window)->ShouldActivate(NULL)) && |
| + SupportsChildActivation(window->parent()); |
| +} |
| + |
| +} // namespace |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ActivationController, public: |
| + |
| +ActivationController::ActivationController() |
| + : updating_activation_(false), |
| + default_container_for_test_(NULL) { |
| + aura::RootWindow::GetInstance()->SetProperty( |
| + aura::kRootWindowActivationClient, this); |
| + aura::RootWindow::GetInstance()->AddRootWindowObserver(this); |
| +} |
| + |
| +ActivationController::~ActivationController() { |
| + aura::RootWindow::GetInstance()->RemoveRootWindowObserver(this); |
| +} |
| + |
| +// static |
| +aura::Window* ActivationController::GetActivatableWindow(aura::Window* window) { |
| + aura::Window* parent = window->parent(); |
| + aura::Window* child = window; |
| + while (parent) { |
| + if (SupportsChildActivation(parent)) |
| + return child; |
| + // If |child| isn't activatable, but has transient parent, trace |
| + // that path instead. |
| + if (child->transient_parent()) |
| + return GetActivatableWindow(child->transient_parent()); |
| + parent = parent->parent(); |
| + child = child->parent(); |
| + } |
| + return NULL; |
| +} |
| + |
| +// static |
| +bool ActivationController::CanFocusWindow(aura::Window* window) { |
| + return CanActivateWindow(GetActivatableWindow(window)); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// StackingController, aura::ActivationClient implementation: |
| + |
| +void ActivationController::ActivateWindow(aura::Window* window) { |
| + AutoReset<bool> in_activate_window(&updating_activation_, true); |
| + if (!window) |
| + return; |
| + // Nothing may actually have changed. |
| + aura::Window* old_active = GetActiveWindow(); |
| + if (old_active == window) |
| + return; |
| + // The stacking client may impose rules on what window configurations can be |
| + // activated or deactivated. |
| + if (!CanActivateWindow(window)) |
|
sky
2011/12/09 23:11:23
If we end up here because of focus change, wouldn'
Ben Goodger (Google)
2011/12/12 18:01:16
I am not quite sure what you mean by this. I've ad
sky
2011/12/12 18:06:11
Say you had a window that didn't want to become ac
|
| + return; |
| + |
| + if (!window->Contains(window->GetFocusManager()->GetFocusedWindow())) |
| + window->GetFocusManager()->SetFocusedWindow(window); |
| + aura::RootWindow::GetInstance()->SetProperty(aura::kRootWindowActiveWindow, |
| + window); |
| + // Invoke OnLostActive after we've changed the active window. That way if the |
| + // delegate queries for active state it doesn't think the window is still |
| + // active. |
| + if (old_active && GetActivationDelegate(old_active)) |
| + GetActivationDelegate(old_active)->OnLostActive(); |
| + if (window) { |
| + window->parent()->StackChildAtTop(window); |
| + if (GetActivationDelegate(window)) |
| + GetActivationDelegate(window)->OnActivated(); |
| + } |
| +} |
| + |
| +void ActivationController::DeactivateWindow(aura::Window* window) { |
| + if (window) |
| + ActivateNextWindow(window); |
| +} |
| + |
| +aura::Window* ActivationController::GetActiveWindow() { |
| + return reinterpret_cast<aura::Window*>( |
| + aura::RootWindow::GetInstance()->GetProperty( |
| + aura::kRootWindowActiveWindow)); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ActivationController, aura::WindowObserver implementation: |
| + |
| +void ActivationController::OnWindowVisibilityChanged(aura::Window* window, |
| + bool visible) { |
| + if (!visible) |
| + ActivateNextWindow(window); |
| +} |
| + |
| +void ActivationController::OnWindowDestroyed(aura::Window* window) { |
| + if (IsActiveWindow(window)) { |
| + // Clear the property before activating something else, since |
| + // ActivateWindow() will attempt to notify the window stored in this value |
| + // otherwise. |
| + aura::RootWindow::GetInstance()->SetProperty(aura::kRootWindowActiveWindow, |
| + NULL); |
| + ActivateWindow(GetTopmostWindowToActivate(window)); |
| + } |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ActivationController, aura::RootWindowObserver implementation: |
| + |
| +void ActivationController::OnWindowInitialized(aura::Window* window) { |
| + window->AddObserver(this); |
|
sky
2011/12/09 23:11:23
It doesn't seem like you ever remove this. Maybe O
|
| +} |
| + |
| +void ActivationController::OnWindowFocused(aura::Window* window) { |
| + if (!updating_activation_) |
| + ActivateWindow(GetActivatableWindow(window)); |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// ActivationController, private: |
| + |
| +void ActivationController::ActivateNextWindow(aura::Window* window) { |
| + if (IsActiveWindow(window)) |
| + ActivateWindow(GetTopmostWindowToActivate(window)); |
| +} |
| + |
| +aura::Window* ActivationController::GetTopmostWindowToActivate( |
| + aura::Window* ignore) const { |
| + const aura::Window* container = |
| + default_container_for_test_ ? default_container_for_test_ : |
| + GetContainer(kShellWindowId_DefaultContainer); |
| + for (aura::Window::Windows::const_reverse_iterator i = |
| + container->children().rbegin(); |
| + i != container->children().rend(); |
| + ++i) { |
| + if (*i != ignore && CanActivateWindow(*i)) |
| + return *i; |
| + } |
| + return NULL; |
| +} |
| + |
| +} // namespace internal |
| +} // namespace aura_shell |
| Property changes on: ui\aura_shell\activation_controller.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |