| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/chrome_launcher_controller_impl.h" | 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1126 } | 1126 } |
| 1127 } | 1127 } |
| 1128 | 1128 |
| 1129 void ChromeLauncherControllerImpl::DoUnpinAppWithID(const std::string& app_id, | 1129 void ChromeLauncherControllerImpl::DoUnpinAppWithID(const std::string& app_id, |
| 1130 bool update_prefs) { | 1130 bool update_prefs) { |
| 1131 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); | 1131 ash::ShelfID shelf_id = GetShelfIDForAppID(app_id); |
| 1132 if (shelf_id && IsPinned(shelf_id)) | 1132 if (shelf_id && IsPinned(shelf_id)) |
| 1133 UnpinAndUpdatePrefs(shelf_id, update_prefs); | 1133 UnpinAndUpdatePrefs(shelf_id, update_prefs); |
| 1134 } | 1134 } |
| 1135 | 1135 |
| 1136 int ChromeLauncherControllerImpl::PinRunningAppInternal(int index, | 1136 void ChromeLauncherControllerImpl::PinRunningAppInternal( |
| 1137 ash::ShelfID shelf_id) { | 1137 int index, |
| 1138 ash::ShelfID shelf_id) { |
| 1138 int running_index = model_->ItemIndexByID(shelf_id); | 1139 int running_index = model_->ItemIndexByID(shelf_id); |
| 1139 ash::ShelfItem item = model_->items()[running_index]; | 1140 ash::ShelfItem item = model_->items()[running_index]; |
| 1140 DCHECK(item.type == ash::TYPE_WINDOWED_APP || | 1141 DCHECK(item.type == ash::TYPE_WINDOWED_APP || |
| 1141 item.type == ash::TYPE_PLATFORM_APP); | 1142 item.type == ash::TYPE_PLATFORM_APP); |
| 1142 item.type = ash::TYPE_APP_SHORTCUT; | 1143 item.type = ash::TYPE_APP_SHORTCUT; |
| 1143 model_->Set(running_index, item); | 1144 model_->Set(running_index, item); |
| 1144 // The |ShelfModel|'s weight system might reposition the item to a | 1145 // The |ShelfModel|'s weight system might reposition the item to a |
| 1145 // new index, so we get the index again. | 1146 // new index, so we get the index again. |
| 1146 running_index = model_->ItemIndexByID(shelf_id); | 1147 running_index = model_->ItemIndexByID(shelf_id); |
| 1147 if (running_index < index) | 1148 if (running_index < index) |
| 1148 --index; | 1149 --index; |
| 1149 if (running_index != index) | 1150 if (running_index != index) |
| 1150 model_->Move(running_index, index); | 1151 model_->Move(running_index, index); |
| 1151 return index; | |
| 1152 } | 1152 } |
| 1153 | 1153 |
| 1154 void ChromeLauncherControllerImpl::UnpinRunningAppInternal(int index) { | 1154 void ChromeLauncherControllerImpl::UnpinRunningAppInternal(int index) { |
| 1155 DCHECK_GE(index, 0); | 1155 DCHECK_GE(index, 0); |
| 1156 ash::ShelfItem item = model_->items()[index]; | 1156 ash::ShelfItem item = model_->items()[index]; |
| 1157 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); | 1157 DCHECK_EQ(item.type, ash::TYPE_APP_SHORTCUT); |
| 1158 item.type = ash::TYPE_WINDOWED_APP; | 1158 item.type = ash::TYPE_WINDOWED_APP; |
| 1159 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such | 1159 // A platform app and a windowed app are sharing TYPE_APP_SHORTCUT. As such |
| 1160 // we have to check here what this was before it got a shortcut. | 1160 // we have to check here what this was before it got a shortcut. |
| 1161 LauncherItemController* controller = GetLauncherItemController(item.id); | 1161 LauncherItemController* controller = GetLauncherItemController(item.id); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1213 | 1213 |
| 1214 void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() { | 1214 void ChromeLauncherControllerImpl::UpdateAppLaunchersFromPref() { |
| 1215 // There are various functions which will trigger a |SyncPinPosition| call | 1215 // There are various functions which will trigger a |SyncPinPosition| call |
| 1216 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu | 1216 // like a direct call to |DoPinAppWithID|, or an indirect call to the menu |
| 1217 // model which will use weights to re-arrange the icons to new positions. | 1217 // model which will use weights to re-arrange the icons to new positions. |
| 1218 // Since this function is meant to synchronize the "is state" with the | 1218 // Since this function is meant to synchronize the "is state" with the |
| 1219 // "sync state", it makes no sense to store any changes by this function back | 1219 // "sync state", it makes no sense to store any changes by this function back |
| 1220 // into the pref state. Therefore we tell |persistPinnedState| to ignore any | 1220 // into the pref state. Therefore we tell |persistPinnedState| to ignore any |
| 1221 // invocations while we are running. | 1221 // invocations while we are running. |
| 1222 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); | 1222 base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true); |
| 1223 std::vector<std::string> pinned_apps = ash::launcher::GetPinnedAppsFromPrefs( | 1223 const std::vector<std::string> pinned_apps = |
| 1224 profile_->GetPrefs(), launcher_controller_helper_.get()); | 1224 ash::launcher::GetPinnedAppsFromPrefs(profile_->GetPrefs(), |
| 1225 launcher_controller_helper_.get()); |
| 1225 | 1226 |
| 1226 int index = 0; | 1227 int index = 0; |
| 1227 int max_index = model_->item_count(); | |
| 1228 int seen_chrome_index = -1; | |
| 1229 | |
| 1230 // At least chrome browser shortcut should exist. | |
| 1231 DCHECK_GT(max_index, 0); | |
| 1232 | |
| 1233 // Skip app list items if it exists. | 1228 // Skip app list items if it exists. |
| 1234 if (model_->items()[0].type == ash::TYPE_APP_LIST) | 1229 if (model_->items()[0].type == ash::TYPE_APP_LIST) |
| 1235 ++index; | 1230 ++index; |
| 1236 | 1231 |
| 1237 // Walk the model and |pinned_apps| from the pref lockstep, adding and | 1232 // Apply pins in two steps. At the first step, go through the list of apps to |
| 1238 // removing items as necessary. NB: This code uses plain old indexing instead | 1233 // pin, move existing pin to current position specified by |index| or create |
| 1239 // of iterators because of model mutations as part of the loop. | 1234 // the new pin at that position. |
| 1240 std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin()); | 1235 for (const auto& pref_app_id : pinned_apps) { |
| 1241 for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) { | 1236 // Filter out apps that may be mapped wrongly. |
| 1237 // TODO(khmel): b/31703859 is to refactore shelf mapping. |
| 1238 const std::string shelf_app_id = |
| 1239 ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(pref_app_id); |
| 1240 if (shelf_app_id != pref_app_id) |
| 1241 continue; |
| 1242 |
| 1242 // Update apps icon if applicable. | 1243 // Update apps icon if applicable. |
| 1243 OnAppUpdated(profile_, *pref_app_id); | 1244 OnAppUpdated(profile_, pref_app_id); |
| 1244 // Check if we have an item which we need to handle. | 1245 |
| 1245 if (IsAppPinned(*pref_app_id)) { | 1246 // Find existing pin or app from the right of current |index|. |
| 1246 if (seen_chrome_index >= 0 && | 1247 int app_index = index; |
| 1247 *pref_app_id == extension_misc::kChromeAppId) { | 1248 for (; app_index < model_->item_count(); ++app_index) { |
| 1248 // Current item is Chrome browser and we saw it before. | 1249 const ash::ShelfItem& item = model_->items()[app_index]; |
| 1249 model_->Move(seen_chrome_index, index); | 1250 const IDToItemControllerMap::iterator it = |
| 1250 ++pref_app_id; | 1251 id_to_item_controller_map_.find(item.id); |
| 1251 --index; | 1252 if (it != id_to_item_controller_map_.end() && |
| 1252 continue; | 1253 it->second->app_id() == pref_app_id) { |
| 1254 break; |
| 1253 } | 1255 } |
| 1254 for (; index < max_index; ++index) { | 1256 } |
| 1255 const ash::ShelfItem& item(model_->items()[index]); | 1257 if (app_index < model_->item_count()) { |
| 1256 if (item.type != ash::TYPE_APP_SHORTCUT && | 1258 // Found existing pin or running app. |
| 1257 item.type != ash::TYPE_BROWSER_SHORTCUT) { | 1259 const ash::ShelfItem item = model_->items()[app_index]; |
| 1258 continue; | 1260 if (item.type == ash::TYPE_APP_SHORTCUT || |
| 1259 } | 1261 item.type == ash::TYPE_BROWSER_SHORTCUT) { |
| 1260 LauncherItemController* controller = GetLauncherItemController(item.id); | 1262 // Just move to required position or keep it inplace. |
| 1261 if (controller && controller->app_id() == *pref_app_id) { | 1263 model_->Move(app_index, index); |
| 1262 ++pref_app_id; | 1264 } else { |
| 1263 break; | 1265 PinRunningAppInternal(index, item.id); |
| 1264 } else if (item.type == ash::TYPE_BROWSER_SHORTCUT) { | |
| 1265 // We cannot close browser shortcut. Remember its position. | |
| 1266 seen_chrome_index = index; | |
| 1267 } else { | |
| 1268 // Check if this is a platform or a windowed app. | |
| 1269 if (item.type == ash::TYPE_APP_SHORTCUT && controller && | |
| 1270 (controller->locked() || | |
| 1271 controller->type() == LauncherItemController::TYPE_APP)) { | |
| 1272 // Note: This will not change the amount of items (|max_index|). | |
| 1273 // Even changes to the actual |index| due to item weighting | |
| 1274 // changes should be fine. | |
| 1275 UnpinRunningAppInternal(index); | |
| 1276 } else { | |
| 1277 if (controller) | |
| 1278 LauncherItemClosed(item.id); | |
| 1279 --max_index; | |
| 1280 } | |
| 1281 --index; | |
| 1282 } | |
| 1283 } | 1266 } |
| 1284 // If the item wasn't found, that means id_to_item_controller_map_ | 1267 DCHECK_EQ(model_->ItemIndexByID(item.id), index); |
| 1285 // is out of sync. | |
| 1286 DCHECK(index <= max_index); | |
| 1287 } else { | 1268 } else { |
| 1288 // Check if the item was already running but not yet pinned. | 1269 // This is fresh pin. Create new one. |
| 1289 ash::ShelfID shelf_id = GetShelfIDForAppID(*pref_app_id); | 1270 DCHECK_NE(pref_app_id, extension_misc::kChromeAppId); |
| 1290 if (shelf_id) { | 1271 CreateAppShortcutLauncherItem(pref_app_id, index); |
| 1291 // This app is running but not yet pinned. So pin and move it. | |
| 1292 index = PinRunningAppInternal(index, shelf_id); | |
| 1293 } else { | |
| 1294 // This app wasn't pinned before, insert a new entry. | |
| 1295 shelf_id = CreateAppShortcutLauncherItem(*pref_app_id, index); | |
| 1296 ++max_index; | |
| 1297 index = model_->ItemIndexByID(shelf_id); | |
| 1298 } | |
| 1299 ++pref_app_id; | |
| 1300 } | 1272 } |
| 1273 ++index; |
| 1301 } | 1274 } |
| 1302 | 1275 |
| 1303 // Remove any trailing existing items. | 1276 // At second step remove any pin to the right from the current index. |
| 1304 while (index < model_->item_count()) { | 1277 while (index < model_->item_count()) { |
| 1305 const ash::ShelfItem& item(model_->items()[index]); | 1278 const ash::ShelfItem item = model_->items()[index]; |
| 1306 if (item.type == ash::TYPE_APP_SHORTCUT) { | 1279 if (item.type != ash::TYPE_APP_SHORTCUT) { |
| 1307 LauncherItemController* controller = GetLauncherItemController(item.id); | 1280 ++index; |
| 1308 if (controller) { | 1281 continue; |
| 1309 if (controller->locked() || | 1282 } |
| 1310 controller->type() == LauncherItemController::TYPE_APP) { | 1283 |
| 1311 UnpinRunningAppInternal(index); | 1284 const LauncherItemController* controller = |
| 1312 } else { | 1285 GetLauncherItemController(item.id); |
| 1313 LauncherItemClosed(item.id); | 1286 DCHECK(controller); |
| 1314 } | 1287 DCHECK_NE(controller->app_id(), extension_misc::kChromeAppId); |
| 1315 } | 1288 |
| 1289 if (controller->locked() || |
| 1290 controller->type() == LauncherItemController::TYPE_APP) { |
| 1291 UnpinRunningAppInternal(index); |
| 1292 // Note, item can be moved to the right due weighting in shelf model. |
| 1293 DCHECK_GE(model_->ItemIndexByID(item.id), index); |
| 1316 } else { | 1294 } else { |
| 1317 ++index; | 1295 LauncherItemClosed(item.id); |
| 1318 } | |
| 1319 } | |
| 1320 | |
| 1321 // Append unprocessed items from the pref to the end of the model. | |
| 1322 for (; pref_app_id != pinned_apps.end(); ++pref_app_id) { | |
| 1323 // Update apps icon if applicable. | |
| 1324 OnAppUpdated(profile_, *pref_app_id); | |
| 1325 if (*pref_app_id == extension_misc::kChromeAppId) { | |
| 1326 int target_index = FindInsertionPoint(); | |
| 1327 DCHECK(seen_chrome_index >= 0 && seen_chrome_index < target_index); | |
| 1328 model_->Move(seen_chrome_index, target_index); | |
| 1329 } else { | |
| 1330 DoPinAppWithID(*pref_app_id); | |
| 1331 int target_index = FindInsertionPoint(); | |
| 1332 ash::ShelfID id = GetShelfIDForAppID(*pref_app_id); | |
| 1333 int source_index = model_->ItemIndexByID(id); | |
| 1334 if (source_index != target_index) | |
| 1335 model_->Move(source_index, target_index); | |
| 1336 } | 1296 } |
| 1337 } | 1297 } |
| 1338 } | 1298 } |
| 1339 | 1299 |
| 1340 void ChromeLauncherControllerImpl::SetShelfAutoHideBehaviorFromPrefs() { | 1300 void ChromeLauncherControllerImpl::SetShelfAutoHideBehaviorFromPrefs() { |
| 1341 for (ash::WmWindow* window : ash::WmShell::Get()->GetAllRootWindows()) { | 1301 for (ash::WmWindow* window : ash::WmShell::Get()->GetAllRootWindows()) { |
| 1342 ash::WmShelf* shelf = ash::WmShelf::ForWindow(window); | 1302 ash::WmShelf* shelf = ash::WmShelf::ForWindow(window); |
| 1343 // TODO(jamescook): This check should not be necessary, but otherwise this | 1303 // TODO(jamescook): This check should not be necessary, but otherwise this |
| 1344 // tries to set autohide state on a secondary display during login before | 1304 // tries to set autohide state on a secondary display during login before |
| 1345 // the ShelfView is created, which is not allowed. | 1305 // the ShelfView is created, which is not allowed. |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1719 if (index == -1) | 1679 if (index == -1) |
| 1720 continue; | 1680 continue; |
| 1721 ash::ShelfItem item = model_->items()[index]; | 1681 ash::ShelfItem item = model_->items()[index]; |
| 1722 item.image = image; | 1682 item.image = image; |
| 1723 if (arc_deferred_launcher_) | 1683 if (arc_deferred_launcher_) |
| 1724 arc_deferred_launcher_->MaybeApplySpinningEffect(id, &item.image); | 1684 arc_deferred_launcher_->MaybeApplySpinningEffect(id, &item.image); |
| 1725 model_->Set(index, item); | 1685 model_->Set(index, item); |
| 1726 // It's possible we're waiting on more than one item, so don't break. | 1686 // It's possible we're waiting on more than one item, so don't break. |
| 1727 } | 1687 } |
| 1728 } | 1688 } |
| OLD | NEW |