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

Commit bfaa9760 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Updating the touch proxy logic:

In draglayer, we always dispatch touch events to child views. If the
touch originated from gesture area, when we dont route it through touch
controllers.
The proxy events are only send to touch controller. If any controller consumes
the event, then we cancel the view touch (pilferPointers)

This allows the controllers to work outside the dragView area, and prevents normal
view interaction when there is a window on top (like keyboard) while keeping our
activity focused

Bug: 131088901
Bug: 130618737
Change-Id: If033dde3a0f9cb6a6e449c9586c1fa050af5bdcb
parent efe84750
Loading
Loading
Loading
Loading
+37 −84
Original line number Diff line number Diff line
@@ -15,24 +15,20 @@
 */
package com.android.quickstep;

import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;

import android.graphics.PointF;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;

import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.Utilities;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.util.CachedEventDispatcher;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;

import androidx.annotation.Nullable;

/**
 * Input consumer for handling touch on the recents/Launcher activity.
@@ -40,24 +36,27 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
public class OverviewInputConsumer<T extends BaseDraggingActivity>
        implements InputConsumer {

    private final CachedEventDispatcher mCachedEventDispatcher = new CachedEventDispatcher();
    private final T mActivity;
    private final BaseDragLayer mTarget;
    private final InputMonitorCompat mInputMonitor;

    private final int[] mLocationOnScreen = new int[2];
    private final PointF mDownPos = new PointF();
    private final int mTouchSlopSquared;
    private final boolean mProxyTouch;

    private final boolean mStartingInActivityBounds;
    private boolean mTargetHandledTouch;

    private boolean mTrackingStarted = false;
    private boolean mInvalidated = false;

    OverviewInputConsumer(T activity, boolean startingInActivityBounds) {
    OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor,
            boolean startingInActivityBounds) {
        mActivity = activity;
        mTarget = activity.getDragLayer();
        int touchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
        mTouchSlopSquared = touchSlop * touchSlop;
        mInputMonitor = inputMonitor;
        mStartingInActivityBounds = startingInActivityBounds;

        mTarget = activity.getDragLayer();
        if (!startingInActivityBounds) {
            mTarget.getLocationOnScreen(mLocationOnScreen);
        }
        mProxyTouch = mTarget.prepareProxyEventStarting();
    }

    @Override
@@ -67,92 +66,46 @@ public class OverviewInputConsumer<T extends BaseDraggingActivity>

    @Override
    public void onMotionEvent(MotionEvent ev) {
        if (mInvalidated) {
        if (!mProxyTouch) {
            return;
        }
        mCachedEventDispatcher.dispatchEvent(ev);
        int action = ev.getActionMasked();
        if (action == ACTION_DOWN) {
            if (mStartingInActivityBounds) {
                startTouchTracking(ev, false /* updateLocationOffset */,
                        false /* closeActiveWindows */);
                return;
            }
            mTrackingStarted = false;
            mDownPos.set(ev.getX(), ev.getY());
        } else if (!mTrackingStarted) {
            switch (action) {
                case ACTION_CANCEL:
                case ACTION_UP:
                    startTouchTracking(ev, true /* updateLocationOffset */,
                            false /* closeActiveWindows */);
                    break;
                case ACTION_MOVE: {
                    float x = ev.getX() - mDownPos.x;
                    float y = ev.getY() - mDownPos.y;
                    double hypotSquared = x * x + y * y;
                    if (hypotSquared >= mTouchSlopSquared) {
                        // Start tracking only when touch slop is crossed.
                        startTouchTracking(ev, true /* updateLocationOffset */,
                                true /* closeActiveWindows */);
                    }
                }
            }
        }

        if (action == ACTION_UP || action == ACTION_CANCEL) {
            mInvalidated = true;

            // Set an empty consumer to that all the cached events are cleared
            if (!mCachedEventDispatcher.hasConsumer()) {
                mCachedEventDispatcher.setConsumer(motionEvent -> { });
            }
        }
    }

    @Override
    public void onKeyEvent(KeyEvent ev) {
        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
            mActivity.dispatchKeyEvent(ev);
        }
    }

    private void startTouchTracking(MotionEvent ev, boolean updateLocationOffset,
            boolean closeActiveWindows) {
        if (updateLocationOffset) {
            mTarget.getLocationOnScreen(mLocationOnScreen);
        int flags = ev.getEdgeFlags();
        if (!mStartingInActivityBounds) {
            ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR);
        }
        ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
        boolean handled = mTarget.proxyTouchEvent(ev);
        ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
        ev.setEdgeFlags(flags);

        if (closeActiveWindows) {
        if (!mTargetHandledTouch && handled) {
            mTargetHandledTouch = true;
            if (!mStartingInActivityBounds) {
                OverviewCallbacks.get(mActivity).closeAllWindows();
                ActivityManagerWrapper.getInstance()
                        .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
                TOUCH_INTERACTION_LOG.addLog("startQuickstep");
            }

        mTrackingStarted = true;
        mCachedEventDispatcher.setConsumer(this::sendEvent);

            if (mInputMonitor != null) {
                mInputMonitor.pilferPointers();
            }
        }
    }

    private void sendEvent(MotionEvent ev) {
        if (mInvalidated) {
            return;
    @Override
    public void onKeyEvent(KeyEvent ev) {
        if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
            mActivity.dispatchKeyEvent(ev);
        }
        int flags = ev.getEdgeFlags();
        ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR);
        ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
        mInvalidated = !mTarget.dispatchTouchEvent(this, ev);
        ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
        ev.setEdgeFlags(flags);
    }

    public static InputConsumer newInstance(ActivityControlHelper activityHelper,
            boolean startingInActivityBounds) {
            @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) {
        BaseDraggingActivity activity = activityHelper.getCreatedActivity();
        if (activity == null) {
            return InputConsumer.NO_OP;
        }
        return new OverviewInputConsumer(activity, startingInActivityBounds);
        return new OverviewInputConsumer(activity, inputMonitor, startingInActivityBounds);
    }
}
 No newline at end of file
