Search in sources :

Example 41 with Hotseat

use of com.android.launcher3.Hotseat in project android_packages_apps_Trebuchet by LineageOS.

the class LoaderCursor method checkItemPlacement.

/**
 * check & update map of what's occupied; used to discard overlapping/invalid items
 */
protected boolean checkItemPlacement(ItemInfo item) {
    int containerIndex = item.screenId;
    if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
        final GridOccupancy hotseatOccupancy = occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT);
        if (item.screenId >= mIDP.numHotseatIcons) {
            Log.e(TAG, "Error loading shortcut " + item + " into hotseat position " + item.screenId + ", position out of bounds: (0 to " + (mIDP.numHotseatIcons - 1) + ")");
            return false;
        }
        if (hotseatOccupancy != null) {
            if (hotseatOccupancy.cells[(int) item.screenId][0]) {
                Log.e(TAG, "Error loading shortcut into hotseat " + item + " into position (" + item.screenId + ":" + item.cellX + "," + item.cellY + ") already occupied");
                return false;
            } else {
                hotseatOccupancy.cells[item.screenId][0] = true;
                return true;
            }
        } else {
            final GridOccupancy occupancy = new GridOccupancy(mIDP.numHotseatIcons, 1);
            occupancy.cells[item.screenId][0] = true;
            occupied.put(LauncherSettings.Favorites.CONTAINER_HOTSEAT, occupancy);
            return true;
        }
    } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
        // Skip further checking if it is not the hotseat or workspace container
        return true;
    }
    final int countX = mIDP.numColumns;
    final int countY = mIDP.numRows;
    if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP && item.cellX < 0 || item.cellY < 0 || item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
        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 (!occupied.containsKey(item.screenId)) {
        GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1);
        if (item.screenId == Workspace.FIRST_SCREEN_ID) {
            // Mark the first row as occupied (if the feature is enabled)
            // in order to account for the QSB.
            screen.markCells(0, 0, countX + 1, 1, FeatureFlags.QSB_ON_FIRST_SCREEN);
        }
        occupied.put(item.screenId, screen);
    }
    final GridOccupancy occupancy = occupied.get(item.screenId);
    // Check if any workspace icons overlap with each other
    if (occupancy.isRegionVacant(item.cellX, item.cellY, item.spanX, item.spanY)) {
        occupancy.markCells(item, true);
        return true;
    } else {
        Log.e(TAG, "Error loading shortcut " + item + " into cell (" + containerIndex + "-" + item.screenId + ":" + item.cellX + "," + item.cellX + "," + item.spanX + "," + item.spanY + ") already occupied");
        return false;
    }
}
Also used : GridOccupancy(com.android.launcher3.util.GridOccupancy)

Example 42 with Hotseat

use of com.android.launcher3.Hotseat in project android_packages_apps_Trebuchet by LineageOS.

the class ImportDataTask method importWorkspaceItems.

/**
 * 1) Imports all the workspace entries from the source provider.
 * 2) For home screen entries, maps the screen id based on {@param screenIdMap}
 * 3) In the end fills any holes in hotseat with items from default hotseat layout.
 */
