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 "chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h"
7 #include "apps/shell_window.h"
8 #include "ash/shelf/shelf_util.h"
10 #include "ash/wm/window_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
14 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h"
15 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
16 #include "chrome/browser/ui/host_desktop.h"
17 #include "extensions/common/extension.h"
18 #include "ui/aura/client/activation_client.h"
19 #include "ui/aura/root_window.h"
21 using apps::ShellWindow
;
25 std::string
GetAppLauncherId(ShellWindow
* shell_window
) {
26 if (shell_window
->window_type_is_panel())
27 return base::StringPrintf("panel:%d", shell_window
->session_id().id());
28 return shell_window
->extension()->id();
31 bool ControlsWindow(aura::Window
* window
) {
32 return chrome::GetHostDesktopTypeForNativeWindow(window
) ==
33 chrome::HOST_DESKTOP_TYPE_ASH
;
38 ShellWindowLauncherController::ShellWindowLauncherController(
39 ChromeLauncherController
* owner
)
41 activation_client_(NULL
) {
42 apps::ShellWindowRegistry
* registry
=
43 apps::ShellWindowRegistry::Get(owner
->profile());
44 registry_
.insert(registry
);
45 registry
->AddObserver(this);
46 if (ash::Shell::HasInstance()) {
47 if (ash::Shell::GetInstance()->GetPrimaryRootWindow()) {
48 activation_client_
= aura::client::GetActivationClient(
49 ash::Shell::GetInstance()->GetPrimaryRootWindow());
50 if (activation_client_
)
51 activation_client_
->AddObserver(this);
56 ShellWindowLauncherController::~ShellWindowLauncherController() {
57 for (std::set
<apps::ShellWindowRegistry
*>::iterator it
= registry_
.begin();
58 it
!= registry_
.end(); ++it
)
59 (*it
)->RemoveObserver(this);
61 if (activation_client_
)
62 activation_client_
->RemoveObserver(this);
63 for (WindowToAppLauncherIdMap::iterator iter
=
64 window_to_app_launcher_id_map_
.begin();
65 iter
!= window_to_app_launcher_id_map_
.end(); ++iter
) {
66 iter
->first
->RemoveObserver(this);
70 void ShellWindowLauncherController::AdditionalUserAddedToSession(
72 // TODO(skuhne): This was added for the legacy side by side mode in M32. If
73 // this mode gets no longer pursued this special case can be removed.
74 if (chrome::MultiUserWindowManager::GetMultiProfileMode() !=
75 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_MIXED
)
78 apps::ShellWindowRegistry
* registry
= apps::ShellWindowRegistry::Get(profile
);
79 if (registry_
.find(registry
) != registry_
.end())
82 registry
->AddObserver(this);
83 registry_
.insert(registry
);
86 void ShellWindowLauncherController::OnShellWindowAdded(
87 ShellWindow
* shell_window
) {
88 if (!ControlsWindow(shell_window
->GetNativeWindow()))
90 RegisterApp(shell_window
);
93 void ShellWindowLauncherController::OnShellWindowIconChanged(
94 ShellWindow
* shell_window
) {
95 if (!ControlsWindow(shell_window
->GetNativeWindow()))
98 const std::string app_launcher_id
= GetAppLauncherId(shell_window
);
99 AppControllerMap::iterator iter
= app_controller_map_
.find(app_launcher_id
);
100 if (iter
== app_controller_map_
.end())
102 ShellWindowLauncherItemController
* controller
= iter
->second
;
103 controller
->set_image_set_by_controller(true);
104 owner_
->SetLauncherItemImage(controller
->launcher_id(),
105 shell_window
->app_icon().AsImageSkia());
108 void ShellWindowLauncherController::OnShellWindowRemoved(
109 ShellWindow
* shell_window
) {
110 // Do nothing here; shell_window->window() has already been deleted and
111 // OnWindowDestroying() has been called, doing the removal.
114 // Called from aura::Window::~Window(), before delegate_->OnWindowDestroyed()
115 // which destroys ShellWindow, so both |window| and the associated ShellWindow
117 void ShellWindowLauncherController::OnWindowDestroying(aura::Window
* window
) {
118 if (!ControlsWindow(window
))
120 UnregisterApp(window
);
123 void ShellWindowLauncherController::OnWindowActivated(
124 aura::Window
* new_active
,
125 aura::Window
* old_active
) {
126 // Make the newly active window the active (first) entry in the controller.
127 ShellWindowLauncherItemController
* new_controller
=
128 ControllerForWindow(new_active
);
129 if (new_controller
) {
130 new_controller
->SetActiveWindow(new_active
);
131 owner_
->SetItemStatus(new_controller
->launcher_id(), ash::STATUS_ACTIVE
);
134 // Mark the old active window's launcher item as running (if different).
135 ShellWindowLauncherItemController
* old_controller
=
136 ControllerForWindow(old_active
);
137 if (old_controller
&& old_controller
!= new_controller
)
138 owner_
->SetItemStatus(old_controller
->launcher_id(), ash::STATUS_RUNNING
);
141 void ShellWindowLauncherController::RegisterApp(ShellWindow
* shell_window
) {
142 aura::Window
* window
= shell_window
->GetNativeWindow();
143 // Get the app's launcher identifier and add an entry to the map.
144 DCHECK(window_to_app_launcher_id_map_
.find(window
) ==
145 window_to_app_launcher_id_map_
.end());
146 const std::string app_launcher_id
= GetAppLauncherId(shell_window
);
147 window_to_app_launcher_id_map_
[window
] = app_launcher_id
;
148 window
->AddObserver(this);
150 // Find or create an item controller and launcher item.
151 std::string app_id
= shell_window
->extension()->id();
152 ash::LauncherItemStatus status
= ash::wm::IsActiveWindow(window
) ?
153 ash::STATUS_ACTIVE
: ash::STATUS_RUNNING
;
154 AppControllerMap::iterator iter
= app_controller_map_
.find(app_launcher_id
);
155 ash::LauncherID launcher_id
= 0;
156 if (iter
!= app_controller_map_
.end()) {
157 ShellWindowLauncherItemController
* controller
= iter
->second
;
158 DCHECK(controller
->app_id() == app_id
);
159 launcher_id
= controller
->launcher_id();
160 controller
->AddShellWindow(shell_window
, status
);
162 LauncherItemController::Type type
= shell_window
->window_type_is_panel()
163 ? LauncherItemController::TYPE_APP_PANEL
164 : LauncherItemController::TYPE_APP
;
165 ShellWindowLauncherItemController
* controller
=
166 new ShellWindowLauncherItemController(
167 type
, app_launcher_id
, app_id
, owner_
);
168 controller
->AddShellWindow(shell_window
, status
);
169 // If the app launcher id is not unique, and there is already a launcher
170 // item for this app id (e.g. pinned), use that launcher item.
171 if (app_launcher_id
== app_id
)
172 launcher_id
= owner_
->GetLauncherIDForAppID(app_id
);
173 if (launcher_id
== 0)
174 launcher_id
= owner_
->CreateAppLauncherItem(controller
, app_id
, status
);
176 owner_
->SetItemController(launcher_id
, controller
);
177 const std::string app_launcher_id
= GetAppLauncherId(shell_window
);
178 app_controller_map_
[app_launcher_id
] = controller
;
180 owner_
->SetItemStatus(launcher_id
, status
);
181 ash::SetLauncherIDForWindow(launcher_id
, window
);
184 void ShellWindowLauncherController::UnregisterApp(aura::Window
* window
) {
185 WindowToAppLauncherIdMap::iterator iter1
=
186 window_to_app_launcher_id_map_
.find(window
);
187 DCHECK(iter1
!= window_to_app_launcher_id_map_
.end());
188 std::string app_launcher_id
= iter1
->second
;
189 window_to_app_launcher_id_map_
.erase(iter1
);
190 window
->RemoveObserver(this);
192 AppControllerMap::iterator iter2
= app_controller_map_
.find(app_launcher_id
);
193 DCHECK(iter2
!= app_controller_map_
.end());
194 ShellWindowLauncherItemController
* controller
= iter2
->second
;
195 controller
->RemoveShellWindowForWindow(window
);
196 if (controller
->shell_window_count() == 0) {
197 // If this is the last window associated with the app launcher id, close the
199 ash::LauncherID launcher_id
= controller
->launcher_id();
200 owner_
->CloseLauncherItem(launcher_id
);
201 app_controller_map_
.erase(iter2
);
205 bool ShellWindowLauncherController::IsRegisteredApp(aura::Window
* window
) {
206 return window_to_app_launcher_id_map_
.find(window
) !=
207 window_to_app_launcher_id_map_
.end();
212 ShellWindowLauncherItemController
*
213 ShellWindowLauncherController::ControllerForWindow(
214 aura::Window
* window
) {
215 WindowToAppLauncherIdMap::iterator iter1
=
216 window_to_app_launcher_id_map_
.find(window
);
217 if (iter1
== window_to_app_launcher_id_map_
.end())
219 std::string app_launcher_id
= iter1
->second
;
220 AppControllerMap::iterator iter2
= app_controller_map_
.find(app_launcher_id
);
221 if (iter2
== app_controller_map_
.end())
223 return iter2
->second
;