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.
4
5 #include "ui/wm/core/window_util.h"
6
7 #include "base/bind.h"
8 #include "ui/aura/client/aura_constants.h"
9 #include "ui/aura/window.h"
10 #include "ui/compositor/dip_util.h"
11 #include "ui/compositor/layer.h"
12 #include "ui/compositor/layer_tree_owner.h"
13 #include "ui/wm/core/transient_window_manager.h"
14 #include "ui/wm/core/window_properties.h"
15 #include "ui/wm/public/activation_client.h"
16
17 namespace {
18
19 // Invokes |map_func| on all the children of |to_clone|, adding the newly
20 // cloned children to |parent|. If |map_func| returns nullptr on
21 // the layer owner, all its layer's children will not be cloned.
22 //
23 // WARNING: It is assumed that |parent| is ultimately owned by a LayerTreeOwner.
CloneChildren(ui::Layer * to_clone,ui::Layer * parent,const wm::MapLayerFunc & map_func)24 void CloneChildren(ui::Layer* to_clone,
25 ui::Layer* parent,
26 const wm::MapLayerFunc& map_func) {
27 typedef std::vector<ui::Layer*> Layers;
28 // Make a copy of the children since RecreateLayer() mutates it.
29 Layers children(to_clone->children());
30 for (Layers::const_iterator i = children.begin(); i != children.end(); ++i) {
31 ui::LayerOwner* owner = (*i)->owner();
32 ui::Layer* old_layer = owner ? map_func.Run(owner).release() : NULL;
33 if (old_layer) {
34 parent->Add(old_layer);
35 // RecreateLayer() moves the existing children to the new layer. Create a
36 // copy of those.
37 CloneChildren(owner->layer(), old_layer, map_func);
38 }
39 }
40 }
41
42 // Invokes Mirror() on all the children of |to_mirror|, adding the newly cloned
43 // children to |parent|.
44 //
45 // WARNING: It is assumed that |parent| is ultimately owned by a LayerTreeOwner.
MirrorChildren(ui::Layer * to_mirror,ui::Layer * parent,bool sync_bounds)46 void MirrorChildren(ui::Layer* to_mirror,
47 ui::Layer* parent,
48 bool sync_bounds) {
49 for (auto* child : to_mirror->children()) {
50 ui::Layer* mirror = child->Mirror().release();
51 mirror->set_sync_bounds_with_source(sync_bounds);
52 parent->Add(mirror);
53 MirrorChildren(child, mirror, sync_bounds);
54 }
55 }
56
57 } // namespace
58
59 namespace wm {
60
ActivateWindow(aura::Window * window)61 void ActivateWindow(aura::Window* window) {
62 DCHECK(window);
63 DCHECK(window->GetRootWindow());
64 GetActivationClient(window->GetRootWindow())->ActivateWindow(window);
65 }
66
DeactivateWindow(aura::Window * window)67 void DeactivateWindow(aura::Window* window) {
68 DCHECK(window);
69 DCHECK(window->GetRootWindow());
70 GetActivationClient(window->GetRootWindow())->DeactivateWindow(window);
71 }
72
IsActiveWindow(const aura::Window * window)73 bool IsActiveWindow(const aura::Window* window) {
74 DCHECK(window);
75 if (!window->GetRootWindow())
76 return false;
77 const ActivationClient* client = GetActivationClient(window->GetRootWindow());
78 return client && client->GetActiveWindow() == window;
79 }
80
CanActivateWindow(const aura::Window * window)81 bool CanActivateWindow(const aura::Window* window) {
82 DCHECK(window);
83 if (!window->GetRootWindow())
84 return false;
85 const ActivationClient* client = GetActivationClient(window->GetRootWindow());
86 return client && client->CanActivateWindow(window);
87 }
88
SetWindowFullscreen(aura::Window * window,bool fullscreen)89 void SetWindowFullscreen(aura::Window* window, bool fullscreen) {
90 DCHECK(window);
91 ui::WindowShowState current_show_state =
92 window->GetProperty(aura::client::kShowStateKey);
93 bool is_fullscreen = current_show_state == ui::SHOW_STATE_FULLSCREEN;
94 if (fullscreen == is_fullscreen)
95 return;
96 if (fullscreen) {
97 // Save the previous show state so that we can correctly restore it after
98 // exiting the fullscreen mode.
99 ui::WindowShowState pre_show_state = current_show_state;
100 // If the previous show state is ui::SHOW_STATE_MINIMIZED, we will use
101 // the show state before the window was minimized. But if the window was
102 // fullscreen before it was minimized, we will keep the
103 // PreMinimizedShowState unchanged.
104 if (pre_show_state == ui::SHOW_STATE_MINIMIZED) {
105 pre_show_state =
106 window->GetProperty(aura::client::kPreMinimizedShowStateKey);
107 }
108 if (pre_show_state != ui::SHOW_STATE_FULLSCREEN) {
109 window->SetProperty(aura::client::kPreFullscreenShowStateKey,
110 pre_show_state);
111 }
112 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
113 } else {
114 ui::WindowShowState pre_fullscreen_show_state =
115 window->GetProperty(aura::client::kPreFullscreenShowStateKey);
116 DCHECK_NE(pre_fullscreen_show_state, ui::SHOW_STATE_MINIMIZED);
117 window->SetProperty(aura::client::kShowStateKey, pre_fullscreen_show_state);
118 window->ClearProperty(aura::client::kPreFullscreenShowStateKey);
119 }
120 }
121
WindowStateIs(const aura::Window * window,ui::WindowShowState state)122 bool WindowStateIs(const aura::Window* window, ui::WindowShowState state) {
123 return window->GetProperty(aura::client::kShowStateKey) == state;
124 }
125
SetWindowState(aura::Window * window,ui::WindowShowState state)126 void SetWindowState(aura::Window* window, ui::WindowShowState state) {
127 window->SetProperty(aura::client::kShowStateKey, state);
128 }
129
Unminimize(aura::Window * window)130 void Unminimize(aura::Window* window) {
131 DCHECK_EQ(window->GetProperty(aura::client::kShowStateKey),
132 ui::SHOW_STATE_MINIMIZED);
133 window->SetProperty(
134 aura::client::kShowStateKey,
135 window->GetProperty(aura::client::kPreMinimizedShowStateKey));
136 }
137
GetActivatableWindow(aura::Window * window)138 aura::Window* GetActivatableWindow(aura::Window* window) {
139 ActivationClient* client = GetActivationClient(window->GetRootWindow());
140 return client ? client->GetActivatableWindow(window) : NULL;
141 }
142
GetToplevelWindow(aura::Window * window)143 aura::Window* GetToplevelWindow(aura::Window* window) {
144 return const_cast<aura::Window*>(
145 GetToplevelWindow(const_cast<const aura::Window*>(window)));
146 }
147
GetToplevelWindow(const aura::Window * window)148 const aura::Window* GetToplevelWindow(const aura::Window* window) {
149 const ActivationClient* client = GetActivationClient(window->GetRootWindow());
150 return client ? client->GetToplevelWindow(window) : NULL;
151 }
152
RecreateLayers(ui::LayerOwner * root)153 std::unique_ptr<ui::LayerTreeOwner> RecreateLayers(ui::LayerOwner* root) {
154 DCHECK(root->OwnsLayer());
155 return RecreateLayersWithClosure(
156 root, base::BindRepeating(
157 [](ui::LayerOwner* owner) { return owner->RecreateLayer(); }));
158 }
159
RecreateLayersWithClosure(ui::LayerOwner * root,const MapLayerFunc & map_func)160 std::unique_ptr<ui::LayerTreeOwner> RecreateLayersWithClosure(
161 ui::LayerOwner* root,
162 const MapLayerFunc& map_func) {
163 DCHECK(root->OwnsLayer());
164 auto layer = map_func.Run(root);
165 if (!layer)
166 return nullptr;
167 auto old_layer = std::make_unique<ui::LayerTreeOwner>(std::move(layer));
168 CloneChildren(root->layer(), old_layer->root(), map_func);
169 return old_layer;
170 }
171
MirrorLayers(ui::LayerOwner * root,bool sync_bounds)172 std::unique_ptr<ui::LayerTreeOwner> MirrorLayers(
173 ui::LayerOwner* root, bool sync_bounds) {
174 auto mirror = std::make_unique<ui::LayerTreeOwner>(root->layer()->Mirror());
175 MirrorChildren(root->layer(), mirror->root(), sync_bounds);
176 return mirror;
177 }
178
GetTransientParent(aura::Window * window)179 aura::Window* GetTransientParent(aura::Window* window) {
180 return const_cast<aura::Window*>(GetTransientParent(
181 const_cast<const aura::Window*>(window)));
182 }
183
GetTransientParent(const aura::Window * window)184 const aura::Window* GetTransientParent(const aura::Window* window) {
185 const TransientWindowManager* manager =
186 TransientWindowManager::GetIfExists(window);
187 return manager ? manager->transient_parent() : nullptr;
188 }
189
GetTransientChildren(const aura::Window * window)190 const std::vector<aura::Window*>& GetTransientChildren(
191 const aura::Window* window) {
192 const TransientWindowManager* manager =
193 TransientWindowManager::GetIfExists(window);
194 if (manager)
195 return manager->transient_children();
196
197 static std::vector<aura::Window*>* shared = new std::vector<aura::Window*>;
198 return *shared;
199 }
200
GetTransientRoot(aura::Window * window)201 aura::Window* GetTransientRoot(aura::Window* window) {
202 while (window && GetTransientParent(window))
203 window = GetTransientParent(window);
204 return window;
205 }
206
AddTransientChild(aura::Window * parent,aura::Window * child)207 void AddTransientChild(aura::Window* parent, aura::Window* child) {
208 TransientWindowManager::GetOrCreate(parent)->AddTransientChild(child);
209 }
210
RemoveTransientChild(aura::Window * parent,aura::Window * child)211 void RemoveTransientChild(aura::Window* parent, aura::Window* child) {
212 TransientWindowManager::GetOrCreate(parent)->RemoveTransientChild(child);
213 }
214
HasTransientAncestor(const aura::Window * window,const aura::Window * ancestor)215 bool HasTransientAncestor(const aura::Window* window,
216 const aura::Window* ancestor) {
217 const aura::Window* transient_parent = GetTransientParent(window);
218 if (transient_parent == ancestor)
219 return true;
220 return transient_parent ?
221 HasTransientAncestor(transient_parent, ancestor) : false;
222 }
223
224 } // namespace wm
225