Search in sources :

Example 81 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ProtonAOSP.

the class WidgetsRecommendationTableLayout method fitRecommendedWidgetsToTableSpace.

private RecommendationTableData fitRecommendedWidgetsToTableSpace(float previewScale, List<ArrayList<WidgetItem>> recommendedWidgetsInTable) {
    if (previewScale < MAX_DOWN_SCALE_RATIO) {
        Log.w(TAG, "Hide recommended widgets. Can't down scale previews to " + previewScale);
        return new RecommendationTableData(List.of(), previewScale);
    }
    // A naive estimation of the widgets recommendation table height without inflation.
    float totalHeight = mWidgetsRecommendationTableVerticalPadding;
    DeviceProfile deviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
    for (int i = 0; i < recommendedWidgetsInTable.size(); i++) {
        List<WidgetItem> widgetItems = recommendedWidgetsInTable.get(i);
        float rowHeight = 0;
        for (int j = 0; j < widgetItems.size(); j++) {
            WidgetItem widgetItem = widgetItems.get(j);
            Size widgetSize = WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile, widgetItem);
            float previewHeight = widgetSize.getHeight() * previewScale;
            rowHeight = Math.max(rowHeight, previewHeight + mWidgetCellTextViewsHeight + mWidgetCellVerticalPadding);
        }
        totalHeight += rowHeight;
    }
    if (totalHeight < mRecommendationTableMaxHeight) {
        return new RecommendationTableData(recommendedWidgetsInTable, previewScale);
    }
    if (recommendedWidgetsInTable.size() > 1) {
        // num of row by 1 to see if it fits.
        return fitRecommendedWidgetsToTableSpace(previewScale, recommendedWidgetsInTable.subList(/* fromIndex= */
        0, /* toIndex= */
        recommendedWidgetsInTable.size() - 1));
    }
    float nextPreviewScale = previewScale * DOWN_SCALE_RATIO;
    return fitRecommendedWidgetsToTableSpace(nextPreviewScale, recommendedWidgetsInTable);
}
Also used : DeviceProfile(com.android.launcher3.DeviceProfile) Size(android.util.Size) WidgetItem(com.android.launcher3.model.WidgetItem)

Example 82 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ProtonAOSP.

the class WidgetsRecyclerView method getCurrentScrollY.

@Override
public int getCurrentScrollY() {
    // Skip early if widgets are not bound.
    if (isModelNotReady() || getChildCount() == 0) {
        return -1;
    }
    int rowIndex = -1;
    View child = null;
    LayoutManager layoutManager = getLayoutManager();
    if (layoutManager instanceof LinearLayoutManager) {
        // Use the LayoutManager as the source of truth for visible positions. During
        // animations, the view group child may not correspond to the visible views that appear
        // at the top.
        rowIndex = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
        child = layoutManager.findViewByPosition(rowIndex);
    }
    if (child == null) {
        // If the layout manager returns null for any reason, which can happen before layout
        // has occurred for the position, then look at the child of this view as a ViewGroup.
        child = getChildAt(0);
        rowIndex = getChildPosition(child);
    }
    for (int i = 0; i < getChildCount(); i++) {
        View view = getChildAt(i);
        if (view instanceof TableLayout) {
            // This assumes there is ever only one content shown in this recycler view.
            mLastVisibleWidgetContentTableHeight = view.getMeasuredHeight();
        } else if (view instanceof WidgetsListHeader && mWidgetHeaderHeight == 0 && view.getMeasuredHeight() > 0) {
            // This assumes all header views are of the same height.
            mWidgetHeaderHeight = view.getMeasuredHeight();
        } else if (view instanceof EmptySpaceView && view.getMeasuredHeight() > 0) {
            mWidgetEmptySpaceHeight = view.getMeasuredHeight();
        }
    }
    int scrollPosition = getItemsHeight(rowIndex);
    int offset = getLayoutManager().getDecoratedTop(child);
    return getPaddingTop() + scrollPosition - offset;
}
Also used : LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) EmptySpaceView(com.android.launcher3.widget.picker.WidgetsSpaceViewHolderBinder.EmptySpaceView) LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) EmptySpaceView(com.android.launcher3.widget.picker.WidgetsSpaceViewHolderBinder.EmptySpaceView) BaseRecyclerView(com.android.launcher3.BaseRecyclerView) View(android.view.View) RecyclerView(androidx.recyclerview.widget.RecyclerView) TableLayout(android.widget.TableLayout) Point(android.graphics.Point)

