Roll src/third_party/skia b14e4a0:3c29c4d
[chromium-blink-merge.git] / ui / wm / core / shadow_controller.cc
blob67a3630839d312aeb53aca40f144e175a0a2c69a
1 // Copyright (c) 2012 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.
5 #include "ui/wm/core/shadow_controller.h"
7 #include <utility>
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/memory/linked_ptr.h"
12 #include "base/scoped_observer.h"
13 #include "ui/aura/env.h"
14 #include "ui/aura/env_observer.h"
15 #include "ui/aura/window.h"
16 #include "ui/aura/window_event_dispatcher.h"
17 #include "ui/aura/window_observer.h"
18 #include "ui/compositor/layer.h"
19 #include "ui/wm/core/shadow.h"
20 #include "ui/wm/core/shadow_types.h"
21 #include "ui/wm/core/window_util.h"
22 #include "ui/wm/public/activation_client.h"
24 using std::make_pair;
26 namespace wm {
28 namespace {
30 ShadowType GetShadowTypeFromWindow(aura::Window* window) {
31 switch (window->type()) {
32 case ui::wm::WINDOW_TYPE_NORMAL:
33 case ui::wm::WINDOW_TYPE_PANEL:
34 case ui::wm::WINDOW_TYPE_MENU:
35 case ui::wm::WINDOW_TYPE_TOOLTIP:
36 return SHADOW_TYPE_RECTANGULAR;
37 default:
38 break;
40 return SHADOW_TYPE_NONE;
43 bool ShouldUseSmallShadowForWindow(aura::Window* window) {
44 switch (window->type()) {
45 case ui::wm::WINDOW_TYPE_MENU:
46 case ui::wm::WINDOW_TYPE_TOOLTIP:
47 return true;
48 default:
49 break;
51 return false;
54 bool IsShadowAlwaysActive(aura::Window* window) {
55 return GetShadowType(window) == SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE;
58 Shadow::Style GetShadowStyleForWindow(aura::Window* window) {
59 return ShouldUseSmallShadowForWindow(window) ? Shadow::STYLE_SMALL :
60 ((IsActiveWindow(window) || IsShadowAlwaysActive(window)) ?
61 Shadow::STYLE_ACTIVE : Shadow::STYLE_INACTIVE);
64 // Returns the shadow style to be applied to |losing_active| when it is losing
65 // active to |gaining_active|. |gaining_active| may be of a type that hides when
66 // inactive, and as such we do not want to render |losing_active| as inactive.
67 Shadow::Style GetShadowStyleForWindowLosingActive(
68 aura::Window* losing_active,
69 aura::Window* gaining_active) {
70 if (IsShadowAlwaysActive(losing_active))
71 return Shadow::STYLE_ACTIVE;
73 if (gaining_active && aura::client::GetHideOnDeactivate(gaining_active)) {
74 aura::Window::Windows::const_iterator it =
75 std::find(GetTransientChildren(losing_active).begin(),
76 GetTransientChildren(losing_active).end(),
77 gaining_active);
78 if (it != GetTransientChildren(losing_active).end())
79 return Shadow::STYLE_ACTIVE;
81 return Shadow::STYLE_INACTIVE;
84 } // namespace
86 // ShadowController::Impl ------------------------------------------------------
88 // Real implementation of the ShadowController. ShadowController observes
89 // ActivationChangeObserver, which are per ActivationClient, where as there is
90 // only a single Impl (as it observes all window creation by way of an
91 // EnvObserver).
92 class ShadowController::Impl :
93 public aura::EnvObserver,
94 public aura::WindowObserver,
95 public base::RefCounted<Impl> {
96 public:
97 // Returns the singleton instance, destroyed when there are no more refs.
98 static Impl* GetInstance();
100 // aura::EnvObserver override:
101 virtual void OnWindowInitialized(aura::Window* window) OVERRIDE;
103 // aura::WindowObserver overrides:
104 virtual void OnWindowPropertyChanged(
105 aura::Window* window, const void* key, intptr_t old) OVERRIDE;
106 virtual void OnWindowBoundsChanged(
107 aura::Window* window,
108 const gfx::Rect& old_bounds,
109 const gfx::Rect& new_bounds) OVERRIDE;
110 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
112 private:
113 friend class base::RefCounted<Impl>;
114 friend class ShadowController;
115 friend class ShadowController::TestApi;
117 typedef std::map<aura::Window*, linked_ptr<Shadow> > WindowShadowMap;
119 Impl();
120 virtual ~Impl();
122 // Forwarded from ShadowController.
123 void OnWindowActivated(aura::Window* gained_active,
124 aura::Window* lost_active);
126 // Checks if |window| is visible and contains a property requesting a shadow.
127 bool ShouldShowShadowForWindow(aura::Window* window) const;
129 // Returns |window|'s shadow from |window_shadows_|, or NULL if no shadow
130 // exists.
131 Shadow* GetShadowForWindow(aura::Window* window);
133 // Updates the shadow styles for windows when activation changes.
134 void HandleWindowActivationChange(aura::Window* gaining_active,
135 aura::Window* losing_active);
137 // Shows or hides |window|'s shadow as needed (creating the shadow if
138 // necessary).
139 void HandlePossibleShadowVisibilityChange(aura::Window* window);
141 // Creates a new shadow for |window| and stores it in |window_shadows_|. The
142 // shadow's bounds are initialized and it is added to the window's layer.
143 void CreateShadowForWindow(aura::Window* window);
145 WindowShadowMap window_shadows_;
147 ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_;
149 static Impl* instance_;
151 DISALLOW_COPY_AND_ASSIGN(Impl);
154 // static
155 ShadowController::Impl* ShadowController::Impl::instance_ = NULL;
157 // static
158 ShadowController::Impl* ShadowController::Impl::GetInstance() {
159 if (!instance_)
160 instance_ = new Impl();
161 return instance_;
164 void ShadowController::Impl::OnWindowInitialized(aura::Window* window) {
165 observer_manager_.Add(window);
166 SetShadowType(window, GetShadowTypeFromWindow(window));
167 HandlePossibleShadowVisibilityChange(window);
170 void ShadowController::Impl::OnWindowPropertyChanged(aura::Window* window,
171 const void* key,
172 intptr_t old) {
173 if (key == kShadowTypeKey) {
174 HandlePossibleShadowVisibilityChange(window);
175 return;
179 void ShadowController::Impl::OnWindowBoundsChanged(
180 aura::Window* window,
181 const gfx::Rect& old_bounds,
182 const gfx::Rect& new_bounds) {
183 Shadow* shadow = GetShadowForWindow(window);
184 if (shadow)
185 shadow->SetContentBounds(gfx::Rect(new_bounds.size()));
188 void ShadowController::Impl::OnWindowDestroyed(aura::Window* window) {
189 window_shadows_.erase(window);
190 observer_manager_.Remove(window);
193 void ShadowController::Impl::OnWindowActivated(aura::Window* gained_active,
194 aura::Window* lost_active) {
195 if (gained_active) {
196 Shadow* shadow = GetShadowForWindow(gained_active);
197 if (shadow && !ShouldUseSmallShadowForWindow(gained_active))
198 shadow->SetStyle(Shadow::STYLE_ACTIVE);
200 if (lost_active) {
201 Shadow* shadow = GetShadowForWindow(lost_active);
202 if (shadow && !ShouldUseSmallShadowForWindow(lost_active)) {
203 shadow->SetStyle(GetShadowStyleForWindowLosingActive(lost_active,
204 gained_active));
209 bool ShadowController::Impl::ShouldShowShadowForWindow(
210 aura::Window* window) const {
211 const ShadowType type = GetShadowType(window);
212 switch (type) {
213 case SHADOW_TYPE_NONE:
214 return false;
215 case SHADOW_TYPE_RECTANGULAR:
216 case SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE:
217 return true;
218 default:
219 NOTREACHED() << "Unknown shadow type " << type;
220 return false;
224 Shadow* ShadowController::Impl::GetShadowForWindow(aura::Window* window) {
225 WindowShadowMap::const_iterator it = window_shadows_.find(window);
226 return it != window_shadows_.end() ? it->second.get() : NULL;
229 void ShadowController::Impl::HandlePossibleShadowVisibilityChange(
230 aura::Window* window) {
231 const bool should_show = ShouldShowShadowForWindow(window);
232 Shadow* shadow = GetShadowForWindow(window);
233 if (shadow) {
234 shadow->SetStyle(GetShadowStyleForWindow(window));
235 shadow->layer()->SetVisible(should_show);
236 } else if (should_show && !shadow) {
237 CreateShadowForWindow(window);
241 void ShadowController::Impl::CreateShadowForWindow(aura::Window* window) {
242 linked_ptr<Shadow> shadow(new Shadow());
243 window_shadows_.insert(make_pair(window, shadow));
244 shadow->Init(GetShadowStyleForWindow(window));
245 shadow->SetContentBounds(gfx::Rect(window->bounds().size()));
246 shadow->layer()->SetVisible(ShouldShowShadowForWindow(window));
247 window->layer()->Add(shadow->layer());
250 ShadowController::Impl::Impl()
251 : observer_manager_(this) {
252 aura::Env::GetInstance()->AddObserver(this);
255 ShadowController::Impl::~Impl() {
256 DCHECK_EQ(instance_, this);
257 aura::Env::GetInstance()->RemoveObserver(this);
258 instance_ = NULL;
261 // ShadowController ------------------------------------------------------------
263 ShadowController::ShadowController(
264 aura::client::ActivationClient* activation_client)
265 : activation_client_(activation_client),
266 impl_(Impl::GetInstance()) {
267 // Watch for window activation changes.
268 activation_client_->AddObserver(this);
271 ShadowController::~ShadowController() {
272 activation_client_->RemoveObserver(this);
275 void ShadowController::OnWindowActivated(aura::Window* gained_active,
276 aura::Window* lost_active) {
277 impl_->OnWindowActivated(gained_active, lost_active);
280 // ShadowController::TestApi ---------------------------------------------------
282 Shadow* ShadowController::TestApi::GetShadowForWindow(aura::Window* window) {
283 return controller_->impl_->GetShadowForWindow(window);
286 } // namespace wm