OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h" | 5 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h" |
6 | 6 |
7 #include "ash/wm/window_state.h" | |
8 #include "ash/wm/window_util.h" | 7 #include "ash/wm/window_util.h" |
9 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h" | |
10 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_v2app.h" | |
11 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" | 8 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
12 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h" | |
13 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h" | |
14 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h" | |
15 #include "components/favicon/content/content_favicon_driver.h" | |
16 #include "content/public/browser/web_contents.h" | |
17 #include "extensions/browser/app_window/app_window.h" | |
18 #include "extensions/browser/app_window/native_app_window.h" | |
19 #include "skia/ext/image_operations.h" | |
20 #include "ui/aura/client/aura_constants.h" | 9 #include "ui/aura/client/aura_constants.h" |
21 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
22 #include "ui/events/event.h" | 11 #include "ui/base/base_window.h" |
23 #include "ui/gfx/image/image_skia.h" | |
24 #include "ui/wm/core/window_animations.h" | 12 #include "ui/wm/core/window_animations.h" |
25 | 13 |
26 using extensions::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 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 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 gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bmp)); | |
50 } | |
51 | |
52 // Functor for std::find_if used in AppLauncherItemController. | |
53 class AppWindowHasWindow { | |
54 public: | |
55 explicit AppWindowHasWindow(aura::Window* window) : window_(window) {} | |
56 | |
57 bool operator()(AppWindow* app_window) const { | |
58 return app_window->GetNativeWindow() == window_; | |
59 } | |
60 | |
61 private: | |
62 const aura::Window* window_; | |
63 }; | |
64 | |
65 } // namespace | |
66 | |
67 AppWindowLauncherItemController::AppWindowLauncherItemController( | 14 AppWindowLauncherItemController::AppWindowLauncherItemController( |
68 Type type, | 15 Type type, |
69 const std::string& app_shelf_id, | 16 const std::string& app_shelf_id, |
70 const std::string& app_id, | 17 const std::string& app_id, |
71 ChromeLauncherController* controller) | 18 ChromeLauncherController* controller) |
72 : LauncherItemController(type, app_id, controller), | 19 : LauncherItemController(type, app_id, controller), |
73 last_active_app_window_(NULL), | |
74 app_shelf_id_(app_shelf_id), | 20 app_shelf_id_(app_shelf_id), |
75 observed_windows_(this) {} | 21 observed_windows_(this) {} |
76 | 22 |
77 AppWindowLauncherItemController::~AppWindowLauncherItemController() {} | 23 AppWindowLauncherItemController::~AppWindowLauncherItemController() {} |
78 | 24 |
79 void AppWindowLauncherItemController::AddAppWindow( | 25 void AppWindowLauncherItemController::AddWindow(ui::BaseWindow* window) { |
80 AppWindow* app_window, | 26 windows_.push_front(window); |
81 ash::ShelfItemStatus status) { | 27 observed_windows_.Add(window->GetNativeWindow()); |
82 if (app_window->window_type_is_panel() && type() != TYPE_APP_PANEL) | |
83 LOG(ERROR) << "AppWindow of type Panel added to non-panel launcher item"; | |
84 app_windows_.push_front(app_window); | |
85 observed_windows_.Add(app_window->GetNativeWindow()); | |
86 } | 28 } |
87 | 29 |
88 void AppWindowLauncherItemController::RemoveAppWindowForWindow( | 30 AppWindowLauncherItemController::WindowList::iterator |
31 AppWindowLauncherItemController::GetFromNativeWindow(aura::Window* window) { | |
32 return std::find_if(windows_.begin(), windows_.end(), | |
dcheng
2016/03/26 09:02:31
Nit: #include <algorithm> for find_if.
khmel
2016/03/28 17:17:31
Done.
| |
33 [window](ui::BaseWindow* base_window) { | |
34 return base_window->GetNativeWindow() == window; | |
35 }); | |
36 } | |
37 | |
38 void AppWindowLauncherItemController::RemoveWindowForNativeWindow( | |
89 aura::Window* window) { | 39 aura::Window* window) { |
90 AppWindowList::iterator iter = std::find_if( | 40 auto iter = GetFromNativeWindow(window); |
91 app_windows_.begin(), app_windows_.end(), AppWindowHasWindow(window)); | 41 if (iter != windows_.end()) { |
92 if (iter != app_windows_.end()) { | 42 if (*iter == last_active_window_) |
93 if (*iter == last_active_app_window_) | 43 last_active_window_ = nullptr; |
94 last_active_app_window_ = NULL; | 44 OnWindowRemoved(*iter); |
95 app_windows_.erase(iter); | 45 windows_.erase(iter); |
96 } | 46 } |
97 observed_windows_.Remove(window); | 47 observed_windows_.Remove(window); |
98 } | 48 } |
99 | 49 |
100 void AppWindowLauncherItemController::SetActiveWindow(aura::Window* window) { | 50 void AppWindowLauncherItemController::SetActiveWindow(aura::Window* window) { |
101 AppWindowList::iterator iter = std::find_if( | 51 auto iter = GetFromNativeWindow(window); |
102 app_windows_.begin(), app_windows_.end(), AppWindowHasWindow(window)); | 52 if (iter != windows_.end()) |
103 if (iter != app_windows_.end()) | 53 last_active_window_ = *iter; |
104 last_active_app_window_ = *iter; | |
105 } | 54 } |
106 | 55 |
107 bool AppWindowLauncherItemController::IsOpen() const { | 56 bool AppWindowLauncherItemController::IsOpen() const { |
108 return !app_windows_.empty(); | 57 return !windows_.empty(); |
109 } | 58 } |
110 | 59 |
111 bool AppWindowLauncherItemController::IsVisible() const { | 60 bool AppWindowLauncherItemController::IsVisible() const { |
112 // Return true if any windows are visible. | 61 // Return true if any windows are visible. |
113 for (AppWindowList::const_iterator iter = app_windows_.begin(); | 62 for (const auto& window : windows_) { |
114 iter != app_windows_.end(); | 63 if (window->GetNativeWindow()->IsVisible()) |
115 ++iter) { | |
116 if ((*iter)->GetNativeWindow()->IsVisible()) | |
117 return true; | 64 return true; |
118 } | 65 } |
119 return false; | 66 return false; |
120 } | 67 } |
121 | 68 |
122 void AppWindowLauncherItemController::Launch(ash::LaunchSource source, | 69 void AppWindowLauncherItemController::Launch(ash::LaunchSource source, |
123 int event_flags) { | 70 int event_flags) { |
124 launcher_controller()->LaunchApp(app_id(), source, ui::EF_NONE); | 71 launcher_controller()->LaunchApp(app_id(), source, ui::EF_NONE); |
125 } | 72 } |
126 | 73 |
127 ash::ShelfItemDelegate::PerformedAction | 74 ash::ShelfItemDelegate::PerformedAction |
128 AppWindowLauncherItemController::Activate(ash::LaunchSource source) { | 75 AppWindowLauncherItemController::Activate(ash::LaunchSource source) { |
129 DCHECK(!app_windows_.empty()); | 76 DCHECK(!windows_.empty()); |
130 AppWindow* window_to_activate = | 77 ui::BaseWindow* window_to_activate = |
131 last_active_app_window_ ? last_active_app_window_ : app_windows_.back(); | 78 last_active_window_ ? last_active_window_ : windows_.back(); |
132 window_to_activate->GetBaseWindow()->Activate(); | 79 window_to_activate->Activate(); |
133 return kExistingWindowActivated; | 80 return kExistingWindowActivated; |
134 } | 81 } |
135 | 82 |
136 void AppWindowLauncherItemController::Close() { | 83 void AppWindowLauncherItemController::Close() { |
137 // Note: Closing windows may affect the contents of app_windows_. | 84 // Note: Closing windows may affect the contents of app_windows_. |
138 AppWindowList windows_to_close = app_windows_; | 85 WindowList windows_to_close = windows_; |
139 for (AppWindowList::iterator iter = windows_to_close.begin(); | 86 for (const auto& window : windows_) |
140 iter != windows_to_close.end(); | 87 window->Close(); |
141 ++iter) { | |
142 (*iter)->GetBaseWindow()->Close(); | |
143 } | |
144 } | 88 } |
145 | 89 |
146 void AppWindowLauncherItemController::ActivateIndexedApp(size_t index) { | 90 void AppWindowLauncherItemController::ActivateIndexedApp(size_t index) { |
147 if (index >= app_windows_.size()) | 91 if (index >= windows_.size()) |
148 return; | 92 return; |
149 AppWindowList::iterator it = app_windows_.begin(); | 93 auto it = windows_.begin(); |
150 std::advance(it, index); | 94 std::advance(it, index); |
151 ShowAndActivateOrMinimize(*it); | 95 ShowAndActivateOrMinimize(*it); |
152 } | 96 } |
153 | 97 |
154 ChromeLauncherAppMenuItems AppWindowLauncherItemController::GetApplicationList( | 98 ChromeLauncherAppMenuItems AppWindowLauncherItemController::GetApplicationList( |
155 int event_flags) { | 99 int event_flags) { |
156 ChromeLauncherAppMenuItems items; | 100 ChromeLauncherAppMenuItems items; |
157 items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false)); | 101 items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false)); |
158 int index = 0; | |
159 for (AppWindowList::iterator iter = app_windows_.begin(); | |
160 iter != app_windows_.end(); | |
161 ++iter) { | |
162 AppWindow* app_window = *iter; | |
163 | |
164 // If the app's web contents provides a favicon, use it. Otherwise, use a | |
165 // scaled down app icon. | |
166 favicon::FaviconDriver* favicon_driver = | |
167 favicon::ContentFaviconDriver::FromWebContents( | |
168 app_window->web_contents()); | |
169 gfx::Image result = favicon_driver->GetFavicon(); | |
170 if (result.IsEmpty()) | |
171 result = GetAppListIcon(app_window); | |
172 | |
173 items.push_back(new ChromeLauncherAppMenuItemV2App( | |
174 app_window->GetTitle(), | |
175 &result, // Will be copied | |
176 app_id(), | |
177 launcher_controller(), | |
178 index, | |
179 index == 0 /* has_leading_separator */)); | |
180 ++index; | |
181 } | |
182 return items; | 102 return items; |
183 } | 103 } |
184 | 104 |
185 ash::ShelfItemDelegate::PerformedAction | 105 ash::ShelfItemDelegate::PerformedAction |
186 AppWindowLauncherItemController::ItemSelected(const ui::Event& event) { | 106 AppWindowLauncherItemController::ItemSelected(const ui::Event& event) { |
187 if (app_windows_.empty()) | 107 if (windows_.empty()) |
188 return kNoAction; | 108 return kNoAction; |
189 if (type() == TYPE_APP_PANEL) { | 109 |
190 DCHECK_EQ(app_windows_.size(), 1u); | 110 DCHECK_EQ(TYPE_APP, type()); |
191 AppWindow* panel = app_windows_.front(); | 111 ui::BaseWindow* window_to_show = |
192 aura::Window* panel_window = panel->GetNativeWindow(); | 112 last_active_window_ ? last_active_window_ : windows_.front(); |
193 // If the panel is attached on another display, move it to the current | 113 // If the event was triggered by a keystroke, we try to advance to the next |
194 // display and activate it. | 114 // item if the window we are trying to activate is already active. |
195 if (ash::wm::GetWindowState(panel_window)->panel_attached() && | 115 if (windows_.size() >= 1 && window_to_show->IsActive() && |
196 ash::wm::MoveWindowToEventRoot(panel_window, event)) { | 116 event.type() == ui::ET_KEY_RELEASED) { |
197 if (!panel->GetBaseWindow()->IsActive()) | 117 return ActivateOrAdvanceToNextAppWindow(window_to_show); |
198 return ShowAndActivateOrMinimize(panel); | |
199 } else { | |
200 return ShowAndActivateOrMinimize(panel); | |
201 } | |
202 } else { | 118 } else { |
203 AppWindow* window_to_show = last_active_app_window_ | 119 return ShowAndActivateOrMinimize(window_to_show); |
204 ? last_active_app_window_ | |
205 : app_windows_.front(); | |
206 // If the event was triggered by a keystroke, we try to advance to the next | |
207 // item if the window we are trying to activate is already active. | |
208 if (app_windows_.size() >= 1 && | |
209 window_to_show->GetBaseWindow()->IsActive() && | |
210 event.type() == ui::ET_KEY_RELEASED) { | |
211 return ActivateOrAdvanceToNextAppWindow(window_to_show); | |
212 } else { | |
213 return ShowAndActivateOrMinimize(window_to_show); | |
214 } | |
215 } | 120 } |
216 return kNoAction; | |
217 } | 121 } |
218 | 122 |
219 base::string16 AppWindowLauncherItemController::GetTitle() { | 123 base::string16 AppWindowLauncherItemController::GetTitle() { |
220 // For panels return the title of the contents if set. | |
221 // Otherwise return the title of the app. | |
222 if (type() == TYPE_APP_PANEL && !app_windows_.empty()) { | |
223 AppWindow* app_window = app_windows_.front(); | |
224 if (app_window->web_contents()) { | |
225 base::string16 title = app_window->web_contents()->GetTitle(); | |
226 if (!title.empty()) | |
227 return title; | |
228 } | |
229 } | |
230 return GetAppTitle(); | 124 return GetAppTitle(); |
231 } | 125 } |
232 | 126 |
233 ash::ShelfMenuModel* AppWindowLauncherItemController::CreateApplicationMenu( | |
234 int event_flags) { | |
235 return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags)); | |
236 } | |
237 | |
238 bool AppWindowLauncherItemController::IsDraggable() { | 127 bool AppWindowLauncherItemController::IsDraggable() { |
239 if (type() == TYPE_APP_PANEL) | 128 DCHECK_EQ(TYPE_APP, type()); |
240 return true; | |
241 return CanPin(); | 129 return CanPin(); |
242 } | 130 } |
243 | 131 |
244 bool AppWindowLauncherItemController::CanPin() const { | 132 bool AppWindowLauncherItemController::CanPin() const { |
245 return launcher_controller()->CanPin(app_id()); | 133 return launcher_controller()->CanPin(app_id()); |
246 } | 134 } |
247 | 135 |
248 bool AppWindowLauncherItemController::ShouldShowTooltip() { | 136 bool AppWindowLauncherItemController::ShouldShowTooltip() { |
249 if (type() == TYPE_APP_PANEL && IsVisible()) | 137 DCHECK_EQ(TYPE_APP, type()); |
250 return false; | |
251 return true; | 138 return true; |
252 } | 139 } |
253 | 140 |
254 void AppWindowLauncherItemController::OnWindowPropertyChanged( | 141 void AppWindowLauncherItemController::OnWindowPropertyChanged( |
255 aura::Window* window, | 142 aura::Window* window, |
256 const void* key, | 143 const void* key, |
257 intptr_t old) { | 144 intptr_t old) { |
258 if (key == aura::client::kDrawAttentionKey) { | 145 if (key == aura::client::kDrawAttentionKey) { |
259 ash::ShelfItemStatus status; | 146 ash::ShelfItemStatus status; |
260 if (ash::wm::IsActiveWindow(window)) { | 147 if (ash::wm::IsActiveWindow(window)) { |
261 status = ash::STATUS_ACTIVE; | 148 status = ash::STATUS_ACTIVE; |
262 } else if (window->GetProperty(aura::client::kDrawAttentionKey)) { | 149 } else if (window->GetProperty(aura::client::kDrawAttentionKey)) { |
263 status = ash::STATUS_ATTENTION; | 150 status = ash::STATUS_ATTENTION; |
264 } else { | 151 } else { |
265 status = ash::STATUS_RUNNING; | 152 status = ash::STATUS_RUNNING; |
266 } | 153 } |
267 launcher_controller()->SetItemStatus(shelf_id(), status); | 154 launcher_controller()->SetItemStatus(shelf_id(), status); |
268 } | 155 } |
269 } | 156 } |
270 | 157 |
271 ash::ShelfItemDelegate::PerformedAction | 158 ash::ShelfItemDelegate::PerformedAction |
272 AppWindowLauncherItemController::ShowAndActivateOrMinimize( | 159 AppWindowLauncherItemController::ShowAndActivateOrMinimize( |
273 AppWindow* app_window) { | 160 ui::BaseWindow* app_window) { |
274 // Either show or minimize windows when shown from the launcher. | 161 // Either show or minimize windows when shown from the launcher. |
275 return launcher_controller()->ActivateWindowOrMinimizeIfActive( | 162 return launcher_controller()->ActivateWindowOrMinimizeIfActive( |
276 app_window->GetBaseWindow(), GetApplicationList(0).size() == 2); | 163 app_window, GetApplicationList(0).size() == 2); |
277 } | 164 } |
278 | 165 |
279 ash::ShelfItemDelegate::PerformedAction | 166 ash::ShelfItemDelegate::PerformedAction |
280 AppWindowLauncherItemController::ActivateOrAdvanceToNextAppWindow( | 167 AppWindowLauncherItemController::ActivateOrAdvanceToNextAppWindow( |
281 AppWindow* window_to_show) { | 168 ui::BaseWindow* window_to_show) { |
282 AppWindowList::iterator i( | 169 WindowList::iterator i( |
283 std::find(app_windows_.begin(), app_windows_.end(), window_to_show)); | 170 std::find(windows_.begin(), windows_.end(), window_to_show)); |
284 if (i != app_windows_.end()) { | 171 if (i != windows_.end()) { |
285 if (++i != app_windows_.end()) | 172 if (++i != windows_.end()) |
286 window_to_show = *i; | 173 window_to_show = *i; |
287 else | 174 else |
288 window_to_show = app_windows_.front(); | 175 window_to_show = windows_.front(); |
289 } | 176 } |
290 if (window_to_show->GetBaseWindow()->IsActive()) { | 177 if (window_to_show->IsActive()) { |
291 // Coming here, only a single window is active. For keyboard activations | 178 // Coming here, only a single window is active. For keyboard activations |
292 // the window gets animated. | 179 // the window gets animated. |
293 AnimateWindow(window_to_show->GetNativeWindow(), | 180 AnimateWindow(window_to_show->GetNativeWindow(), |
294 wm::WINDOW_ANIMATION_TYPE_BOUNCE); | 181 wm::WINDOW_ANIMATION_TYPE_BOUNCE); |
295 } else { | 182 } else { |
296 return ShowAndActivateOrMinimize(window_to_show); | 183 return ShowAndActivateOrMinimize(window_to_show); |
297 } | 184 } |
298 return kNoAction; | 185 return kNoAction; |
299 } | 186 } |
OLD | NEW |