Example 83 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ProtonAOSP.

the class Launcher method inflateAppWidget.

private View inflateAppWidget(LauncherAppWidgetInfo item) {
    if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
        item.providerName = QsbContainerView.getSearchComponentName(this);
        if (item.providerName == null) {
            getModelWriter().deleteItemFromDatabase(item);
            return null;
        }
    }
    final AppWidgetHostView view;
    if (mIsSafeModeEnabled) {
        view = new PendingAppWidgetHostView(this, item, mIconCache, true);
        prepareAppWidget(view, item);
        return view;
    }
    Object traceToken = TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId);
    try {
        final LauncherAppWidgetProviderInfo appWidgetInfo;
        String removalReason = "";
        if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
            // If the provider is not ready, bind as a pending widget.
            appWidgetInfo = null;
            removalReason = "the provider isn't ready.";
        } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
            // The widget id is not valid. Try to find the widget based on the provider info.
            appWidgetInfo = mAppWidgetManager.findProvider(item.providerName, item.user);
            if (appWidgetInfo == null) {
                if (WidgetsModel.GO_DISABLE_WIDGETS) {
                    removalReason = "widgets are disabled on go device.";
                } else {
                    removalReason = "WidgetManagerHelper cannot find a provider from provider info.";
                }
            }
        } else {
            appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId);
            if (appWidgetInfo == null) {
                if (item.appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
                    removalReason = "CustomWidgetManager cannot find provider from that widget id.";
                } else {
                    removalReason = "AppWidgetManager cannot find provider for that widget id." + " It could be because AppWidgetService is not available, or the" + " appWidgetId has not been bound to a the provider yet, or you" + " don't have access to that appWidgetId.";
                }
            }
        }
        // If the provider is ready, but the width is not yet restored, try to restore it.
        if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) && (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
            if (appWidgetInfo == null) {
                FileLog.d(TAG, "Removing restored widget: id=" + item.appWidgetId + " belongs to component " + item.providerName + " user " + item.user + ", as the provider is null and " + removalReason);
                getModelWriter().deleteItemFromDatabase(item);
                return null;
            }
            // If we do not have a valid id, try to bind an id.
            if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
                if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) {
                    // Id has not been allocated yet. Allocate a new id.
                    item.appWidgetId = mAppWidgetHost.allocateAppWidgetId();
                    item.restoreStatus |= LauncherAppWidgetInfo.FLAG_ID_ALLOCATED;
                    // Also try to bind the widget. If the bind fails, the user will be shown
                    // a click to setup UI, which will ask for the bind permission.
                    PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(appWidgetInfo, item.sourceContainer);
                    pendingInfo.spanX = item.spanX;
                    pendingInfo.spanY = item.spanY;
                    pendingInfo.minSpanX = item.minSpanX;
                    pendingInfo.minSpanY = item.minSpanY;
                    Bundle options = pendingInfo.getDefaultSizeOptions(this);
                    boolean isDirectConfig = item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
                    if (isDirectConfig && item.bindOptions != null) {
                        Bundle newOptions = item.bindOptions.getExtras();
                        if (options != null) {
                            newOptions.putAll(options);
                        }
                        options = newOptions;
                    }
                    boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(item.appWidgetId, appWidgetInfo, options);
                    // We tried to bind once. If we were not able to bind, we would need to
                    // go through the permission dialog, which means we cannot skip the config
                    // activity.
                    item.bindOptions = null;
                    item.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG;
                    // Bind succeeded
                    if (success) {
                        // If the widget has a configure activity, it is still needs to set it
                        // up, otherwise the widget is ready to go.
                        item.restoreStatus = (appWidgetInfo.configure == null) || isDirectConfig ? LauncherAppWidgetInfo.RESTORE_COMPLETED : LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
                    }
                    getModelWriter().updateItemInDatabase(item);
                }
            } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) && (appWidgetInfo.configure == null)) {
                // The widget was marked as UI not ready, but there is no configure activity to
                // update the UI.
                item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
                getModelWriter().updateItemInDatabase(item);
            } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) && appWidgetInfo.configure != null) {
                if (mAppWidgetManager.isAppWidgetRestored(item.appWidgetId)) {
                    item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
                    getModelWriter().updateItemInDatabase(item);
                }
            }
        }
        if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
            // Verify that we own the widget
            if (appWidgetInfo == null) {
                FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
                getModelWriter().deleteWidgetInfo(item, getAppWidgetHost());
                return null;
            }
            item.minSpanX = appWidgetInfo.minSpanX;
            item.minSpanY = appWidgetInfo.minSpanY;
            view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
        } else if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) && appWidgetInfo != null) {
            mAppWidgetHost.addPendingView(item.appWidgetId, new PendingAppWidgetHostView(this, item, mIconCache, false));
            view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
        } else {
            view = new PendingAppWidgetHostView(this, item, mIconCache, false);
        }
        prepareAppWidget(view, item);
    } finally {
        TraceHelper.INSTANCE.endSection(traceToken);
    }
    return view;
}
Also used : LauncherAppWidgetProviderInfo(com.android.launcher3.widget.LauncherAppWidgetProviderInfo) PendingAppWidgetHostView(com.android.launcher3.widget.PendingAppWidgetHostView) LauncherAppWidgetHostView(com.android.launcher3.widget.LauncherAppWidgetHostView) AppWidgetHostView(android.appwidget.AppWidgetHostView) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) Bundle(android.os.Bundle) DragObject(com.android.launcher3.DropTarget.DragObject) PendingAppWidgetHostView(com.android.launcher3.widget.PendingAppWidgetHostView)