private void importWorkspaceItems() throws Exception {
    String profileId = Long.toString(UserCache.INSTANCE.get(mContext).getSerialNumberForUser(Process.myUserHandle()));
    boolean createEmptyRowOnFirstScreen;
    if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
        try (Cursor c = mContext.getContentResolver().query(mOtherFavoritesUri, null, // get items on the first row of the first screen (min screen id)
        "profileId = ? AND container = -100 AND cellY = 0 AND screen = " + "(SELECT MIN(screen) FROM favorites WHERE container = -100)", new String[] { profileId }, null)) {
            // First row of first screen is not empty
            createEmptyRowOnFirstScreen = c.moveToNext();
        }
    } else {
        createEmptyRowOnFirstScreen = false;
    }
    ArrayList<ContentProviderOperation> insertOperations = new ArrayList<>(BATCH_INSERT_SIZE);
    // Set of package names present in hotseat
    final HashSet<String> hotseatTargetApps = new HashSet<>();
    int maxId = 0;
    // Number of imported items on workspace and hotseat
    int totalItemsOnWorkspace = 0;
    try (Cursor c = mContext.getContentResolver().query(mOtherFavoritesUri, null, // Only migrate the primary user
    Favorites.PROFILE_ID + " = ?", new String[] { profileId }, // before the corresponding items.
    Favorites.CONTAINER + " , " + Favorites.SCREEN)) {
        // various columns we expect to exist.
        final int idIndex = c.getColumnIndexOrThrow(Favorites._ID);
        final int intentIndex = c.getColumnIndexOrThrow(Favorites.INTENT);
        final int titleIndex = c.getColumnIndexOrThrow(Favorites.TITLE);
        final int containerIndex = c.getColumnIndexOrThrow(Favorites.CONTAINER);
        final int itemTypeIndex = c.getColumnIndexOrThrow(Favorites.ITEM_TYPE);
        final int widgetProviderIndex = c.getColumnIndexOrThrow(Favorites.APPWIDGET_PROVIDER);
        final int screenIndex = c.getColumnIndexOrThrow(Favorites.SCREEN);
        final int cellXIndex = c.getColumnIndexOrThrow(Favorites.CELLX);
        final int cellYIndex = c.getColumnIndexOrThrow(Favorites.CELLY);
        final int spanXIndex = c.getColumnIndexOrThrow(Favorites.SPANX);
        final int spanYIndex = c.getColumnIndexOrThrow(Favorites.SPANY);
        final int rankIndex = c.getColumnIndexOrThrow(Favorites.RANK);
        final int iconIndex = c.getColumnIndexOrThrow(Favorites.ICON);
        final int iconPackageIndex = c.getColumnIndexOrThrow(Favorites.ICON_PACKAGE);
        final int iconResourceIndex = c.getColumnIndexOrThrow(Favorites.ICON_RESOURCE);
        SparseBooleanArray mValidFolders = new SparseBooleanArray();
        ContentValues values = new ContentValues();
        Integer firstScreenId = null;
        while (c.moveToNext()) {
            values.clear();
            int id = c.getInt(idIndex);
            maxId = Math.max(maxId, id);
            int type = c.getInt(itemTypeIndex);
            int container = c.getInt(containerIndex);
            int screen = c.getInt(screenIndex);
            int cellX = c.getInt(cellXIndex);
            int cellY = c.getInt(cellYIndex);
            int spanX = c.getInt(spanXIndex);
            int spanY = c.getInt(spanYIndex);
            switch(container) {
                case Favorites.CONTAINER_DESKTOP:
                    {
                        if (screen < Workspace.FIRST_SCREEN_ID) {
                            FileLog.d(TAG, String.format("Skipping item %d, type %d not on a valid screen %d", id, type, screen));
                            continue;
                        }
                        if (firstScreenId == null) {
                            firstScreenId = screen;
                        }
                        // Reset the screen to 0-index value
                        if (createEmptyRowOnFirstScreen && firstScreenId.equals(screen)) {
                            // Shift items by 1.
                            cellY++;
                            // Change the screen id to first screen
                            screen = Workspace.FIRST_SCREEN_ID;
                        }
                        mMaxGridSizeX = Math.max(mMaxGridSizeX, cellX + spanX);
                        mMaxGridSizeY = Math.max(mMaxGridSizeY, cellY + spanY);
                        break;
                    }
                case Favorites.CONTAINER_HOTSEAT:
                    {
                        mHotseatSize = Math.max(mHotseatSize, screen + 1);
                        break;
                    }
                default:
                    if (!mValidFolders.get(container)) {
                        FileLog.d(TAG, String.format("Skipping item %d, type %d not in a valid folder %d", id, type, container));
                        continue;
                    }
            }
            Intent intent = null;
            switch(type) {
                case Favorites.ITEM_TYPE_FOLDER:
                    {
                        mValidFolders.put(id, true);
                        // Use a empty intent to indicate a folder.
                        intent = new Intent();
                        break;
                    }
                case Favorites.ITEM_TYPE_APPWIDGET:
                    {
                        values.put(Favorites.RESTORED, LauncherAppWidgetInfo.FLAG_ID_NOT_VALID | LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY | LauncherAppWidgetInfo.FLAG_UI_NOT_READY);
                        values.put(Favorites.APPWIDGET_PROVIDER, c.getString(widgetProviderIndex));
                        break;
                    }
                case Favorites.ITEM_TYPE_SHORTCUT:
                case Favorites.ITEM_TYPE_APPLICATION:
                    {
                        intent = Intent.parseUri(c.getString(intentIndex), 0);
                        if (PackageManagerHelper.isLauncherAppTarget(intent)) {
                            type = Favorites.ITEM_TYPE_APPLICATION;
                        } else {
                            values.put(Favorites.ICON_PACKAGE, c.getString(iconPackageIndex));
                            values.put(Favorites.ICON_RESOURCE, c.getString(iconResourceIndex));
                        }
                        values.put(Favorites.ICON, c.getBlob(iconIndex));
                        values.put(Favorites.INTENT, intent.toUri(0));
                        values.put(Favorites.RANK, c.getInt(rankIndex));
                        values.put(Favorites.RESTORED, 1);
                        break;
                    }
                default:
                    FileLog.d(TAG, String.format("Skipping item %d, not a valid type %d", id, type));
                    continue;
            }
            if (container == Favorites.CONTAINER_HOTSEAT) {
                if (intent == null) {
                    FileLog.d(TAG, String.format("Skipping item %d, null intent on hotseat", id));
                    continue;
                }
                if (intent.getComponent() != null) {
                    intent.setPackage(intent.getComponent().getPackageName());
                }
                hotseatTargetApps.add(getPackage(intent));
            }
            values.put(Favorites._ID, id);
            values.put(Favorites.ITEM_TYPE, type);
            values.put(Favorites.CONTAINER, container);
            values.put(Favorites.SCREEN, screen);
            values.put(Favorites.CELLX, cellX);
            values.put(Favorites.CELLY, cellY);
            values.put(Favorites.SPANX, spanX);
            values.put(Favorites.SPANY, spanY);
            values.put(Favorites.TITLE, c.getString(titleIndex));
            insertOperations.add(ContentProviderOperation.newInsert(Favorites.CONTENT_URI).withValues(values).build());
            if (container < 0) {
                totalItemsOnWorkspace++;
            }
            if (insertOperations.size() >= BATCH_INSERT_SIZE) {
                mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, insertOperations);
                insertOperations.clear();
            }
        }
    }
    FileLog.d(TAG, totalItemsOnWorkspace + " items imported from external source");
    if (totalItemsOnWorkspace < MIN_ITEM_COUNT_FOR_SUCCESSFUL_MIGRATION) {
        throw new Exception("Insufficient data");
    }
    if (!insertOperations.isEmpty()) {
        mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, insertOperations);
        insertOperations.clear();
    }
    IntSparseArrayMap<Object> hotseatItems = GridSizeMigrationTask.removeBrokenHotseatItems(mContext);
    int myHotseatCount = LauncherAppState.getIDP(mContext).numHotseatIcons;
    if (hotseatItems.size() < myHotseatCount) {
        // Insufficient hotseat items. Add a few more.
        HotseatParserCallback parserCallback = new HotseatParserCallback(hotseatTargetApps, hotseatItems, insertOperations, maxId + 1, myHotseatCount);
        new HotseatLayoutParser(mContext, parserCallback).loadLayout(null, new IntArray());
        mHotseatSize = hotseatItems.keyAt(hotseatItems.size() - 1) + 1;
        if (!insertOperations.isEmpty()) {
            mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, insertOperations);
        }
    }
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) Intent(android.content.Intent) Cursor(android.database.Cursor) URISyntaxException(java.net.URISyntaxException) IntArray(com.android.launcher3.util.IntArray) SparseBooleanArray(android.util.SparseBooleanArray) HashSet(java.util.HashSet)

