1 // Copyright 2013 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/default_activation_client.h"
6 
7 #include "base/macros.h"
8 #include "ui/aura/window.h"
9 #include "ui/wm/public/activation_change_observer.h"
10 #include "ui/wm/public/activation_delegate.h"
11 
12 namespace wm {
13 
14 // Takes care of observing root window destruction & destroying the client.
15 class DefaultActivationClient::Deleter : public aura::WindowObserver {
16  public:
Deleter(DefaultActivationClient * client,aura::Window * root_window)17   Deleter(DefaultActivationClient* client, aura::Window* root_window)
18       : client_(client),
19         root_window_(root_window) {
20     root_window_->AddObserver(this);
21   }
22 
23  private:
~Deleter()24   ~Deleter() override {}
25 
26   // Overridden from WindowObserver:
OnWindowDestroyed(aura::Window * window)27   void OnWindowDestroyed(aura::Window* window) override {
28     DCHECK_EQ(window, root_window_);
29     root_window_->RemoveObserver(this);
30     delete client_;
31     delete this;
32   }
33 
34   DefaultActivationClient* client_;
35   aura::Window* root_window_;
36 
37   DISALLOW_COPY_AND_ASSIGN(Deleter);
38 };
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 // DefaultActivationClient, public:
42 
DefaultActivationClient(aura::Window * root_window)43 DefaultActivationClient::DefaultActivationClient(aura::Window* root_window)
44     : last_active_(nullptr) {
45   SetActivationClient(root_window, this);
46   new Deleter(this, root_window);
47 }
48 
49 ////////////////////////////////////////////////////////////////////////////////
50 // DefaultActivationClient, ActivationClient implementation:
51 
AddObserver(ActivationChangeObserver * observer)52 void DefaultActivationClient::AddObserver(ActivationChangeObserver* observer) {
53   observers_.AddObserver(observer);
54 }
55 
RemoveObserver(ActivationChangeObserver * observer)56 void DefaultActivationClient::RemoveObserver(
57     ActivationChangeObserver* observer) {
58   observers_.RemoveObserver(observer);
59 }
60 
ActivateWindow(aura::Window * window)61 void DefaultActivationClient::ActivateWindow(aura::Window* window) {
62   ActivateWindowImpl(
63       ActivationChangeObserver::ActivationReason::ACTIVATION_CLIENT, window);
64 }
65 
ActivateWindowImpl(ActivationChangeObserver::ActivationReason reason,aura::Window * window)66 void DefaultActivationClient::ActivateWindowImpl(
67     ActivationChangeObserver::ActivationReason reason,
68     aura::Window* window) {
69   aura::Window* last_active = ActivationClient::GetActiveWindow();
70   if (last_active == window)
71     return;
72 
73   for (auto& observer : observers_)
74     observer.OnWindowActivating(reason, window, last_active);
75 
76   last_active_ = last_active;
77   RemoveActiveWindow(window);
78   active_windows_.push_back(window);
79   window->parent()->StackChildAtTop(window);
80   window->AddObserver(this);
81 
82   for (auto& observer : observers_)
83     observer.OnWindowActivated(reason, window, last_active);
84 
85   ActivationChangeObserver* observer = GetActivationChangeObserver(last_active);
86   if (observer) {
87     observer->OnWindowActivated(reason, window, last_active);
88   }
89   observer = GetActivationChangeObserver(window);
90   if (observer) {
91     observer->OnWindowActivated(reason, window, last_active);
92   }
93 }
94 
DeactivateWindow(aura::Window * window)95 void DefaultActivationClient::DeactivateWindow(aura::Window* window) {
96   ActivationChangeObserver* observer = GetActivationChangeObserver(window);
97   if (observer) {
98     observer->OnWindowActivated(
99         ActivationChangeObserver::ActivationReason::ACTIVATION_CLIENT, nullptr,
100         window);
101   }
102   if (last_active_)
103     ActivateWindow(last_active_);
104 }
105 
GetActiveWindow() const106 const aura::Window* DefaultActivationClient::GetActiveWindow() const {
107   if (active_windows_.empty())
108     return nullptr;
109   return active_windows_.back();
110 }
111 
GetActivatableWindow(aura::Window * window) const112 aura::Window* DefaultActivationClient::GetActivatableWindow(
113     aura::Window* window) const {
114   return nullptr;
115 }
116 
GetToplevelWindow(const aura::Window * window) const117 const aura::Window* DefaultActivationClient::GetToplevelWindow(
118     const aura::Window* window) const {
119   return nullptr;
120 }
121 
CanActivateWindow(const aura::Window * window) const122 bool DefaultActivationClient::CanActivateWindow(
123     const aura::Window* window) const {
124   return true;
125 }
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 // DefaultActivationClient, aura::WindowObserver implementation:
129 
OnWindowDestroyed(aura::Window * window)130 void DefaultActivationClient::OnWindowDestroyed(aura::Window* window) {
131   if (window == last_active_)
132     last_active_ = nullptr;
133 
134   if (window == GetActiveWindow()) {
135     active_windows_.pop_back();
136     aura::Window* next_active = ActivationClient::GetActiveWindow();
137     if (next_active && GetActivationChangeObserver(next_active)) {
138       GetActivationChangeObserver(next_active)
139           ->OnWindowActivated(ActivationChangeObserver::ActivationReason::
140                                   WINDOW_DISPOSITION_CHANGED,
141                               next_active, nullptr);
142     }
143     return;
144   }
145 
146   RemoveActiveWindow(window);
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 // DefaultActivationClient, private:
151 
~DefaultActivationClient()152 DefaultActivationClient::~DefaultActivationClient() {
153   for (unsigned int i = 0; i < active_windows_.size(); ++i) {
154     active_windows_[i]->RemoveObserver(this);
155   }
156 }
157 
RemoveActiveWindow(aura::Window * window)158 void DefaultActivationClient::RemoveActiveWindow(aura::Window* window) {
159   for (unsigned int i = 0; i < active_windows_.size(); ++i) {
160     if (active_windows_[i] == window) {
161       active_windows_.erase(active_windows_.begin() + i);
162       window->RemoveObserver(this);
163       return;
164     }
165   }
166 }
167 
168 }  // namespace wm
169