Example 84 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ProtonAOSP.

the class Launcher method handleActivityResult.

private void handleActivityResult(final int requestCode, final int resultCode, final Intent data) {
    if (isWorkspaceLoading()) {
        // process the result once the workspace has loaded.
        mPendingActivityResult = new ActivityResultInfo(requestCode, resultCode, data);
        return;
    }
    mPendingActivityResult = null;
    // Reset the startActivity waiting flag
    final PendingRequestArgs requestArgs = mPendingRequestArgs;
    setWaitingForResult(null);
    if (requestArgs == null) {
        return;
    }
    final int pendingAddWidgetId = requestArgs.getWidgetId();
    Runnable exitSpringLoaded = new Runnable() {

        @Override
        public void run() {
            mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
        }
    };
    if (requestCode == REQUEST_BIND_APPWIDGET) {
        // This is called only if the user did not previously have permissions to bind widgets
        final int appWidgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
        if (resultCode == RESULT_CANCELED) {
            completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId, requestArgs);
            mWorkspace.removeExtraEmptyScreenDelayed(ON_ACTIVITY_RESULT_ANIMATION_DELAY, false, exitSpringLoaded);
        } else if (resultCode == RESULT_OK) {
            addAppWidgetImpl(appWidgetId, requestArgs, null, requestArgs.getWidgetHandler(), ON_ACTIVITY_RESULT_ANIMATION_DELAY);
        }
        return;
    }
    boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET);
    // We have special handling for widgets
    if (isWidgetDrop) {
        final int appWidgetId;
        int widgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
        if (widgetId < 0) {
            appWidgetId = pendingAddWidgetId;
        } else {
            appWidgetId = widgetId;
        }
        final int result;
        if (appWidgetId < 0 || resultCode == RESULT_CANCELED) {
            Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not " + "returned from the widget configuration activity.");
            result = RESULT_CANCELED;
            completeTwoStageWidgetDrop(result, appWidgetId, requestArgs);
            mWorkspace.removeExtraEmptyScreenDelayed(ON_ACTIVITY_RESULT_ANIMATION_DELAY, false, () -> getStateManager().goToState(NORMAL));
        } else {
            if (requestArgs.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
                // When the screen id represents an actual screen (as opposed to a rank)
                // we make sure that the drop page actually exists.
                requestArgs.screenId = ensurePendingDropLayoutExists(requestArgs.screenId);
            }
            final CellLayout dropLayout = mWorkspace.getScreenWithId(requestArgs.screenId);
            dropLayout.setDropPending(true);
            final Runnable onComplete = new Runnable() {

                @Override
                public void run() {
                    completeTwoStageWidgetDrop(resultCode, appWidgetId, requestArgs);
                    dropLayout.setDropPending(false);
                }
            };
            mWorkspace.removeExtraEmptyScreenDelayed(ON_ACTIVITY_RESULT_ANIMATION_DELAY, false, onComplete);
        }
        return;
    }
    if (requestCode == REQUEST_RECONFIGURE_APPWIDGET || requestCode == REQUEST_BIND_PENDING_APPWIDGET) {
        if (resultCode == RESULT_OK) {
            // Update the widget view.
            completeAdd(requestCode, data, pendingAddWidgetId, requestArgs);
        }
        // Leave the widget in the pending state if the user canceled the configure.
        return;
    }
    if (requestCode == REQUEST_CREATE_SHORTCUT) {
        // Handle custom shortcuts created using ACTION_CREATE_SHORTCUT.
        if (resultCode == RESULT_OK && requestArgs.container != ItemInfo.NO_ID) {
            completeAdd(requestCode, data, -1, requestArgs);
            mWorkspace.removeExtraEmptyScreenDelayed(ON_ACTIVITY_RESULT_ANIMATION_DELAY, false, exitSpringLoaded);
        } else if (resultCode == RESULT_CANCELED) {
            mWorkspace.removeExtraEmptyScreenDelayed(ON_ACTIVITY_RESULT_ANIMATION_DELAY, false, exitSpringLoaded);
        }
    }
    mDragLayer.clearAnimatedView();
}
Also used : ActivityResultInfo(com.android.launcher3.util.ActivityResultInfo) PendingRequestArgs(com.android.launcher3.util.PendingRequestArgs)

