From cae95210719c7d520afcf1b5c6f088d776c974d2 Mon Sep 17 00:00:00 2001 From: Matt Garnes Date: Fri, 19 Jun 2015 13:11:08 -0700 Subject: Fix unintended dynamic grid resize side effects. - Do not attempt to resize the grid unless the dynamic grid resize has been explicitly triggered. - Workspace Ids are 1 indexed not 0, so on resize, start at 1. - After resizing the grid, persist the changes to the DB. The initial implementation only did the resize in memory and did not persist this, causing side effects later. Bugs fixed: 1. Resize the dynamic grid from large to small. Add a new icon by installing a new app or adding a shortcut from file manager. The new icon will overlap one on one of the new pages. 2. Resize the grid from large to small in a previous version of trebuchet (before the grid resize feature was added). Icons on the outer edges of the grid will be lost but persist in the DB. Upgrade to a new version of Trebuchet. The icons will return to the workspace. Change-Id: I8b0defafb3299d1f3d534526a75f9253495d739d --- src/com/android/launcher3/Launcher.java | 22 ++++++---- src/com/android/launcher3/LauncherModel.java | 50 +++++++++++++++++++--- .../list/SettingsPinnedHeaderAdapter.java | 10 ++--- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 813d091df..682758909 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -337,6 +337,7 @@ public class Launcher extends Activity private boolean mWorkspaceLoading = true; private boolean mDynamicGridUpdateRequired = false; + private boolean mDynamicGridResizeRequired = false; private boolean mPaused = true; private boolean mRestoring; @@ -457,7 +458,7 @@ public class Launcher extends Activity Runnable mUpdateDynamicGridRunnable = new Runnable() { @Override public void run() { - updateDynamicGrid(); + updateDynamicGrid(false); } }; @@ -469,7 +470,7 @@ public class Launcher extends Activity return; } - updateDynamicGrid(); + updateDynamicGrid(false); } }; @@ -1323,7 +1324,7 @@ public class Launcher extends Activity SettingsProvider.putInt(this, SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, size.getValue()); - setUpdateDynamicGrid(); + setUpdateDynamicGrid(true); } mOverviewSettingsPanel.notifyDataSetInvalidated(); @@ -5862,11 +5863,11 @@ public class Launcher extends Activity return effect == null ? TransitionEffect.TRANSITION_EFFECT_NONE : effect.getName(); } - public void updateDynamicGrid() { - updateDynamicGrid(mWorkspace.getRestorePage()); + public void updateDynamicGrid(boolean resizeGridIfNeeded) { + updateDynamicGrid(mWorkspace.getRestorePage(), resizeGridIfNeeded); } - public void updateDynamicGrid(int page) { + public void updateDynamicGrid(int page, boolean resizeGridIfNeeded) { mSearchDropTargetBar.setupQSB(Launcher.this); initializeDynamicGrid(true); @@ -5875,19 +5876,22 @@ public class Launcher extends Activity // Synchronized reload mModel.resetLoadedState(true, true); - mModel.startLoader(true, page); + int flag = resizeGridIfNeeded ? LauncherModel.LOADER_FLAG_RESIZE_GRID : + LauncherModel.LOADER_FLAG_NONE; + mModel.startLoader(true, page, flag); mWorkspace.updateCustomContentVisibility(); mAppDrawerAdapter.reset(); } - public void setUpdateDynamicGrid() { + public void setUpdateDynamicGrid(boolean resizeDynamicGrid) { mDynamicGridUpdateRequired = true; + mDynamicGridResizeRequired = resizeDynamicGrid; } public boolean updateGridIfNeeded() { if (mDynamicGridUpdateRequired) { - updateDynamicGrid(mWorkspace.getCurrentPage()); + updateDynamicGrid(mWorkspace.getCurrentPage(), mDynamicGridResizeRequired); mDynamicGridUpdateRequired = false; return true; } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index f67e828aa..fbacc3937 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -100,6 +100,7 @@ public class LauncherModel extends BroadcastReceiver public static final int LOADER_FLAG_NONE = 0; public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0; public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1; + public static final int LOADER_FLAG_RESIZE_GRID = 1 << 2; private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons private static final long INVALID_SCREEN_ID = -1L; @@ -1857,7 +1858,8 @@ public class LauncherModel extends BroadcastReceiver // check & update map of what's occupied; used to discard overlapping/invalid items private boolean checkItemPlacement(HashMap occupied, ItemInfo item, - AtomicBoolean deleteOnInvalidPlacement) { + AtomicBoolean deleteOnInvalidPlacement, + boolean shouldResizeAndUpdateDB) { LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); final int countX = (int) grid.numColumns; @@ -1914,12 +1916,21 @@ public class LauncherModel extends BroadcastReceiver // available position. if (item.cellX < 0 || item.cellY < 0 || item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) { + // If we won't be resizing the grid, then just return, this item does not fit. + if (!shouldResizeAndUpdateDB) { + Log.e(TAG, "Error loading shortcut " + item + + " into cell (" + containerIndex + "-" + item.screenId + ":" + + item.cellX + "," + item.cellY + + ") out of screen bounds ( " + countX + "x" + countY + ")"); + return false; + } + if (item.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) { - // Place the item at 0 0 of screen 0 + // Place the item at 0 0 of screen 1 // if items overlap here, they will be moved later on item.cellX = 0; item.cellY = 0; - item.screenId = 0; + item.screenId = 1; item.wasMovedDueToReducedSpace = true; item.requiresDbUpdate = true; } else { @@ -1961,6 +1972,16 @@ public class LauncherModel extends BroadcastReceiver // Check if any workspace icons overlap with each other for (int x = item.cellX; x < (item.cellX + item.spanX); x++) { for (int y = item.cellY; y < (item.cellY + item.spanY); y++) { + // If we are not resizing the grid, overlapping items should be rejected. + if (!shouldResizeAndUpdateDB && screens[x][y] != null) { + Log.e(TAG, "Error loading shortcut " + item + + " into cell (" + containerIndex + "-" + item.screenId + ":" + + x + "," + y + + ") occupied by " + + screens[x][y]); + return false; + } + if (screens[x][y] != null) { ItemInfo occupiedItem = screens[x][y]; // If an item is overlapping another because one of them @@ -2008,7 +2029,8 @@ public class LauncherModel extends BroadcastReceiver for (int x = item.cellX; x < (item.cellX + item.spanX); x++) { for (int y = item.cellY; y < (item.cellY + item.spanY); y++) { screens[x][y] = item; - if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) { + if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET + && shouldResizeAndUpdateDB) { // fill up the entire grid where the widget technically is for (int spanX = x; spanX < item.spanX; spanX++) { screens[spanX][y] = item; @@ -2056,6 +2078,8 @@ public class LauncherModel extends BroadcastReceiver int countX = (int) grid.numColumns; int countY = (int) grid.numRows; + boolean shouldResize = ((mFlags & LOADER_FLAG_RESIZE_GRID) != 0); + if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) { Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true); LauncherAppState.getLauncherProvider().deleteDatabase(); @@ -2320,7 +2344,8 @@ public class LauncherModel extends BroadcastReceiver // check & update map of what's occupied deleteOnInvalidPlacement.set(false); - if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) { + if (!checkItemPlacement(occupied, info, + deleteOnInvalidPlacement, shouldResize)) { if (deleteOnInvalidPlacement.get()) { itemsToRemove.add(id); } @@ -2367,7 +2392,7 @@ public class LauncherModel extends BroadcastReceiver // check & update map of what's occupied deleteOnInvalidPlacement.set(false); if (!checkItemPlacement(occupied, folderInfo, - deleteOnInvalidPlacement)) { + deleteOnInvalidPlacement, shouldResize)) { if (deleteOnInvalidPlacement.get()) { itemsToRemove.add(id); } @@ -2480,7 +2505,7 @@ public class LauncherModel extends BroadcastReceiver // check & update map of what's occupied deleteOnInvalidPlacement.set(false); if (!checkItemPlacement(occupied, appWidgetInfo, - deleteOnInvalidPlacement)) { + deleteOnInvalidPlacement, shouldResize)) { if (deleteOnInvalidPlacement.get()) { itemsToRemove.add(id); } @@ -2619,6 +2644,17 @@ public class LauncherModel extends BroadcastReceiver updateWorkspaceScreenOrder(context, sBgWorkspaceScreens); } + // If any items have been shifted and require a DB update, update them in the DB. + if (shouldResize) { + for (ItemInfo info : sBgWorkspaceItems) { + if (info != null && info.requiresDbUpdate) { + info.requiresDbUpdate = false; + LauncherModel.modifyItemInDatabase(mContext, info, info.container, + info.screenId, info.cellX, info.cellY, info.spanX, info.spanY); + } + } + } + if (DEBUG_LOADERS) { Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms"); Log.d(TAG, "workspace layout: "); diff --git a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java index 9882c7625..df9a1f05b 100644 --- a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java +++ b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java @@ -288,7 +288,7 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { switch (position) { case 0: updateSearchBarVisibility(v); - mLauncher.setUpdateDynamicGrid(); + mLauncher.setUpdateDynamicGrid(false); break; case 1: mLauncher.onClickTransitionEffectButton(v, false); @@ -297,13 +297,13 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { onIconLabelsBooleanChanged(v, SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS, R.bool.preferences_interface_homescreen_hide_icon_labels_default); - mLauncher.setUpdateDynamicGrid(); + mLauncher.setUpdateDynamicGrid(false); break; case 3: onSettingsBooleanChanged(v, SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL, R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default); - mLauncher.setUpdateDynamicGrid(); + mLauncher.setUpdateDynamicGrid(false); break; case 4: mLauncher.onClickDynamicGridSizeButton(); @@ -328,7 +328,7 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { onIconLabelsBooleanChanged(v, SettingsProvider.SETTINGS_UI_DRAWER_HIDE_ICON_LABELS, R.bool.preferences_interface_drawer_hide_icon_labels_default); - mLauncher.setUpdateDynamicGrid(); + mLauncher.setUpdateDynamicGrid(false); break; } break; @@ -338,7 +338,7 @@ public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { onSettingsBooleanChanged(v, SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE, R.bool.preferences_interface_general_icons_large_default); - mLauncher.setUpdateDynamicGrid(); + mLauncher.setUpdateDynamicGrid(false); break; case 1: Intent intent = new Intent(); -- cgit v1.2.3