+2 −2
Original line number Diff line number Diff line
@@ -468,10 +468,10 @@ public class TouchInteractionService extends Service implements
                    mInputMonitorCompat, activityControl);

        } else if (mSwipeSharedState.goingToLauncher || activityControl.isResumed()) {
            return OverviewInputConsumer.newInstance(activityControl, false);
            return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false);
        } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
                activityControl.isInLiveTileMode()) {
            return OverviewInputConsumer.newInstance(activityControl, false);
            return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false);
        } else {
            return createOtherActivityInputConsumer(event, runningTaskInfo);
        }
+1 −1
Original line number Diff line number Diff line
@@ -738,7 +738,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
            setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
        }

        return OverviewInputConsumer.newInstance(mActivityControlHelper, true);
        return OverviewInputConsumer.newInstance(mActivityControlHelper, null, true);
    }

    @UiThread
+1 −28
Original line number Diff line number Diff line
@@ -17,18 +17,13 @@ package com.android.quickstep.fallback;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewDebug;
import android.view.WindowInsets;

import com.android.launcher3.BaseActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
@@ -39,9 +34,6 @@ public class RecentsRootView extends BaseDragLayer<RecentsActivity> {
    private static final int MIN_SIZE = 10;
    private final RecentsActivity mActivity;

    @ViewDebug.ExportedProperty(category = "launcher")
    private final RectF mTouchExcludeRegion = new RectF();

    private final Point mLastKnownSize = new Point(MIN_SIZE, MIN_SIZE);

    public RecentsRootView(Context context, AttributeSet attrs) {
@@ -100,26 +92,7 @@ public class RecentsRootView extends BaseDragLayer<RecentsActivity> {

    @Override
    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
        if (Utilities.ATLEAST_Q) {
            Insets gestureInsets = insets.getMandatorySystemGestureInsets();
            mTouchExcludeRegion.set(gestureInsets.left, gestureInsets.top,
                    gestureInsets.right, gestureInsets.bottom);
        }
        updateTouchExcludeRegion(insets);
        return super.dispatchApplyWindowInsets(insets);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            float x = ev.getX();
            float y = ev.getY();
            if (y < mTouchExcludeRegion.top
                    || x < mTouchExcludeRegion.left
                    || x > (getWidth() - mTouchExcludeRegion.right)
                    || y > (getHeight() - mTouchExcludeRegion.bottom)) {
                return false;
            }
        }
        return super.dispatchTouchEvent(ev);
    }
}
 No newline at end of file
+1 −26
Original line number Diff line number Diff line
@@ -8,13 +8,10 @@ import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.WindowInsets;
@@ -31,9 +28,6 @@ public class LauncherRootView extends InsettableFrameLayout {
    @ViewDebug.ExportedProperty(category = "launcher")
    private final Rect mConsumedInsets = new Rect();

    @ViewDebug.ExportedProperty(category = "launcher")
    private final RectF mTouchExcludeRegion = new RectF();

    @ViewDebug.ExportedProperty(category = "launcher")
    private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
            Collections.singletonList(new Rect());
@@ -164,29 +158,10 @@ public class LauncherRootView extends InsettableFrameLayout {

    @Override
    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
        if (Utilities.ATLEAST_Q) {
            Insets gestureInsets = insets.getMandatorySystemGestureInsets();
            mTouchExcludeRegion.set(gestureInsets.left, gestureInsets.top,
                    gestureInsets.right, gestureInsets.bottom);
        }
        mLauncher.getDragLayer().updateTouchExcludeRegion(insets);
        return super.dispatchApplyWindowInsets(insets);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            float x = ev.getX();
            float y = ev.getY();
            if (y < mTouchExcludeRegion.top
                    || x < mTouchExcludeRegion.left
                    || x > (getWidth() - mTouchExcludeRegion.right)
                    || y > (getHeight() - mTouchExcludeRegion.bottom)) {
                return false;
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
Loading