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

Commit e1fcb539 authored by Jeremy Sim's avatar Jeremy Sim
Browse files

App Pairs: Implement Overview Actions View button

[App Pairs 6/?]

This patch includes:
- Ability to "save app pair" from Overview Actions
- The actions bar is not longer hidden for GroupedTasks; instead the individual buttons for "Select", "Screenshot", and "Split screen" are toggled off and "Save app pair" is toggled on.

Note: This patch introduces a slight regression (b/315545418) where users are now able to long-press to select text on task 1 of a paired GroupedTaskView (previously we did not let them select text on either task for consistency.) Will follow up with a fix -- see bug for details.

Flag: ACONFIG com.android.wm.shell.enable_app_pairs DEVELOPMENT
Bug: 315545418
Bug: 315292030
Test: Manual, all action buttons still work and "Save app pair" appears and disappears correctly
Change-Id: I0eb1fa9520ba14074ede3480e771b340cf2f6e2c
parent c8112630
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -55,6 +55,15 @@
            android:theme="@style/ThemeControlHighlightWorkspaceColor"
            android:visibility="gone" />

        <Button
            android:id="@+id/action_save_app_pair"
            style="@style/OverviewActionButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/action_save_app_pair"
            android:theme="@style/ThemeControlHighlightWorkspaceColor"
            android:visibility="gone" />

        <Space
            android:layout_width="0dp"
            android:layout_height="1dp"
+2 −0
Original line number Diff line number Diff line
@@ -228,6 +228,8 @@
    <string name="action_screenshot">Screenshot</string>
    <!-- Label for a button that enters split screen selection mode. [CHAR_LIMIT=20] -->
    <string name="action_split">Split</string>
    <!-- Label for a button that saves a new app pair. [CHAR_LIMIT=20] -->
    <string name="action_save_app_pair">Save app pair</string>
    <!-- Label for toast with instructions for split screen selection mode. [CHAR_LIMIT=50] -->
    <string name="toast_split_select_app">Tap another app to use split screen</string>
    <string name="toast_split_select_app_cancel"><b>Cancel</b></string>
+15 −1
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.launcher3.util.ResourceBasedOverride;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.Snackbar;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
@@ -210,13 +211,19 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
            }
        }

        private void enterSplitSelect() {
        protected void enterSplitSelect() {
            RecentsView overviewPanel = mThumbnailView.getTaskView().getRecentsView();
            // Task has already been dismissed
            if (overviewPanel == null) return;
            overviewPanel.initiateSplitSelect(mThumbnailView.getTaskView());
        }

        protected void saveAppPair() {
            GroupedTaskView taskView = (GroupedTaskView) mThumbnailView.getTaskView();
            taskView.getRecentsView().getSplitSelectController().getAppPairsController()
                    .saveAppPair(taskView);
        }

        /**
         * Called when the overlay is no longer used.
         */
@@ -329,6 +336,10 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
            public void onSplit() {
                endLiveTileMode(TaskOverlay.this::enterSplitSelect);
            }

            public void onSaveAppPair() {
                endLiveTileMode(TaskOverlay.this::saveAppPair);
            }
        }
    }

