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 { | 14 namespace { |
29 | 15 |
30 // Size of the icon in the shelf launcher in display-independent pixels. | 16 // Functor for std::find_if used in AppLauncherItemController. |
31 const int kAppListIconSize = 24; | 17 class WindowHasNativeWindow { |
18 public: | |
19 explicit WindowHasNativeWindow(aura::Window* window) : window_(window) {} | |
32 | 20 |
33 // This will return a slightly smaller icon than the app icon to be used in | 21 bool operator()(ui::BaseWindow* window) const { |
34 // the application list menu. | 22 return window->GetNativeWindow() == window_; |
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 } | 23 } |
60 | |
61 private: | 24 private: |
62 const aura::Window* window_; | 25 const aura::Window* window_; |
63 }; | 26 }; |
64 | 27 |
65 } // namespace | 28 } // namespace |
66 | 29 |
67 AppWindowLauncherItemController::AppWindowLauncherItemController( | 30 AppWindowLauncherItemController::AppWindowLauncherItemController( |
68 Type type, | 31 Type type, |
69 const std::string& app_shelf_id, | 32 const std::string& app_shelf_id, |
70 const std::string& app_id, | 33 const std::string& app_id, |
71 ChromeLauncherController* controller) | 34 ChromeLauncherController* controller) |
72 : LauncherItemController(type, app_id, controller), | 35 : LauncherItemController(type, app_id, controller), |
73 last_active_app_window_(NULL), | |
74 app_shelf_id_(app_shelf_id), | 36 app_shelf_id_(app_shelf_id), |
75 observed_windows_(this) {} | 37 observed_windows_(this) {} |
76 | 38 |
77 AppWindowLauncherItemController::~AppWindowLauncherItemController() {} | 39 AppWindowLauncherItemController::~AppWindowLauncherItemController() {} |
78 | 40 |
79 void AppWindowLauncherItemController::AddAppWindow( | 41 void AppWindowLauncherItemController::AddWindow(ui::BaseWindow* window) { |
80 AppWindow* app_window, | 42 windows_.push_front(window); |
81 ash::ShelfItemStatus status) { | 43 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 } | 44 } |
87 | 45 |
88 void AppWindowLauncherItemController::RemoveAppWindowForWindow( | 46 void AppWindowLauncherItemController::RemoveWindowForNativeWindow( |
89 aura::Window* window) { | 47 aura::Window* window) { |
90 AppWindowList::iterator iter = std::find_if( | 48 WindowList::iterator iter = std::find_if(windows_.begin(), windows_.end(), |
91 app_windows_.begin(), app_windows_.end(), AppWindowHasWindow(window)); | 49 WindowHasNativeWindow(window)); |
xiyuan
2016/03/23 23:22:53
nit: we can use lambda
e.g.
auto iter = std::fin
khmel
2016/03/24 16:30:37
Thanks for idea, also use helper function to reduc
| |
92 if (iter != app_windows_.end()) { | 50 if (iter != windows_.end()) { |
93 if (*iter == last_active_app_window_) | 51 if (*iter == last_active_window_) |
94 last_active_app_window_ = NULL; | 52 last_active_window_ = nullptr; |
95 app_windows_.erase(iter); | 53 OnWindowRemoved(*iter); |
54 windows_.erase(iter); | |
96 } | 55 } |
97 observed_windows_.Remove(window); | 56 observed_windows_.Remove(window); |
98 } | 57 } |
99 | 58 |
100 void AppWindowLauncherItemController::SetActiveWindow(aura::Window* window) { | 59 void AppWindowLauncherItemController::SetActiveWindow(aura::Window* window) { |
101 AppWindowList::iterator iter = std::find_if( | 60 WindowList::iterator iter = std::find_if(windows_.begin(), windows_.end(), |
102 app_windows_.begin(), app_windows_.end(), AppWindowHasWindow(window)); | 61 WindowHasNativeWindow(window)); |
xiyuan
2016/03/23 23:22:53
nit: use lambda ?
khmel
2016/03/24 16:30:37
Done.
| |
103 if (iter != app_windows_.end()) | 62 if (iter != windows_.end()) |
104 last_active_app_window_ = *iter; | 63 last_active_window_ = *iter; |
105 } | 64 } |
106 | 65 |
107 bool AppWindowLauncherItemController::IsOpen() const { | 66 bool AppWindowLauncherItemController::IsOpen() const { |
108 return !app_windows_.empty(); | 67 return !windows_.empty(); |
109 } | 68 } |
110 | 69 |
111 bool AppWindowLauncherItemController::IsVisible() const { | 70 bool AppWindowLauncherItemController::IsVisible() const { |
112 // Return true if any windows are visible. | 71 // Return true if any windows are visible. |
113 for (AppWindowList::const_iterator iter = app_windows_.begin(); | 72 for (WindowList::const_iterator iter = windows_.begin(); |
114 iter != app_windows_.end(); | 73 iter != windows_.end(); ++iter) { |
xiyuan
2016/03/23 23:22:52
nit: We can use range loop now.
i.e.
for (const a
khmel
2016/03/24 16:30:37
Done.
| |
115 ++iter) { | |
116 if ((*iter)->GetNativeWindow()->IsVisible()) | 74 if ((*iter)->GetNativeWindow()->IsVisible()) |
117 return true; | 75 return true; |
118 } | 76 } |
119 return false; | 77 return false; |
120 } | 78 } |
121 | 79 |
122 void AppWindowLauncherItemController::Launch(ash::LaunchSource source, | 80 void AppWindowLauncherItemController::Launch(ash::LaunchSource source, |
123 int event_flags) { | 81 int event_flags) { |
124 launcher_controller()->LaunchApp(app_id(), source, ui::EF_NONE); | 82 launcher_controller()->LaunchApp(app_id(), source, ui::EF_NONE); |
125 } | 83 } |
126 | 84 |
127 ash::ShelfItemDelegate::PerformedAction | 85 ash::ShelfItemDelegate::PerformedAction |
128 AppWindowLauncherItemController::Activate(ash::LaunchSource source) { | 86 AppWindowLauncherItemController::Activate(ash::LaunchSource source) { |
129 DCHECK(!app_windows_.empty()); | 87 DCHECK(!windows_.empty()); |
130 AppWindow* window_to_activate = | 88 ui::BaseWindow* window_to_activate = |
131 last_active_app_window_ ? last_active_app_window_ : app_windows_.back(); | 89 last_active_window_ ? last_active_window_ : windows_.back(); |
132 window_to_activate->GetBaseWindow()->Activate(); | 90 window_to_activate->Activate(); |
133 return kExistingWindowActivated; | 91 return kExistingWindowActivated; |
134 } | 92 } |
135 | 93 |
136 void AppWindowLauncherItemController::Close() { | 94 void AppWindowLauncherItemController::Close() { |
137 // Note: Closing windows may affect the contents of app_windows_. | 95 // Note: Closing windows may affect the contents of app_windows_. |
138 AppWindowList windows_to_close = app_windows_; | 96 WindowList windows_to_close = windows_; |
139 for (AppWindowList::iterator iter = windows_to_close.begin(); | 97 for (WindowList::iterator iter = windows_to_close.begin(); |
140 iter != windows_to_close.end(); | 98 iter != windows_to_close.end(); ++iter) { |
xiyuan
2016/03/23 23:22:52
nit: range loop?
khmel
2016/03/24 16:30:37
Done.
| |
141 ++iter) { | 99 (*iter)->Close(); |
142 (*iter)->GetBaseWindow()->Close(); | |
143 } | 100 } |
144 } | 101 } |
145 | 102 |
146 void AppWindowLauncherItemController::ActivateIndexedApp(size_t index) { | 103 void AppWindowLauncherItemController::ActivateIndexedApp(size_t index) { |
147 if (index >= app_windows_.size()) | 104 if (index >= windows_.size()) |
148 return; | 105 return; |
149 AppWindowList::iterator it = app_windows_.begin(); | 106 WindowList::iterator it = windows_.begin(); |
150 std::advance(it, index); | 107 std::advance(it, index); |
151 ShowAndActivateOrMinimize(*it); | 108 ShowAndActivateOrMinimize(*it); |
152 } | 109 } |
153 | 110 |
154 ChromeLauncherAppMenuItems AppWindowLauncherItemController::GetApplicationList( | 111 ChromeLauncherAppMenuItems AppWindowLauncherItemController::GetApplicationList( |
155 int event_flags) { | 112 int event_flags) { |
156 ChromeLauncherAppMenuItems items; | 113 ChromeLauncherAppMenuItems items; |
157 items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false)); | 114 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; | 115 return items; |
183 } | 116 } |
184 | 117 |
185 ash::ShelfItemDelegate::PerformedAction | 118 ash::ShelfItemDelegate::PerformedAction |
186 AppWindowLauncherItemController::ItemSelected(const ui::Event& event) { | 119 AppWindowLauncherItemController::ItemSelected(const ui::Event& event) { |
187 if (app_windows_.empty()) | 120 if (windows_.empty()) |
188 return kNoAction; | 121 return kNoAction; |
189 if (type() == TYPE_APP_PANEL) { | 122 |
190 DCHECK_EQ(app_windows_.size(), 1u); | 123 DCHECK(type() == TYPE_APP); |
xiyuan
2016/03/23 23:22:53
nit: DCHECK_EQ(TYPE_APP, type());
khmel
2016/03/24 16:30:37
Done.
| |
191 AppWindow* panel = app_windows_.front(); | 124 ui::BaseWindow* window_to_show = |
192 aura::Window* panel_window = panel->GetNativeWindow(); | 125 last_active_window_ ? last_active_window_ : windows_.front(); |
193 // If the panel is attached on another display, move it to the current | 126 // If the event was triggered by a keystroke, we try to advance to the next |
194 // display and activate it. | 127 // item if the window we are trying to activate is already active. |
195 if (ash::wm::GetWindowState(panel_window)->panel_attached() && | 128 if (windows_.size() >= 1 && window_to_show->IsActive() && |
196 ash::wm::MoveWindowToEventRoot(panel_window, event)) { | 129 event.type() == ui::ET_KEY_RELEASED) { |
197 if (!panel->GetBaseWindow()->IsActive()) | 130 return ActivateOrAdvanceToNextAppWindow(window_to_show); |
198 return ShowAndActivateOrMinimize(panel); | |
199 } else { | |
200 return ShowAndActivateOrMinimize(panel); | |
201 } | |
202 } else { | 131 } else { |
203 AppWindow* window_to_show = last_active_app_window_ | 132 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 } | 133 } |
216 return kNoAction; | |
217 } | 134 } |
218 | 135 |
219 base::string16 AppWindowLauncherItemController::GetTitle() { | 136 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(); | 137 return GetAppTitle(); |
231 } | 138 } |
232 | 139 |
233 ash::ShelfMenuModel* AppWindowLauncherItemController::CreateApplicationMenu( | 140 ash::ShelfMenuModel* AppWindowLauncherItemController::CreateApplicationMenu( |
234 int event_flags) { | 141 int event_flags) { |
235 return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags)); | 142 return nullptr; |
xiyuan
2016/03/23 23:22:52
ArcAppWindowLauncherItemController does not overid
khmel
2016/03/24 16:30:37
For better reading it is better remove it here.
| |
236 } | 143 } |
237 | 144 |
238 bool AppWindowLauncherItemController::IsDraggable() { | 145 bool AppWindowLauncherItemController::IsDraggable() { |
239 if (type() == TYPE_APP_PANEL) | 146 DCHECK(type() == TYPE_APP); |
xiyuan
2016/03/23 23:22:53
nit: DCHECK_EQ(TYPE_APP, type());
khmel
2016/03/24 16:30:37
Done.
| |
240 return true; | |
241 return CanPin(); | 147 return CanPin(); |
242 } | 148 } |
243 | 149 |
244 bool AppWindowLauncherItemController::CanPin() const { | 150 bool AppWindowLauncherItemController::CanPin() const { |
245 return launcher_controller()->CanPin(app_id()); | 151 return launcher_controller()->CanPin(app_id()); |
246 } | 152 } |
247 | 153 |
248 bool AppWindowLauncherItemController::ShouldShowTooltip() { | 154 bool AppWindowLauncherItemController::ShouldShowTooltip() { |
249 if (type() == TYPE_APP_PANEL && IsVisible()) | 155 DCHECK(type() == TYPE_APP); |
xiyuan
2016/03/23 23:22:53
nit: DCHECK_EQ(TYPE_APP, type());
khmel
2016/03/24 16:30:37
Done.
| |
250 return false; | |
251 return true; | 156 return true; |
252 } | 157 } |
253 | 158 |
254 void AppWindowLauncherItemController::OnWindowPropertyChanged( | 159 void AppWindowLauncherItemController::OnWindowPropertyChanged( |
255 aura::Window* window, | 160 aura::Window* window, |
256 const void* key, | 161 const void* key, |
257 intptr_t old) { | 162 intptr_t old) { |
258 if (key == aura::client::kDrawAttentionKey) { | 163 if (key == aura::client::kDrawAttentionKey) { |
259 ash::ShelfItemStatus status; | 164 ash::ShelfItemStatus status; |
260 if (ash::wm::IsActiveWindow(window)) { | 165 if (ash::wm::IsActiveWindow(window)) { |
261 status = ash::STATUS_ACTIVE; | 166 status = ash::STATUS_ACTIVE; |
262 } else if (window->GetProperty(aura::client::kDrawAttentionKey)) { | 167 } else if (window->GetProperty(aura::client::kDrawAttentionKey)) { |
263 status = ash::STATUS_ATTENTION; | 168 status = ash::STATUS_ATTENTION; |
264 } else { | 169 } else { |
265 status = ash::STATUS_RUNNING; | 170 status = ash::STATUS_RUNNING; |
266 } | 171 } |
267 launcher_controller()->SetItemStatus(shelf_id(), status); | 172 launcher_controller()->SetItemStatus(shelf_id(), status); |
268 } | 173 } |
269 } | 174 } |
270 | 175 |
271 ash::ShelfItemDelegate::PerformedAction | 176 ash::ShelfItemDelegate::PerformedAction |
272 AppWindowLauncherItemController::ShowAndActivateOrMinimize( | 177 AppWindowLauncherItemController::ShowAndActivateOrMinimize( |
273 AppWindow* app_window) { | 178 ui::BaseWindow* app_window) { |
274 // Either show or minimize windows when shown from the launcher. | 179 // Either show or minimize windows when shown from the launcher. |
275 return launcher_controller()->ActivateWindowOrMinimizeIfActive( | 180 return launcher_controller()->ActivateWindowOrMinimizeIfActive( |
276 app_window->GetBaseWindow(), GetApplicationList(0).size() == 2); | 181 app_window, GetApplicationList(0).size() == 2); |
277 } | 182 } |
278 | 183 |
279 ash::ShelfItemDelegate::PerformedAction | 184 ash::ShelfItemDelegate::PerformedAction |
280 AppWindowLauncherItemController::ActivateOrAdvanceToNextAppWindow( | 185 AppWindowLauncherItemController::ActivateOrAdvanceToNextAppWindow( |
281 AppWindow* window_to_show) { | 186 ui::BaseWindow* window_to_show) { |
282 AppWindowList::iterator i( | 187 WindowList::iterator i( |
283 std::find(app_windows_.begin(), app_windows_.end(), window_to_show)); | 188 std::find(windows_.begin(), windows_.end(), window_to_show)); |
284 if (i != app_windows_.end()) { | 189 if (i != windows_.end()) { |
285 if (++i != app_windows_.end()) | 190 if (++i != windows_.end()) |
286 window_to_show = *i; | 191 window_to_show = *i; |
287 else | 192 else |
288 window_to_show = app_windows_.front(); | 193 window_to_show = windows_.front(); |
289 } | 194 } |
290 if (window_to_show->GetBaseWindow()->IsActive()) { | 195 if (window_to_show->IsActive()) { |
291 // Coming here, only a single window is active. For keyboard activations | 196 // Coming here, only a single window is active. For keyboard activations |
292 // the window gets animated. | 197 // the window gets animated. |
293 AnimateWindow(window_to_show->GetNativeWindow(), | 198 AnimateWindow(window_to_show->GetNativeWindow(), |
294 wm::WINDOW_ANIMATION_TYPE_BOUNCE); | 199 wm::WINDOW_ANIMATION_TYPE_BOUNCE); |
295 } else { | 200 } else { |
296 return ShowAndActivateOrMinimize(window_to_show); | 201 return ShowAndActivateOrMinimize(window_to_show); |
297 } | 202 } |
298 return kNoAction; | 203 return kNoAction; |
299 } | 204 } |
OLD | NEW |