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

Commit d47e7e11 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Add ability to swap docked/fullscreen stack

Adds tap affordance that moves all tasks of the docked
stack into the fullscreen stack as well as moves the top task
of the fullscreen stack into the docked stack.

Also make sure not to trigger focus switch when tapping the divider
handle. For that, add a method so SysUI can specify the touchable
region which then gets excludes for the focus switch touch region.

Bug: 27358134
Change-Id: I34f39c53cacc0b9c00f87a792b88c3f64a5f61e1
parent 899327f5
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -838,6 +838,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            resizePinnedStack(bounds, tempPinnedTaskBounds);
            return true;
        }
        case SWAP_DOCKED_AND_FULLSCREEN_STACK: {
            data.enforceInterface(IActivityManager.descriptor);
            swapDockedAndFullscreenStack();
            reply.writeNoException();
            return true;
        }
        case RESIZE_DOCKED_STACK_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            final boolean hasBounds = data.readInt() != 0;
@@ -3895,6 +3901,17 @@ class ActivityManagerProxy implements IActivityManager
        reply.recycle();
    }
    @Override
    public void swapDockedAndFullscreenStack() throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        mRemote.transact(SWAP_DOCKED_AND_FULLSCREEN_STACK, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
    @Override
    public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
            Rect tempDockedTaskInsetBounds,
            Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds)
+7 −0
Original line number Diff line number Diff line
@@ -150,6 +150,12 @@ public interface IActivityManager extends IInterface {
    public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
            boolean preserveWindows, boolean animate) throws RemoteException;

    /**
     * Moves all tasks from the docked stack in the fullscreen stack and puts the top task of the
     * fullscreen stack into the docked stack.
     */
    public void swapDockedAndFullscreenStack() throws RemoteException;

    /**
     * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
     *
@@ -998,4 +1004,5 @@ public interface IActivityManager extends IInterface {
    int GET_MEMORY_TRIM_LEVEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+369;
    int RESIZE_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 370;
    int IS_VR_PACKAGE_ENABLED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 371;
    int SWAP_DOCKED_AND_FULLSCREEN_STACK = IBinder.FIRST_CALL_TRANSACTION + 372;
}
+6 −0
Original line number Diff line number Diff line
@@ -362,6 +362,12 @@ interface IWindowManager
     */
    void setDockedStackResizing(boolean resizing);

    /**
     * Sets the region the user can touch the divider. This region will be excluded from the region
     * which is used to cause a focus switch when dispatching touch.
     */
    void setDockedStackDividerTouchRegion(in Rect touchableRegion);

    /**
     * Registers a listener that will be called when the dock divider changes its visibility or when
     * the docked stack gets added/removed.
+34 −3
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.stackdivider;

import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -31,6 +34,9 @@ import android.os.Bundle;
import android.util.AttributeSet;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.VelocityTracker;
@@ -39,6 +45,7 @@ import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver.InternalInsetsInfo;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -52,17 +59,16 @@ import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.activity.UndockingTaskEvent;
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;

import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;

/**
 * Docked stack divider.
 */
@@ -136,6 +142,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    private boolean mGrowRecents;
    private ValueAnimator mCurrentAnimator;
    private boolean mEntranceAnimationRunning;
    private GestureDetector mGestureDetector;

    private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
        @Override
@@ -213,12 +220,35 @@ public class DividerView extends FrameLayout implements OnTouchListener,
                landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW));
        getViewTreeObserver().addOnComputeInternalInsetsListener(this);
        mHandle.setAccessibilityDelegate(mHandleDelegate);
        mGestureDetector = new GestureDetector(mContext, new SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                updateDockSide();
                SystemServicesProxy ssp = Recents.getSystemServices();
                if (mDockSide != WindowManager.DOCKED_INVALID
                        && !ssp.isRecentsTopMost(ssp.getTopMostTask(), null /* isTopHome */)) {
                    mWindowManagerProxy.swapTasks();
                    return true;
                }
                return false;
            }
        });
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        EventBus.getDefault().register(this);
        getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {
                getViewTreeObserver().removeOnGlobalLayoutListener(this);
                mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
                        mHandle.getLeft() + mHandle.getWidth(),
                        mHandle.getTop() + mHandle.getHeight()));
            }
        });
    }

    @Override
@@ -320,6 +350,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        convertToScreenCoordinates(event);
        mGestureDetector.onTouchEvent(event);
        final int action = event.getAction() & MotionEvent.ACTION_MASK;
        switch (action) {
            case MotionEvent.ACTION_DOWN:
+44 −4
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.stackdivider;

import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.view.WindowManager.DOCKED_INVALID;

import android.app.ActivityManagerNative;
import android.graphics.Rect;
import android.os.RemoteException;
@@ -27,9 +30,6 @@ import com.android.internal.annotations.GuardedBy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.view.WindowManager.DOCKED_INVALID;

/**
 * Proxy to simplify calls into window manager/activity manager
 */
@@ -39,7 +39,7 @@ public class WindowManagerProxy {

    private static final WindowManagerProxy sInstance = new WindowManagerProxy();

    @GuardedBy("mResizeRect")
    @GuardedBy("mDockedRect")
    private final Rect mDockedRect = new Rect();
    private final Rect mTempDockedTaskRect = new Rect();
    private final Rect mTempDockedInsetRect = new Rect();
@@ -52,6 +52,9 @@ public class WindowManagerProxy {
    private final Rect mTmpRect4 = new Rect();
    private final Rect mTmpRect5 = new Rect();

    @GuardedBy("mDockedRect")
    private final Rect mTouchableRegion = new Rect();

    private boolean mDimLayerVisible;
    private int mDimLayerTargetStack;
    private float mDimLayerAlpha;
@@ -117,6 +120,32 @@ public class WindowManagerProxy {
        }
    };

    private final Runnable mSwapRunnable = new Runnable() {
        @Override
        public void run() {
            try {
                ActivityManagerNative.getDefault().swapDockedAndFullscreenStack();
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to resize stack: " + e);
            }
        }
    };

    private final Runnable mSetTouchableRegionRunnable = new Runnable() {
        @Override
        public void run() {
            try {
                synchronized (mDockedRect) {
                    mTmpRect1.set(mTouchableRegion);
                }
                WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
                        mTmpRect1);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to set touchable region: " + e);
            }
        }
    };

    private WindowManagerProxy() {
    }

@@ -188,4 +217,15 @@ public class WindowManagerProxy {
        mDimLayerAlpha = alpha;
        mExecutor.execute(mDimLayerRunnable);
    }

    public void swapTasks() {
        mExecutor.execute(mSwapRunnable);
    }

    public void setTouchRegion(Rect region) {
        synchronized (mDockedRect) {
            mTouchableRegion.set(region);
        }
        mExecutor.execute(mSetTouchableRegionRunnable);
    }
}
Loading