Example 43 with Hotseat

use of com.android.launcher3.Hotseat in project android_packages_apps_Trebuchet by LineageOS.

the class GridSizeMigrationTask method migrateHotseat.

/**
 * To migrate hotseat, we load all the entries in order (LTR or RTL) and arrange them
 * in the order in the new hotseat while keeping an empty space for all-apps. If the number of
 * entries is more than what can fit in the new hotseat, we drop the entries with least weight.
 * For weight calculation {@see #WT_SHORTCUT}, {@see #WT_APPLICATION}
 * & {@see #WT_FOLDER_FACTOR}.
 *
 * @return true if any DB change was made
 */
protected boolean migrateHotseat() throws Exception {
    ArrayList<DbEntry> items = loadHotseatEntries();
    while (items.size() > mDestHotseatSize) {
        // Pick the center item by default.
        DbEntry toRemove = items.get(items.size() / 2);
        // Find the item with least weight.
        for (DbEntry entry : items) {
            if (entry.weight < toRemove.weight) {
                toRemove = entry;
            }
        }
        mEntryToRemove.add(toRemove.id);
        items.remove(toRemove);
    }
    // Update screen IDS
    int newScreenId = 0;
    for (DbEntry entry : items) {
        if (entry.screenId != newScreenId) {
            entry.screenId = newScreenId;
            // These values does not affect the item position, but we should set them
            // to something other than -1.
            entry.cellX = newScreenId;
            entry.cellY = 0;
            update(entry);
        }
        newScreenId++;
    }
    return applyOperations();
}
Also used : Utilities.parsePoint(com.android.launcher3.Utilities.parsePoint) Point(android.graphics.Point)

