Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddbe35cc authored by Brian Isganitis's avatar Brian Isganitis Committed by Android (Google) Code Review
Browse files

Merge "Drag from appDrawer & pin onto secondary display homescreen" into tm-qpr-dev

parents 42062393 b066f41f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -299,6 +299,10 @@ public final class FeatureFlags {
    public static final BooleanFlag ENABLE_TRANSIENT_TASKBAR = getDebugFlag(
            "ENABLE_TRANSIENT_TASKBAR", false, "Enables transient taskbar.");

    public static final BooleanFlag SECONDARY_DRAG_N_DROP_TO_PIN = getDebugFlag(
            "SECONDARY_DRAG_N_DROP_TO_PIN", false,
            "Enable dragging and dropping to pin apps within secondary display");

    public static void initialize(Context context) {
        synchronized (sDebugFlags) {
            for (DebugFlag flag : sDebugFlags) {
+13 −3
Original line number Diff line number Diff line
@@ -168,7 +168,10 @@ public class PinnedAppsAdapter extends BaseAdapter implements OnSharedPreference
        mPrefs.unregisterOnSharedPreferenceChangeListener(this);
    }

    private void update(ItemInfo info, Function<ComponentKey, Boolean> op) {
    /**
     * Pins or unpins apps from home screen
     */
    public void update(ItemInfo info, Function<ComponentKey, Boolean> op) {
        ComponentKey key = new ComponentKey(info.getTargetComponent(), info.user);
        if (op.apply(key)) {
            createFilteredAppsList();
@@ -210,6 +213,13 @@ public class PinnedAppsAdapter extends BaseAdapter implements OnSharedPreference
                mPinnedApps.contains(new ComponentKey(info.getTargetComponent(), info.user)));
    }

    /**
     * Pins app to home screen
     */
    public void addPinnedApp(ItemInfo info) {
        update(info, mPinnedApps::add);
    }

    private class PinUnPinShortcut extends SystemShortcut<SecondaryDisplayLauncher> {

        private final boolean mIsPinned;
+137 −3
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package com.android.launcher3.secondarydisplay;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
@@ -26,6 +29,9 @@ import android.view.inputmethod.InputMethodManager;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
@@ -33,6 +39,11 @@ import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.graphics.DragPreviewProvider;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.StringCache;
import com.android.launcher3.model.data.AppInfo;
@@ -52,11 +63,11 @@ import java.util.HashMap;
 * Launcher activity for secondary displays
 */
public class SecondaryDisplayLauncher extends BaseDraggingActivity
        implements BgDataModel.Callbacks {
        implements BgDataModel.Callbacks, DragController.DragListener {

    private LauncherModel mModel;

    private BaseDragLayer mDragLayer;
    private SecondaryDragController mDragController;
    private ActivityAllAppsContainerView<SecondaryDisplayLauncher> mAppsView;
    private View mAppsButton;

@@ -69,10 +80,13 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
    private boolean mBindingItems = false;
    private SecondaryDisplayPredictions mSecondaryDisplayPredictions;

    private final int[] mTempXY = new int[2];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mModel = LauncherAppState.getInstance(this).getModel();
        mDragController = new SecondaryDragController(this);
        mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
        mSecondaryDisplayPredictions = SecondaryDisplayPredictions.newInstance(this);
        if (getWindow().getDecorView().isAttachedToWindow()) {
@@ -86,6 +100,12 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
        initUi();
    }

    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        this.getDragController().removeDragListener(this);
    }

    private void initUi() {
        if (mDragLayer != null) {
            return;
@@ -106,12 +126,19 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
        mAppsView = findViewById(R.id.apps_view);
        mAppsButton = findViewById(R.id.all_apps_button);

        mDragController.addDragListener(this);
        mPopupDataProvider = new PopupDataProvider(
                mAppsView.getAppsStore()::updateNotificationDots);

        mModel.addCallbacksAndLoad(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mDragController.cancelDrag();
    }

    @Override
    public void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
@@ -129,12 +156,21 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
        showAppDrawer(false);
    }

    public DragController getDragController() {
        return mDragController;
    }

    @Override
    public void onBackPressed() {
        if (finishAutoCancelActionMode()) {
            return;
        }

        if (mDragController.isDragging()) {
            mDragController.cancelDrag();
            return;
        }

        // Note: There should be at most one log per method call. This is enforced implicitly
        // by using if-else statements.
        AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
@@ -236,6 +272,7 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
    @Override
    public void startBinding() {
        mBindingItems = true;
        mDragController.cancelDrag();
    }

    @Override
@@ -308,4 +345,101 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
            startActivitySafely(v, intent, item);
        }
    }

    /**
     * Core functionality for beginning a drag operation for an item that will be dropped within
     * the secondary display grid home screen
     */
    public void beginDragShared(View child, DragSource source, DragOptions options) {
        Object dragObject = child.getTag();
        if (!(dragObject instanceof ItemInfo)) {
            String msg = "Drag started with a view that has no tag set. This "
                    + "will cause a crash (issue 11627249) down the line. "
                    + "View: " + child + "  tag: " + child.getTag();
            throw new IllegalStateException(msg);
        }
        beginDragShared(child, source, (ItemInfo) dragObject,
                new DragPreviewProvider(child), options);
    }

    private void beginDragShared(View child, DragSource source,
            ItemInfo dragObject, DragPreviewProvider previewProvider, DragOptions options) {

        float iconScale = 1f;
        if (child instanceof BubbleTextView) {
            FastBitmapDrawable icon = ((BubbleTextView) child).getIcon();
            if (icon != null) {
                iconScale = icon.getAnimatedScale();
            }
        }

        // clear pressed state if necessary
        child.clearFocus();
        child.setPressed(false);
        if (child instanceof BubbleTextView) {
            BubbleTextView icon = (BubbleTextView) child;
            icon.clearPressedBackground();
        }

        DraggableView draggableView = null;
        if (child instanceof DraggableView) {
            draggableView = (DraggableView) child;
        }

        final View contentView = previewProvider.getContentView();
        final float scale;
        // The draggable drawable follows the touch point around on the screen
        final Drawable drawable;
        if (contentView == null) {
            drawable = previewProvider.createDrawable();
            scale = previewProvider.getScaleAndPosition(drawable, mTempXY);
        } else {
            drawable = null;
            scale = previewProvider.getScaleAndPosition(contentView, mTempXY);
        }
        int halfPadding = previewProvider.previewPadding / 2;
        int dragLayerX = mTempXY[0];
        int dragLayerY = mTempXY[1];

        Point dragVisualizeOffset = null;
        Rect dragRect = new Rect();
        if (draggableView != null) {
            draggableView.getSourceVisualDragBounds(dragRect);
            dragLayerY += dragRect.top;
            dragVisualizeOffset = new Point(-halfPadding, halfPadding);
        }
        if (contentView != null) {
            mDragController.startDrag(
                    contentView,
                    draggableView,
                    dragLayerX,
                    dragLayerY,
                    source,
                    dragObject,
                    dragVisualizeOffset,
                    dragRect,
                    scale * iconScale,
                    scale,
                    options);
        } else {
            mDragController.startDrag(
                    drawable,
                    draggableView,
                    dragLayerX,
                    dragLayerY,
                    source,
                    dragObject,
                    dragVisualizeOffset,
                    dragRect,
                    scale * iconScale,
                    scale,
                    options);
        }
    }

    @Override
    public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) { }

    @Override
    public void onDragEnd() { }
}
+194 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.launcher3.secondarydisplay;

import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.View;

import androidx.annotation.Nullable;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragDriver;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.testing.shared.TestProtocol;

/**
 * Drag controller for Secondary Launcher activity
 */
public class SecondaryDragController extends DragController<SecondaryDisplayLauncher> {

    private static final boolean PROFILE_DRAWING_DURING_DRAG = false;

    public SecondaryDragController(SecondaryDisplayLauncher secondaryLauncher) {
        super(secondaryLauncher);
    }

    @Override
    protected DragView startDrag(@Nullable Drawable drawable, @Nullable View view,
            DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source,
            ItemInfo dragInfo, Point dragOffset, Rect dragRegion, float initialDragViewScale,
            float dragViewScaleOnDrop, DragOptions options) {

        if (TestProtocol.sDebugTracing) {
            Log.d(TestProtocol.NO_DROP_TARGET, "5");
        }

        if (PROFILE_DRAWING_DURING_DRAG) {
            android.os.Debug.startMethodTracing("Launcher");
        }
        mActivity.hideKeyboard();

        mOptions = options;
        if (mOptions.simulatedDndStartPoint != null) {
            mLastTouch.x = mMotionDown.x = mOptions.simulatedDndStartPoint.x;
            mLastTouch.y = mMotionDown.y = mOptions.simulatedDndStartPoint.y;
        }

        final int registrationX = mMotionDown.x - dragLayerX;
        final int registrationY = mMotionDown.y - dragLayerY;

        final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
        final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;

        mLastDropTarget = null;

        mDragObject = new DropTarget.DragObject(mActivity.getApplicationContext());
        mDragObject.originalView = originalView;

        mIsInPreDrag = mOptions.preDragCondition != null
                && !mOptions.preDragCondition.shouldStartDrag(0);

        final Resources res = mActivity.getResources();
        final float scaleDps = mIsInPreDrag
                ? res.getDimensionPixelSize(R.dimen.pre_drag_view_scale) : 0f;

        final DragView dragView = mDragObject.dragView = drawable != null
                ? new SecondaryDragView(
                mActivity,
                drawable,
                registrationX,
                registrationY,
                initialDragViewScale,
                dragViewScaleOnDrop,
                scaleDps)
                : new SecondaryDragView(
                        mActivity,
                        view,
                        view.getMeasuredWidth(),
                        view.getMeasuredHeight(),
                        registrationX,
                        registrationY,
                        initialDragViewScale,
                        dragViewScaleOnDrop,
                        scaleDps);
        dragView.setItemInfo(dragInfo);
        mDragObject.dragComplete = false;

        mDragObject.xOffset = mMotionDown.x - (dragLayerX + dragRegionLeft);
        mDragObject.yOffset = mMotionDown.y - (dragLayerY + dragRegionTop);

        mDragDriver = DragDriver.create(this, mOptions, ev -> {
        });
        if (!mOptions.isAccessibleDrag) {
            mDragObject.stateAnnouncer = DragViewStateAnnouncer.createFor(dragView);
        }

        mDragObject.dragSource = source;
        mDragObject.dragInfo = dragInfo;
        mDragObject.originalDragInfo = mDragObject.dragInfo.makeShallowCopy();

        if (dragOffset != null) {
            dragView.setDragVisualizeOffset(new Point(dragOffset));
        }
        if (dragRegion != null) {
            dragView.setDragRegion(new Rect(dragRegion));
        }

        mActivity.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        dragView.show(mLastTouch.x, mLastTouch.y);
        mDistanceSinceScroll = 0;

        if (!mIsInPreDrag) {
            callOnDragStart();
        } else if (mOptions.preDragCondition != null) {
            mOptions.preDragCondition.onPreDragStart(mDragObject);
        }

        handleMoveEvent(mLastTouch.x, mLastTouch.y);
        return dragView;
    }

    @Override
    protected void exitDrag() { }

    @Override
    protected DropTarget getDefaultDropTarget(int[] dropCoordinates) {
        DropTarget target = new DropTarget() {
            @Override
            public boolean isDropEnabled() {
                return true;
            }

            @Override
            public void onDrop(DragObject dragObject, DragOptions options) {
                ((SecondaryDragLayer) mActivity.getDragLayer()).getPinnedAppsAdapter().addPinnedApp(
                        dragObject.dragInfo);
                dragObject.dragView.remove();
            }

            @Override
            public void onDragEnter(DragObject dragObject) {
                if (getDistanceDragged() > mActivity.getResources().getDimensionPixelSize(
                        R.dimen.drag_distanceThreshold)) {
                    mActivity.showAppDrawer(false);
                    AbstractFloatingView.closeAllOpenViews(mActivity);
                }
            }

            @Override
            public void onDragOver(DragObject dragObject) { }

            @Override
            public void onDragExit(DragObject dragObject) { }

            @Override
            public boolean acceptDrop(DragObject dragObject) {
                return true;
            }

            @Override
            public void prepareAccessibilityDrop() { }

            @Override
            public void getHitRectRelativeToDragLayer(Rect outRect) { }
        };
        return target;
    }
}
+47 −2
Original line number Diff line number Diff line
@@ -29,8 +29,12 @@ import android.widget.GridView;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DropTarget;
import com.android.launcher3.R;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.popup.PopupDataProvider;
@@ -59,7 +63,8 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>

    @Override
    public void recreateControllers() {
        mControllers = new TouchController[] {new CloseAllAppsTouchController()};
        mControllers = new TouchController[]{new CloseAllAppsTouchController(),
                mActivity.getDragController()};
    }

    /**
@@ -166,6 +171,10 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
        }
    }

    public PinnedAppsAdapter getPinnedAppsAdapter() {
        return mPinnedAppsAdapter;
    }

    private boolean onIconLongClicked(View v) {
        if (!(v instanceof BubbleTextView)) {
            return false;
@@ -183,6 +192,7 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
        if (popupDataProvider == null) {
            return false;
        }

        final PopupContainerWithArrow container =
                (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate(
                        R.layout.popup_container, mActivity.getDragLayer(), false);
@@ -192,7 +202,42 @@ public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher>
                Collections.emptyList(),
                Arrays.asList(mPinnedAppsAdapter.getSystemShortcut(item, v),
                        APP_INFO.getShortcut(mActivity, item, v)));
        v.getParent().requestDisallowInterceptTouchEvent(true);
        container.requestFocus();

        if (!FeatureFlags.SECONDARY_DRAG_N_DROP_TO_PIN.get() || !mActivity.isAppDrawerShown()) {
            return true;
        }

        DragOptions options = new DragOptions();
        DeviceProfile grid = mActivity.getDeviceProfile();
        options.intrinsicIconScaleFactor = (float) grid.allAppsIconSizePx / grid.iconSizePx;
        options.preDragCondition = container.createPreDragCondition(false);
        if (options.preDragCondition == null) {
            options.preDragCondition = new DragOptions.PreDragCondition() {
                private DragView<SecondaryDisplayLauncher> mDragView;

                @Override
                public boolean shouldStartDrag(double distanceDragged) {
                    return mDragView != null && mDragView.isAnimationFinished();
                }

                @Override
                public void onPreDragStart(DropTarget.DragObject dragObject) {
                    mDragView = dragObject.dragView;
                    if (!shouldStartDrag(0)) {
                        mDragView.setOnAnimationEndCallback(() -> {
                            mActivity.beginDragShared(v, mActivity.getAppsView(), options);
                        });
                    }
                }

                @Override
                public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
                    mDragView = null;
                }
            };
        }
        mActivity.beginDragShared(v, mActivity.getAppsView(), options);
        return true;
    }
}
Loading