Example 85 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ProtonAOSP.

the class BaseWidgetSheet method doMeasure.

/**
 * Measures the dimension of this view and its children by taking system insets, navigation bar,
 * status bar, into account.
 */
@GuardedBy("MainThread")
protected void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
    int widthUsed;
    if (mInsets.bottom > 0) {
        widthUsed = mInsets.left + mInsets.right;
    } else {
        Rect padding = deviceProfile.workspacePadding;
        widthUsed = Math.max(padding.left + padding.right, 2 * (mInsets.left + mInsets.right));
    }
    if (deviceProfile.isTablet || deviceProfile.isTwoPanels) {
        // In large screen devices, we restrict the width of the widgets picker to show part of
        // the home screen. Let's ensure the minimum width used is at least the minimum width
        // that isn't taken by the widgets picker.
        int minUsedWidth = (int) (deviceProfile.availableWidthPx * (1 - MAX_WIDTH_SCALE_FOR_LARGER_SCREEN));
        widthUsed = Math.max(widthUsed, minUsedWidth);
    }
    int heightUsed = mInsets.top + deviceProfile.edgeMarginPx;
    measureChildWithMargins(mContent, widthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed);
    setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
}
Also used : DeviceProfile(com.android.launcher3.DeviceProfile) Rect(android.graphics.Rect) Point(android.graphics.Point) GuardedBy(androidx.annotation.GuardedBy)

Aggregations

ArrayList (java.util.ArrayList)64 Test (org.junit.Test)64 WidgetItem (com.android.launcher3.model.WidgetItem)54 WidgetsListContentEntry (com.android.launcher3.widget.model.WidgetsListContentEntry)54 PackageUserKey (com.android.launcher3.util.PackageUserKey)50 List (java.util.List)50 AppWidgetProviderInfo (android.appwidget.AppWidgetProviderInfo)46 SmallTest (androidx.test.filters.SmallTest)44 ComponentName (android.content.ComponentName)42 WidgetsListBaseEntry (com.android.launcher3.widget.model.WidgetsListBaseEntry)41 Point (android.graphics.Point)40 View (android.view.View)37 LauncherAppWidgetHostView (com.android.launcher3.widget.LauncherAppWidgetHostView)32 Collectors (java.util.stream.Collectors)31 Context (android.content.Context)29 IconCache (com.android.launcher3.icons.IconCache)29 LauncherAppWidgetProviderInfo (com.android.launcher3.widget.LauncherAppWidgetProviderInfo)29 WidgetsListHeaderEntry (com.android.launcher3.widget.model.WidgetsListHeaderEntry)29 WorkspaceItemInfo (com.android.launcher3.model.data.WorkspaceItemInfo)27 PendingAddWidgetInfo (com.android.launcher3.widget.PendingAddWidgetInfo)27