Example 44 with Hotseat

use of com.android.launcher3.Hotseat in project android_packages_apps_Trebuchet by LineageOS.

the class GridSizeMigrationTask method migrateGridIfNeeded.

/**
 * Run the migration algorithm if needed. For preview, we provide the intended idp because it
 * has not been changed. If idp is null, we read it from the context, for actual grid migration.
 *
 * @return false if the migration failed.
 */
public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
    boolean migrateForPreview = idp != null;
    if (!migrateForPreview) {
        idp = LauncherAppState.getIDP(context);
    }
    if (!needsToMigrate(context, idp)) {
        return true;
    }
    SharedPreferences prefs = Utilities.getPrefs(context);
    String gridSizeString = getPointString(idp.numColumns, idp.numRows);
    long migrationStartTime = SystemClock.elapsedRealtime();
    try (SQLiteTransaction transaction = (SQLiteTransaction) Settings.call(context.getContentResolver(), Settings.METHOD_NEW_TRANSACTION).getBinder(Settings.EXTRA_VALUE)) {
        int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons);
        Point sourceSize = parsePoint(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString));
        boolean dbChanged = false;
        if (migrateForPreview) {
            copyTable(transaction.getDb(), Favorites.TABLE_NAME, transaction.getDb(), Favorites.PREVIEW_TABLE_NAME, context);
        }
        GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(), srcHotseatCount, sourceSize.x, sourceSize.y);
        if (migrateForPreview ? backupTable.restoreToPreviewIfBackupExists() : backupTable.backupOrRestoreAsNeeded()) {
            dbChanged = true;
            srcHotseatCount = backupTable.getRestoreHotseatAndGridSize(sourceSize);
        }
        HashSet<String> validPackages = getValidPackages(context);
        // Hotseat.
        if (srcHotseatCount != idp.numHotseatIcons && new GridSizeMigrationTask(context, transaction.getDb(), validPackages, migrateForPreview, srcHotseatCount, idp.numHotseatIcons).migrateHotseat()) {
            dbChanged = true;
        }
        // Grid size
        Point targetSize = new Point(idp.numColumns, idp.numRows);
        if (new MultiStepMigrationTask(validPackages, context, transaction.getDb(), migrateForPreview).migrate(sourceSize, targetSize)) {
            dbChanged = true;
        }
        if (dbChanged) {
            // Make sure we haven't removed everything.
            final Cursor c = context.getContentResolver().query(migrateForPreview ? Favorites.PREVIEW_CONTENT_URI : Favorites.CONTENT_URI, null, null, null, null);
            boolean hasData = c.moveToNext();
            c.close();
            if (!hasData) {
                throw new Exception("Removed every thing during grid resize");
            }
        }
        transaction.commit();
        if (!migrateForPreview) {
            Settings.call(context.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
        }
        return true;
    } catch (Exception e) {
        Log.e(TAG, "Error during preview grid migration", e);
        return false;
    } finally {
        Log.v(TAG, "Preview workspace migration completed in " + (SystemClock.elapsedRealtime() - migrationStartTime));
        if (!migrateForPreview) {
            // Save current configuration, so that the migration does not run again.
            prefs.edit().putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString).putInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons).apply();
        }
    }
}
Also used : SharedPreferences(android.content.SharedPreferences) SQLiteTransaction(com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction) Utilities.getPointString(com.android.launcher3.Utilities.getPointString) Utilities.parsePoint(com.android.launcher3.Utilities.parsePoint) Point(android.graphics.Point) Cursor(android.database.Cursor) Utilities.parsePoint(com.android.launcher3.Utilities.parsePoint) Point(android.graphics.Point)

