base: Change DCHECK_IS_ON to a macro DCHECK_IS_ON().
[chromium-blink-merge.git] / ui / wm / core / shadow_controller.cc
blobd25b4a551c34b9854b8011da97bfdbed347827f6
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/client/aura_constants.h"
14 #include "ui/aura/env.h"
15 #include "ui/aura/env_observer.h"
16 #include "ui/aura/window.h"
17 #include "ui/aura/window_observer.h"
18 #include "ui/base/ui_base_types.h"
19 #include "ui/compositor/layer.h"
20 #include "ui/wm/core/shadow.h"
21 #include "ui/wm/core/shadow_types.h"
22 #include "ui/wm/core/window_util.h"
23 #include "ui/wm/public/activation_client.h"
25 using std::make_pair;
27 namespace wm {
29 namespace {
31 ShadowType GetShadowTypeFromWindow(aura::Window* window) {
32 switch (window->type()) {
33 case ui::wm::WINDOW_TYPE_NORMAL:
34 case ui::wm::WINDOW_TYPE_PANEL:
35 case ui::wm::WINDOW_TYPE_MENU:
36 case ui::wm::WINDOW_TYPE_TOOLTIP:
37 return SHADOW_TYPE_RECTANGULAR;
38 default:
39 break;
41 return SHADOW_TYPE_NONE;
44 bool ShouldUseSmallShadowForWindow(aura::Window* window) {
45 switch (window->type()) {
46 case ui::wm::WINDOW_TYPE_MENU:
47 case ui::wm::WINDOW_TYPE_TOOLTIP:
48 return true;
49 default:
50 break;
52 return false;
55 bool IsShadowAlwaysActive(aura::Window* window) {
56 return GetShadowType(window) == SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE;
59 Shadow::Style GetShadowStyleForWindow(aura::Window* window) {
60 return ShouldUseSmallShadowForWindow(window) ? Shadow::STYLE_SMALL :
61 ((IsActiveWindow(window) || IsShadowAlwaysActive(window)) ?
62 Shadow::STYLE_ACTIVE : Shadow::STYLE_INACTIVE);
65 // Returns the shadow style to be applied to |losing_active| when it is losing
66 // active to |gaining_active|. |gaining_active| may be of a type that hides when
67 // inactive, and as such we do not want to render |losing_active| as inactive.
68 Shadow::Style GetShadowStyleForWindowLosingActive(
69 aura::Window* losing_active,
70 aura::Window* gaining_active) {
71 if (IsShadowAlwaysActive(losing_active))
72 return Shadow::STYLE_ACTIVE;
74 if (gaining_active && aura::client::GetHideOnDeactivate(gaining_active)) {
75 aura::Window::Windows::const_iterator it =
76 std::find(GetTransientChildren(losing_active).begin(),
77 GetTransientChildren(losing_active).end(),
78 gaining_active);
79 if (it != GetTransientChildren(losing_active).end())
80 return Shadow::STYLE_ACTIVE;
82 return Shadow::STYLE_INACTIVE;
85 } // namespace
87 // ShadowController::Impl ------------------------------------------------------
89 // Real implementation of the ShadowController. ShadowController observes
90 // ActivationChangeObserver, which are per ActivationClient, where as there is
91 // only a single Impl (as it observes all window creation by way of an
92 // EnvObserver).
93 class ShadowController::Impl :
94 public aura::EnvObserver,
95 public aura::WindowObserver,
96 public base::RefCounted<Impl> {
97 public:
98 // Returns the singleton instance, destroyed when there are no more refs.
99 static Impl* GetInstance();
101 // aura::EnvObserver override:
102 void OnWindowInitialized(aura::Window* window) override;
104 // aura::WindowObserver overrides:
105 void OnWindowPropertyChanged(aura::Window* window,
106 const void* key,
107 intptr_t old) override;
108 void OnWindowBoundsChanged(aura::Window* window,
109 const gfx::Rect& old_bounds,
110 const gfx::Rect& new_bounds) override;
111 void OnWindowDestroyed(aura::Window* window) override;
113 private:
114 friend class base::RefCounted<Impl>;
115 friend class ShadowController;
116 friend class ShadowController::TestApi;
118 typedef std::map<aura::Window*, linked_ptr<Shadow> > WindowShadowMap;
120 Impl();
121 ~Impl() override;
123 // Forwarded from ShadowController.
124 void OnWindowActivated(aura::Window* gained_active,
125 aura::Window* lost_active);
127 // Checks if |window| is visible and contains a property requesting a shadow.
128 bool ShouldShowShadowForWindow(aura::Window* window) const;
130 // Returns |window|'s shadow from |window_shadows_|, or NULL if no shadow
131 // exists.
132 Shadow* GetShadowForWindow(aura::Window* window);
134 // Updates the shadow styles for windows when activation changes.
135 void HandleWindowActivationChange(aura::Window* gaining_active,
136 aura::Window* losing_active);
138 // Shows or hides |window|'s shadow as needed (creating the shadow if
139 // necessary).
140 void HandlePossibleShadowVisibilityChange(aura::Window* window);
142 // Creates a new shadow for |window| and stores it in |window_shadows_|. The
143 // shadow's bounds are initialized and it is added to the window's layer.
144 void CreateShadowForWindow(aura::Window* window);
146 WindowShadowMap window_shadows_;
148 ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_;
150 static Impl* instance_;
152 DISALLOW_COPY_AND_ASSIGN(Impl);
155 // static
156 ShadowController::Impl* ShadowController::Impl::instance_ = NULL;
158 // static
159 ShadowController::Impl* ShadowController::Impl::GetInstance() {
160 if (!instance_)
161 instance_ = new Impl();
162 return instance_;
165 void ShadowController::Impl::OnWindowInitialized(aura::Window* window) {
166 observer_manager_.Add(window);
167 SetShadowType(window, GetShadowTypeFromWindow(window));
168 HandlePossibleShadowVisibilityChange(window);
171 void ShadowController::Impl::OnWindowPropertyChanged(aura::Window* window,
172 const void* key,
173 intptr_t old) {
174 if (key == kShadowTypeKey || key == aura::client::kShowStateKey) {
175 HandlePossibleShadowVisibilityChange(window);
176 return;
180 void ShadowController::Impl::OnWindowBoundsChanged(
181 aura::Window* window,
182 const gfx::Rect& old_bounds,
183 const gfx::Rect& new_bounds) {
184 Shadow* shadow = GetShadowForWindow(window);
185 if (shadow)
186 shadow->SetContentBounds(gfx::Rect(new_bounds.size()));
189 void ShadowController::Impl::OnWindowDestroyed(aura::Window* window) {
190 window_shadows_.erase(window);
191 observer_manager_.Remove(window);
194 void ShadowController::Impl::OnWindowActivated(aura::Window* gained_active,
195 aura::Window* lost_active) {
196 if (gained_active) {
197 Shadow* shadow = GetShadowForWindow(gained_active);
198 if (shadow && !ShouldUseSmallShadowForWindow(gained_active))
199 shadow->SetStyle(Shadow::STYLE_ACTIVE);
201 if (lost_active) {
202 Shadow* shadow = GetShadowForWindow(lost_active);
203 if (shadow && !ShouldUseSmallShadowForWindow(lost_active)) {
204 shadow->SetStyle(GetShadowStyleForWindowLosingActive(lost_active,
205 gained_active));
210 bool ShadowController::Impl::ShouldShowShadowForWindow(
211 aura::Window* window) const {
212 ui::WindowShowState show_state =
213 window->GetProperty(aura::client::kShowStateKey);
214 if (show_state == ui::SHOW_STATE_FULLSCREEN ||
215 show_state == ui::SHOW_STATE_MAXIMIZED) {
216 return SHADOW_TYPE_NONE;
219 const ShadowType type = GetShadowType(window);
220 switch (type) {
221 case SHADOW_TYPE_NONE:
222 return false;
223 case SHADOW_TYPE_RECTANGULAR:
224 case SHADOW_TYPE_RECTANGULAR_ALWAYS_ACTIVE:
225 return true;
226 default:
227 NOTREACHED() << "Unknown shadow type " << type;
228 return false;
232 Shadow* ShadowController::Impl::GetShadowForWindow(aura::Window* window) {
233 WindowShadowMap::const_iterator it = window_shadows_.find(window);
234 return it != window_shadows_.end() ? it->second.get() : NULL;
237 void ShadowController::Impl::HandlePossibleShadowVisibilityChange(
238 aura::Window* window) {
239 const bool should_show = ShouldShowShadowForWindow(window);
240 Shadow* shadow = GetShadowForWindow(window);
241 if (shadow) {
242 shadow->SetStyle(GetShadowStyleForWindow(window));
243 shadow->layer()->SetVisible(should_show);
244 } else if (should_show && !shadow) {
245 CreateShadowForWindow(window);
249 void ShadowController::Impl::CreateShadowForWindow(aura::Window* window) {
250 linked_ptr<Shadow> shadow(new Shadow());
251 window_shadows_.insert(make_pair(window, shadow));
252 shadow->Init(GetShadowStyleForWindow(window));
253 shadow->SetContentBounds(gfx::Rect(window->bounds().size()));
254 shadow->layer()->SetVisible(ShouldShowShadowForWindow(window));
255 window->layer()->Add(shadow->layer());
258 ShadowController::Impl::Impl()
259 : observer_manager_(this) {
260 aura::Env::GetInstance()->AddObserver(this);
263 ShadowController::Impl::~Impl() {
264 DCHECK_EQ(instance_, this);
265 aura::Env::GetInstance()->RemoveObserver(this);
266 instance_ = NULL;
269 // ShadowController ------------------------------------------------------------
271 ShadowController::ShadowController(
272 aura::client::ActivationClient* activation_client)
273 : activation_client_(activation_client),
274 impl_(Impl::GetInstance()) {
275 // Watch for window activation changes.
276 activation_client_->AddObserver(this);
279 ShadowController::~ShadowController() {
280 activation_client_->RemoveObserver(this);
283 void ShadowController::OnWindowActivated(aura::Window* gained_active,
284 aura::Window* lost_active) {
285 impl_->OnWindowActivated(gained_active, lost_active);
288 // ShadowController::TestApi ---------------------------------------------------
290 Shadow* ShadowController::TestApi::GetShadowForWindow(aura::Window* window) {
291 return controller_->impl_->GetShadowForWindow(window);
294 } // namespace wm