Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/aura_shell/activation_controller.h" | |
| 6 | |
| 7 #include "base/auto_reset.h" | |
| 8 #include "ui/aura/client/activation_delegate.h" | |
| 9 #include "ui/aura/client/aura_constants.h" | |
| 10 #include "ui/aura/root_window.h" | |
| 11 #include "ui/aura/window.h" | |
| 12 #include "ui/aura/window_delegate.h" | |
| 13 #include "ui/aura_shell/shell.h" | |
| 14 #include "ui/aura_shell/shell_window_ids.h" | |
| 15 #include "ui/aura_shell/window_util.h" | |
| 16 | |
| 17 namespace aura_shell { | |
| 18 namespace internal { | |
| 19 namespace { | |
| 20 | |
| 21 aura::Window* GetContainer(int id) { | |
| 22 return Shell::GetInstance()->GetContainer(id); | |
| 23 } | |
| 24 | |
| 25 aura::ActivationDelegate* GetActivationDelegate(aura::Window* window) { | |
| 26 return reinterpret_cast<aura::ActivationDelegate*>( | |
| 27 window->GetProperty(aura::kActivationDelegateKey)); | |
| 28 } | |
| 29 | |
| 30 // Returns true if children of |window| can be activated. | |
| 31 bool SupportsChildActivation(aura::Window* window) { | |
| 32 return window->id() == kShellWindowId_DefaultContainer || | |
| 33 window->id() == kShellWindowId_AlwaysOnTopContainer || | |
| 34 window->id() == kShellWindowId_ModalContainer || | |
| 35 window->id() == kShellWindowId_LockModalContainer; | |
| 36 } | |
| 37 | |
| 38 // Returns true if |window| can be activated or deactivated. | |
| 39 // A window manager typically defines some notion of "top level window" that | |
| 40 // supports activation/deactivation. | |
| 41 bool CanActivateWindow(aura::Window* window) { | |
| 42 return window && | |
| 43 window->IsVisible() && | |
| 44 (!GetActivationDelegate(window) || | |
| 45 GetActivationDelegate(window)->ShouldActivate(NULL)) && | |
| 46 SupportsChildActivation(window->parent()); | |
| 47 } | |
| 48 | |
| 49 } // namespace | |
| 50 | |
| 51 //////////////////////////////////////////////////////////////////////////////// | |
| 52 // ActivationController, public: | |
| 53 | |
| 54 ActivationController::ActivationController() | |
| 55 : updating_activation_(false), | |
| 56 default_container_for_test_(NULL) { | |
| 57 aura::RootWindow::GetInstance()->SetProperty( | |
| 58 aura::kRootWindowActivationClient, this); | |
| 59 aura::RootWindow::GetInstance()->AddRootWindowObserver(this); | |
| 60 } | |
| 61 | |
| 62 ActivationController::~ActivationController() { | |
| 63 aura::RootWindow::GetInstance()->RemoveRootWindowObserver(this); | |
| 64 } | |
| 65 | |
| 66 // static | |
| 67 aura::Window* ActivationController::GetActivatableWindow(aura::Window* window) { | |
| 68 aura::Window* parent = window->parent(); | |
| 69 aura::Window* child = window; | |
| 70 while (parent) { | |
| 71 if (SupportsChildActivation(parent)) | |
| 72 return child; | |
| 73 // If |child| isn't activatable, but has transient parent, trace | |
| 74 // that path instead. | |
| 75 if (child->transient_parent()) | |
| 76 return GetActivatableWindow(child->transient_parent()); | |
| 77 parent = parent->parent(); | |
| 78 child = child->parent(); | |
| 79 } | |
| 80 return NULL; | |
| 81 } | |
| 82 | |
| 83 // static | |
| 84 bool ActivationController::CanFocusWindow(aura::Window* window) { | |
| 85 return CanActivateWindow(GetActivatableWindow(window)); | |
| 86 } | |
| 87 | |
| 88 //////////////////////////////////////////////////////////////////////////////// | |
| 89 // StackingController, aura::ActivationClient implementation: | |
| 90 | |
| 91 void ActivationController::ActivateWindow(aura::Window* window) { | |
| 92 AutoReset<bool> in_activate_window(&updating_activation_, true); | |
| 93 if (!window) | |
| 94 return; | |
| 95 // Nothing may actually have changed. | |
| 96 aura::Window* old_active = GetActiveWindow(); | |
| 97 if (old_active == window) | |
| 98 return; | |
| 99 // The stacking client may impose rules on what window configurations can be | |
| 100 // activated or deactivated. | |
| 101 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
| |
| 102 return; | |
| 103 | |
| 104 if (!window->Contains(window->GetFocusManager()->GetFocusedWindow())) | |
| 105 window->GetFocusManager()->SetFocusedWindow(window); | |
| 106 aura::RootWindow::GetInstance()->SetProperty(aura::kRootWindowActiveWindow, | |
| 107 window); | |
| 108 // Invoke OnLostActive after we've changed the active window. That way if the | |
| 109 // delegate queries for active state it doesn't think the window is still | |
| 110 // active. | |
| 111 if (old_active && GetActivationDelegate(old_active)) | |
| 112 GetActivationDelegate(old_active)->OnLostActive(); | |
| 113 if (window) { | |
| 114 window->parent()->StackChildAtTop(window); | |
| 115 if (GetActivationDelegate(window)) | |
| 116 GetActivationDelegate(window)->OnActivated(); | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 void ActivationController::DeactivateWindow(aura::Window* window) { | |
| 121 if (window) | |
| 122 ActivateNextWindow(window); | |
| 123 } | |
| 124 | |
| 125 aura::Window* ActivationController::GetActiveWindow() { | |
| 126 return reinterpret_cast<aura::Window*>( | |
| 127 aura::RootWindow::GetInstance()->GetProperty( | |
| 128 aura::kRootWindowActiveWindow)); | |
| 129 } | |
| 130 | |
| 131 //////////////////////////////////////////////////////////////////////////////// | |
| 132 // ActivationController, aura::WindowObserver implementation: | |
| 133 | |
| 134 void ActivationController::OnWindowVisibilityChanged(aura::Window* window, | |
| 135 bool visible) { | |
| 136 if (!visible) | |
| 137 ActivateNextWindow(window); | |
| 138 } | |
| 139 | |
| 140 void ActivationController::OnWindowDestroyed(aura::Window* window) { | |
| 141 if (IsActiveWindow(window)) { | |
| 142 // Clear the property before activating something else, since | |
| 143 // ActivateWindow() will attempt to notify the window stored in this value | |
| 144 // otherwise. | |
| 145 aura::RootWindow::GetInstance()->SetProperty(aura::kRootWindowActiveWindow, | |
| 146 NULL); | |
| 147 ActivateWindow(GetTopmostWindowToActivate(window)); | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 //////////////////////////////////////////////////////////////////////////////// | |
| 152 // ActivationController, aura::RootWindowObserver implementation: | |
| 153 | |
| 154 void ActivationController::OnWindowInitialized(aura::Window* window) { | |
| 155 window->AddObserver(this); | |
|
sky
2011/12/09 23:11:23
It doesn't seem like you ever remove this. Maybe O
| |
| 156 } | |
| 157 | |
| 158 void ActivationController::OnWindowFocused(aura::Window* window) { | |
| 159 if (!updating_activation_) | |
| 160 ActivateWindow(GetActivatableWindow(window)); | |
| 161 } | |
| 162 | |
| 163 //////////////////////////////////////////////////////////////////////////////// | |
| 164 // ActivationController, private: | |
| 165 | |
| 166 void ActivationController::ActivateNextWindow(aura::Window* window) { | |
| 167 if (IsActiveWindow(window)) | |
| 168 ActivateWindow(GetTopmostWindowToActivate(window)); | |
| 169 } | |
| 170 | |
| 171 aura::Window* ActivationController::GetTopmostWindowToActivate( | |
| 172 aura::Window* ignore) const { | |
| 173 const aura::Window* container = | |
| 174 default_container_for_test_ ? default_container_for_test_ : | |
| 175 GetContainer(kShellWindowId_DefaultContainer); | |
| 176 for (aura::Window::Windows::const_reverse_iterator i = | |
| 177 container->children().rbegin(); | |
| 178 i != container->children().rend(); | |
| 179 ++i) { | |
| 180 if (*i != ignore && CanActivateWindow(*i)) | |
| 181 return *i; | |
| 182 } | |
| 183 return NULL; | |
| 184 } | |
| 185 | |
| 186 } // namespace internal | |
| 187 } // namespace aura_shell | |
| OLD | NEW |