OLD | NEW |
| (Empty) |
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 "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h
" | |
6 | |
7 #include "apps/app_window.h" | |
8 #include "apps/ui/native_app_window.h" | |
9 #include "ash/shelf/shelf_model.h" | |
10 #include "ash/wm/window_state.h" | |
11 #include "ash/wm/window_util.h" | |
12 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h" | |
13 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_v2app.h" | |
14 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" | |
15 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h" | |
16 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h" | |
17 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h" | |
18 #include "content/public/browser/web_contents.h" | |
19 #include "skia/ext/image_operations.h" | |
20 #include "ui/aura/client/aura_constants.h" | |
21 #include "ui/aura/window.h" | |
22 #include "ui/events/event.h" | |
23 #include "ui/gfx/image/image_skia.h" | |
24 #include "ui/views/corewm/window_animations.h" | |
25 | |
26 using apps::AppWindow; | |
27 | |
28 namespace { | |
29 | |
30 // Size of the icon in the shelf launcher in display-independent pixels. | |
31 const int kAppListIconSize = 24; | |
32 | |
33 // This will return a slightly smaller icon than the app icon to be used in | |
34 // the application list menu. | |
35 scoped_ptr<gfx::Image> GetAppListIcon(AppWindow* app_window) { | |
36 // TODO(skuhne): We instead might want to use LoadImages in | |
37 // AppWindow::UpdateExtensionAppIcon() to let the extension give us | |
38 // pre-defined icons in the launcher and the launcher list sizes. Since there | |
39 // is no mock yet, doing this now seems a bit premature and we scale for the | |
40 // time being. | |
41 if (app_window->app_icon().IsEmpty()) | |
42 return make_scoped_ptr(new gfx::Image()); | |
43 | |
44 SkBitmap bmp = | |
45 skia::ImageOperations::Resize(*app_window->app_icon().ToSkBitmap(), | |
46 skia::ImageOperations::RESIZE_BEST, | |
47 kAppListIconSize, | |
48 kAppListIconSize); | |
49 return make_scoped_ptr( | |
50 new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bmp))); | |
51 } | |
52 | |
53 // Functor for std::find_if used in AppLauncherItemController. | |
54 class AppWindowHasWindow { | |
55 public: | |
56 explicit AppWindowHasWindow(aura::Window* window) : window_(window) {} | |
57 | |
58 bool operator()(AppWindow* app_window) const { | |
59 return app_window->GetNativeWindow() == window_; | |
60 } | |
61 | |
62 private: | |
63 const aura::Window* window_; | |
64 }; | |
65 | |
66 } // namespace | |
67 | |
68 ShellWindowLauncherItemController::ShellWindowLauncherItemController( | |
69 Type type, | |
70 const std::string& app_shelf_id, | |
71 const std::string& app_id, | |
72 ChromeLauncherController* controller) | |
73 : LauncherItemController(type, app_id, controller), | |
74 last_active_app_window_(NULL), | |
75 app_shelf_id_(app_shelf_id), | |
76 observed_windows_(this) {} | |
77 | |
78 ShellWindowLauncherItemController::~ShellWindowLauncherItemController() { | |
79 } | |
80 | |
81 void ShellWindowLauncherItemController::AddAppWindow( | |
82 AppWindow* app_window, | |
83 ash::ShelfItemStatus status) { | |
84 if (app_window->window_type_is_panel() && type() != TYPE_APP_PANEL) | |
85 LOG(ERROR) << "AppWindow of type Panel added to non-panel launcher item"; | |
86 app_windows_.push_front(app_window); | |
87 observed_windows_.Add(app_window->GetNativeWindow()); | |
88 } | |
89 | |
90 void ShellWindowLauncherItemController::RemoveShellWindowForWindow( | |
91 aura::Window* window) { | |
92 AppWindowList::iterator iter = std::find_if( | |
93 app_windows_.begin(), app_windows_.end(), AppWindowHasWindow(window)); | |
94 if (iter != app_windows_.end()) { | |
95 if (*iter == last_active_app_window_) | |
96 last_active_app_window_ = NULL; | |
97 app_windows_.erase(iter); | |
98 } | |
99 observed_windows_.Remove(window); | |
100 } | |
101 | |
102 void ShellWindowLauncherItemController::SetActiveWindow(aura::Window* window) { | |
103 AppWindowList::iterator iter = std::find_if( | |
104 app_windows_.begin(), app_windows_.end(), AppWindowHasWindow(window)); | |
105 if (iter != app_windows_.end()) | |
106 last_active_app_window_ = *iter; | |
107 } | |
108 | |
109 bool ShellWindowLauncherItemController::IsOpen() const { | |
110 return !app_windows_.empty(); | |
111 } | |
112 | |
113 bool ShellWindowLauncherItemController::IsVisible() const { | |
114 // Return true if any windows are visible. | |
115 for (AppWindowList::const_iterator iter = app_windows_.begin(); | |
116 iter != app_windows_.end(); | |
117 ++iter) { | |
118 if ((*iter)->GetNativeWindow()->IsVisible()) | |
119 return true; | |
120 } | |
121 return false; | |
122 } | |
123 | |
124 void ShellWindowLauncherItemController::Launch(ash::LaunchSource source, | |
125 int event_flags) { | |
126 launcher_controller()->LaunchApp(app_id(), | |
127 source, | |
128 ui::EF_NONE); | |
129 } | |
130 | |
131 bool ShellWindowLauncherItemController::Activate(ash::LaunchSource source) { | |
132 DCHECK(!app_windows_.empty()); | |
133 AppWindow* window_to_activate = | |
134 last_active_app_window_ ? last_active_app_window_ : app_windows_.back(); | |
135 window_to_activate->GetBaseWindow()->Activate(); | |
136 return false; | |
137 } | |
138 | |
139 void ShellWindowLauncherItemController::Close() { | |
140 // Note: Closing windows may affect the contents of app_windows_. | |
141 AppWindowList windows_to_close = app_windows_; | |
142 for (AppWindowList::iterator iter = windows_to_close.begin(); | |
143 iter != windows_to_close.end(); | |
144 ++iter) { | |
145 (*iter)->GetBaseWindow()->Close(); | |
146 } | |
147 } | |
148 | |
149 void ShellWindowLauncherItemController::ActivateIndexedApp(size_t index) { | |
150 if (index >= app_windows_.size()) | |
151 return; | |
152 AppWindowList::iterator it = app_windows_.begin(); | |
153 std::advance(it, index); | |
154 ShowAndActivateOrMinimize(*it); | |
155 } | |
156 | |
157 ChromeLauncherAppMenuItems | |
158 ShellWindowLauncherItemController::GetApplicationList(int event_flags) { | |
159 ChromeLauncherAppMenuItems items; | |
160 items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false)); | |
161 int index = 0; | |
162 for (AppWindowList::iterator iter = app_windows_.begin(); | |
163 iter != app_windows_.end(); | |
164 ++iter) { | |
165 AppWindow* app_window = *iter; | |
166 scoped_ptr<gfx::Image> image(GetAppListIcon(app_window)); | |
167 items.push_back(new ChromeLauncherAppMenuItemV2App( | |
168 app_window->GetTitle(), | |
169 image.get(), // Will be copied | |
170 app_id(), | |
171 launcher_controller(), | |
172 index, | |
173 index == 0 /* has_leading_separator */)); | |
174 ++index; | |
175 } | |
176 return items.Pass(); | |
177 } | |
178 | |
179 bool ShellWindowLauncherItemController::ItemSelected(const ui::Event& event) { | |
180 if (app_windows_.empty()) | |
181 return false; | |
182 if (type() == TYPE_APP_PANEL) { | |
183 DCHECK(app_windows_.size() == 1); | |
184 AppWindow* panel = app_windows_.front(); | |
185 aura::Window* panel_window = panel->GetNativeWindow(); | |
186 // If the panel is attached on another display, move it to the current | |
187 // display and activate it. | |
188 if (ash::wm::GetWindowState(panel_window)->panel_attached() && | |
189 ash::wm::MoveWindowToEventRoot(panel_window, event)) { | |
190 if (!panel->GetBaseWindow()->IsActive()) | |
191 ShowAndActivateOrMinimize(panel); | |
192 } else { | |
193 ShowAndActivateOrMinimize(panel); | |
194 } | |
195 } else { | |
196 AppWindow* window_to_show = last_active_app_window_ | |
197 ? last_active_app_window_ | |
198 : app_windows_.front(); | |
199 // If the event was triggered by a keystroke, we try to advance to the next | |
200 // item if the window we are trying to activate is already active. | |
201 if (app_windows_.size() >= 1 && | |
202 window_to_show->GetBaseWindow()->IsActive() && | |
203 event.type() == ui::ET_KEY_RELEASED) { | |
204 ActivateOrAdvanceToNextShellWindow(window_to_show); | |
205 } else { | |
206 ShowAndActivateOrMinimize(window_to_show); | |
207 } | |
208 } | |
209 return false; | |
210 } | |
211 | |
212 base::string16 ShellWindowLauncherItemController::GetTitle() { | |
213 // For panels return the title of the contents if set. | |
214 // Otherwise return the title of the app. | |
215 if (type() == TYPE_APP_PANEL && !app_windows_.empty()) { | |
216 AppWindow* app_window = app_windows_.front(); | |
217 if (app_window->web_contents()) { | |
218 base::string16 title = app_window->web_contents()->GetTitle(); | |
219 if (!title.empty()) | |
220 return title; | |
221 } | |
222 } | |
223 return GetAppTitle(); | |
224 } | |
225 | |
226 ui::MenuModel* ShellWindowLauncherItemController::CreateContextMenu( | |
227 aura::Window* root_window) { | |
228 ash::ShelfItem item = | |
229 *(launcher_controller()->model()->ItemByID(shelf_id())); | |
230 return new LauncherContextMenu(launcher_controller(), &item, root_window); | |
231 } | |
232 | |
233 ash::ShelfMenuModel* ShellWindowLauncherItemController::CreateApplicationMenu( | |
234 int event_flags) { | |
235 return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags)); | |
236 } | |
237 | |
238 bool ShellWindowLauncherItemController::IsDraggable() { | |
239 if (type() == TYPE_APP_PANEL) | |
240 return true; | |
241 return launcher_controller()->CanPin() ? true : false; | |
242 } | |
243 | |
244 bool ShellWindowLauncherItemController::ShouldShowTooltip() { | |
245 if (type() == TYPE_APP_PANEL && IsVisible()) | |
246 return false; | |
247 return true; | |
248 } | |
249 | |
250 void ShellWindowLauncherItemController::OnWindowPropertyChanged( | |
251 aura::Window* window, | |
252 const void* key, | |
253 intptr_t old) { | |
254 if (key == aura::client::kDrawAttentionKey) { | |
255 ash::ShelfItemStatus status; | |
256 if (ash::wm::IsActiveWindow(window)) { | |
257 status = ash::STATUS_ACTIVE; | |
258 } else if (window->GetProperty(aura::client::kDrawAttentionKey)) { | |
259 status = ash::STATUS_ATTENTION; | |
260 } else { | |
261 status = ash::STATUS_RUNNING; | |
262 } | |
263 launcher_controller()->SetItemStatus(shelf_id(), status); | |
264 } | |
265 } | |
266 | |
267 void ShellWindowLauncherItemController::ShowAndActivateOrMinimize( | |
268 AppWindow* app_window) { | |
269 // Either show or minimize windows when shown from the launcher. | |
270 launcher_controller()->ActivateWindowOrMinimizeIfActive( | |
271 app_window->GetBaseWindow(), GetApplicationList(0).size() == 2); | |
272 } | |
273 | |
274 void ShellWindowLauncherItemController::ActivateOrAdvanceToNextShellWindow( | |
275 AppWindow* window_to_show) { | |
276 AppWindowList::iterator i( | |
277 std::find(app_windows_.begin(), app_windows_.end(), window_to_show)); | |
278 if (i != app_windows_.end()) { | |
279 if (++i != app_windows_.end()) | |
280 window_to_show = *i; | |
281 else | |
282 window_to_show = app_windows_.front(); | |
283 } | |
284 if (window_to_show->GetBaseWindow()->IsActive()) { | |
285 // Coming here, only a single window is active. For keyboard activations | |
286 // the window gets animated. | |
287 AnimateWindow(window_to_show->GetNativeWindow(), | |
288 views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE); | |
289 } else { | |
290 ShowAndActivateOrMinimize(window_to_show); | |
291 } | |
292 } | |
OLD | NEW |