Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Side by Side Diff: chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.cc

Issue 1823923002: arc: Support running Arc app in shelf (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update unit_test Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698