@@ -342,5 +353,8 @@ public class TaskOverlayFactory implements ResourceBasedOverride {

        /** User wants to start split screen with current app. */
        void onSplit();

        /** User wants to save an app pair with current group of apps. */
        void onSaveAppPair();
    }
}
+6 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
@@ -390,8 +391,12 @@ public class GroupedTaskView extends TaskView {

    @Override
    public void setOverlayEnabled(boolean overlayEnabled) {
        if (FeatureFlags.enableAppPairs()) {
            super.setOverlayEnabled(overlayEnabled);
        } else {
            // Intentional no-op to prevent setting smart actions overlay on thumbnails
        }
    }

    @Override
    public void setOrientationState(RecentsOrientedState orientationState) {
+75 −27
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.launcher3.util.MultiValueAlpha;
@@ -89,14 +90,27 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
    private static final int INDEX_SCROLL_ALPHA = 5;
    private static final int NUM_ALPHAS = 6;

    public @interface ScreenshotButtonHiddenFlags { }
    public static final int FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT = 1 << 0;

    public @interface SplitButtonHiddenFlags { }
    public static final int FLAG_IS_NOT_TABLET = 1 << 0;
    public static final int FLAG_IS_NOT_TABLET_HIDE_SPLIT = 1 << 0;
    public static final int FLAG_MULTIPLE_TASKS_HIDE_SPLIT = 1 << 1;

    public @interface SplitButtonDisabledFlags { }
    public static final int FLAG_SINGLE_TASK = 1 << 0;
    public static final int FLAG_SINGLE_TASK_DISABLE_SPLIT = 1 << 0;

    public @interface AppPairButtonHiddenFlags { }
    public static final int FLAG_SINGLE_TASK_HIDE_APP_PAIR = 1 << 0;

    private MultiValueAlpha mMultiValueAlpha;

    // The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is an
    // ImageButton in go launcher (does not share a common class with Button). Take care when
    // casting this.
    private View mScreenshotButton;
    private Button mSplitButton;
    private Button mSaveAppPairButton;

    @ActionsHiddenFlags
    private int mHiddenFlags;
@@ -104,11 +118,14 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
    @ActionsDisabledFlags
    protected int mDisabledFlags;

    @ScreenshotButtonHiddenFlags
    private int mScreenshotButtonHiddenFlags;

    @SplitButtonHiddenFlags
    private int mSplitButtonHiddenFlags;

    @SplitButtonDisabledFlags
    private int mSplitButtonDisabledFlags;
    @AppPairButtonHiddenFlags
    private int mAppPairButtonHiddenFlags;

    @Nullable
    protected T mCallbacks;
@@ -135,9 +152,12 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
        mMultiValueAlpha = new MultiValueAlpha(findViewById(R.id.action_buttons), NUM_ALPHAS);
        mMultiValueAlpha.setUpdateVisibility(true);

        findViewById(R.id.action_screenshot).setOnClickListener(this);
        mScreenshotButton = findViewById(R.id.action_screenshot);
        mScreenshotButton.setOnClickListener(this);
        mSplitButton = findViewById(R.id.action_split);
        mSplitButton.setOnClickListener(this);
        mSaveAppPairButton = findViewById(R.id.action_save_app_pair);
        mSaveAppPairButton.setOnClickListener(this);
    }

    /**
@@ -159,6 +179,8 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
            mCallbacks.onScreenshot();
        } else if (id == R.id.action_split) {
            mCallbacks.onSplit();
        } else if (id == R.id.action_save_app_pair) {
            mCallbacks.onSaveAppPair();
        }
    }

@@ -201,7 +223,38 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
        }
        boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
        LayoutUtils.setViewEnabled(this, isEnabled);
        updateSplitButtonEnabledState();
    }

    /**
     * Updates a batch of flags to hide and show actions buttons when a grouped task (split screen)
     * is focused.
     * @param isGroupedTask True if the focused task is a grouped task.
     */
    public void updateForGroupedTask(boolean isGroupedTask) {
        // Update flags to see if split button should be hidden.
        updateSplitButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SPLIT, isGroupedTask);
        // Update flags to see if screenshot button should be hidden.
        updateScreenshotButtonHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT, isGroupedTask);
        // Update flags to see if save app pair button should be hidden.
        updateAppPairButtonHiddenFlags(FLAG_SINGLE_TASK_HIDE_APP_PAIR, !isGroupedTask);
    }

    /**
     * Updates the proper flags to indicate whether the "Screenshot" button should be hidden.
     *
     * @param flag   The flag to update.
     * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
     */
    private void updateScreenshotButtonHiddenFlags(@ScreenshotButtonHiddenFlags int flag,
            boolean enable) {
        if (enable) {
            mScreenshotButtonHiddenFlags |= flag;
        } else {
            mScreenshotButtonHiddenFlags &= ~flag;
        }
        if (mScreenshotButton == null) return;
        boolean shouldBeVisible = mScreenshotButtonHiddenFlags == 0;
        mScreenshotButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
    }

    /**
@@ -210,7 +263,8 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
     * @param flag   The flag to update.
     * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
     */
    public void updateSplitButtonHiddenFlags(@SplitButtonHiddenFlags int flag, boolean enable) {
    void updateSplitButtonHiddenFlags(@SplitButtonHiddenFlags int flag,
            boolean enable) {
        if (enable) {
            mSplitButtonHiddenFlags |= flag;
        } else {
@@ -223,18 +277,24 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
    }

    /**
     * Updates the proper flags to indicate whether the "Split screen" button should be disabled.
     * Updates the proper flags to indicate whether the "Save app pair" button should be disabled.
     *
     * @param flag   The flag to update.
     * @param enable Whether to enable the disable flag: True will cause view to be disabled.
     * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
     */
    public void updateSplitButtonDisabledFlags(@SplitButtonDisabledFlags int flag, boolean enable) {
    private void updateAppPairButtonHiddenFlags(@AppPairButtonHiddenFlags int flag, boolean enable) {
        if (!FeatureFlags.enableAppPairs()) {
            return;
        }

        if (enable) {
            mSplitButtonDisabledFlags |= flag;
            mAppPairButtonHiddenFlags |= flag;
        } else {
            mSplitButtonDisabledFlags &= ~flag;
            mAppPairButtonHiddenFlags &= ~flag;
        }
        updateSplitButtonEnabledState();
        if (mSaveAppPairButton == null) return;
        boolean shouldBeVisible = mAppPairButtonHiddenFlags == 0;
        mSaveAppPairButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
    }

    public MultiProperty getContentAlpha() {
@@ -312,19 +372,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
                ? R.drawable.ic_split_horizontal
                : R.drawable.ic_split_vertical;
        mSplitButton.setCompoundDrawablesRelativeWithIntrinsicBounds(splitIconRes, 0, 0, 0);
        mSaveAppPairButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
                R.drawable.ic_save_app_pair, 0, 0, 0);
    }

    /**
     * Enables/disables the "Split" button based on the status of mSplitButtonDisabledFlags and
     * mDisabledFlags.
     */
    private void updateSplitButtonEnabledState() {
        if (mSplitButton == null) {
            return;
        }
        boolean isParentEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
        boolean shouldBeEnabled = mSplitButtonDisabledFlags == 0 && isParentEnabled;
        mSplitButton.setEnabled(shouldBeEnabled);
    }

}
Loading