Example 45 with Hotseat

use of com.android.launcher3.Hotseat in project Neo-Launcher by NeoApplications.

the class NoButtonQuickSwitchTouchController method onMotionPauseChanged.

@Override
public void onMotionPauseChanged(boolean isPaused) {
    ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
    if (shelfState == PEEK) {
        // Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
        AnimatorSetBuilder builder = new AnimatorSetBuilder();
        AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
        allAppsController.setAlphas(NORMAL.getVisibleElements(mLauncher), new AnimationConfig(), builder);
        builder.build().setDuration(0).start();
        if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
            // Hotseat was hidden, but we need it visible when peeking.
            mLauncher.getHotseat().setAlpha(1);
        }
    }
    mShelfPeekAnim.setShelfState(shelfState, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION);
    VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
}
Also used : AnimatorSetBuilder(com.android.launcher3.anim.AnimatorSetBuilder) AllAppsTransitionController(com.android.launcher3.allapps.AllAppsTransitionController) ShelfAnimState(com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState) AnimationConfig(com.android.launcher3.LauncherStateManager.AnimationConfig)

Aggregations

ItemInfo (com.android.launcher3.model.data.ItemInfo)67 View (android.view.View)66 WorkspaceItemInfo (com.android.launcher3.model.data.WorkspaceItemInfo)46 Point (android.graphics.Point)27 ArrayList (java.util.ArrayList)27 CellLayout (com.android.launcher3.CellLayout)26 ViewGroup (android.view.ViewGroup)23 BubbleTextView (com.android.launcher3.BubbleTextView)23 FolderInfo (com.android.launcher3.model.data.FolderInfo)23 ArrowTipView (com.android.launcher3.views.ArrowTipView)22 FolderIcon (com.android.launcher3.folder.FolderIcon)20 SuppressLint (android.annotation.SuppressLint)19 LauncherAppWidgetHostView (com.android.launcher3.widget.LauncherAppWidgetHostView)19 Hotseat (com.android.launcher3.Hotseat)16 Intent (android.content.Intent)15 IntArray (com.android.launcher3.util.IntArray)13 Workspace (com.android.launcher3.Workspace)12 DraggableView (com.android.launcher3.dragndrop.DraggableView)12 HashSet (java.util.HashSet)12 AppWidgetHostView (android.appwidget.AppWidgetHostView)11