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