diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 7563c3f55d..294a997f3d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -58,6 +58,8 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.WindowManager; +import androidx.annotation.BinderThread; + import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; import com.android.launcher3.ResourceUtils; @@ -84,6 +86,7 @@ import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputMonitorCompat; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags; +import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -268,6 +271,9 @@ public class TouchInteractionService extends Service implements private final RectF mSwipeTouchRegion = new RectF(); private ComponentName mGestureBlockingActivity; + private Region mExclusionRegion; + private SystemGestureExclusionListenerCompat mExclusionListener; + @Override public void onCreate() { super.onCreate(); @@ -284,14 +290,23 @@ public class TouchInteractionService extends Service implements mIsUserUnlocked = false; registerReceiver(mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED)); } - onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this)); mDefaultDisplayId = getSystemService(WindowManager.class).getDefaultDisplay() .getDisplayId(); - String blockingActivity = getString(R.string.gesture_blocking_activity); mGestureBlockingActivity = TextUtils.isEmpty(blockingActivity) ? null : ComponentName.unflattenFromString(blockingActivity); + + mExclusionListener = new SystemGestureExclusionListenerCompat(mDefaultDisplayId) { + @Override + @BinderThread + public void onExclusionChanged(Region region) { + // Assignments are atomic, it should be safe on binder thread + mExclusionRegion = region; + } + }; + + onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this)); sConnected = true; } @@ -370,6 +385,12 @@ public class TouchInteractionService extends Service implements disposeEventHandlers(); initInputMonitor(); + + if (mMode == Mode.NO_BUTTON) { + mExclusionListener.register(); + } else { + mExclusionListener.unregister(); + } } @Override @@ -437,6 +458,7 @@ public class TouchInteractionService extends Service implements sConnected = false; Utilities.unregisterReceiverSafely(this, mUserUnlockedReceiver); SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this); + mExclusionListener.unregister(); super.onDestroy(); } @@ -557,10 +579,15 @@ public class TouchInteractionService extends Service implements final ActivityControlHelper activityControl = mOverviewComponentObserver.getActivityControlHelper(); boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event); + + // mExclusionRegion can change on binder thread, use a local instance here. + Region exclusionRegion = mExclusionRegion; + boolean disableHorizontalSwipe = mMode == Mode.NO_BUTTON && exclusionRegion != null + && exclusionRegion.contains((int) event.getX(), (int) event.getY()); return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel, mOverviewComponentObserver.getOverviewIntent(), activityControl, shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive, - mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion); + mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, disableHorizontalSwipe); } private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index b0acffa398..0ed4c99a6f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -111,6 +111,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC private final float mDragSlop; private final float mSquaredTouchSlop; + private final boolean mDisableHorizontalSwipe; // Slop used to check when we start moving window. private boolean mPassedDragSlop; @@ -132,7 +133,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC InputConsumerController inputConsumer, Consumer onCompleteCallback, SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat, - RectF swipeTouchRegion) { + RectF swipeTouchRegion, boolean disableHorizontalSwipe) { super(base); mMainThreadHandler = new Handler(Looper.getMainLooper()); @@ -162,6 +163,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mSquaredTouchSlop = slop * slop; mPassedTouchSlop = mPassedDragSlop = continuingPreviousGesture; + mDisableHorizontalSwipe = !mPassedTouchSlop && disableHorizontalSwipe; } @Override @@ -169,6 +171,13 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC return TYPE_OTHER_ACTIVITY; } + private void forceCancelGesture(MotionEvent ev) { + int action = ev.getAction(); + ev.setAction(ACTION_CANCEL); + finishTouchTracking(ev); + ev.setAction(action); + } + @Override public void onMotionEvent(MotionEvent ev) { if (mVelocityTracker == null) { @@ -216,10 +225,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC // Cancel interaction in case of multi-touch interaction int ptrIdx = ev.getActionIndex(); if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) { - int action = ev.getAction(); - ev.setAction(ACTION_CANCEL); - finishTouchTracking(ev); - ev.setAction(action); + forceCancelGesture(ev); } } break; @@ -258,7 +264,15 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC } if (!mPassedTouchSlop) { - if (squaredHypot(displacementX, mLastPos.y - mDownPos.y) >= mSquaredTouchSlop) { + float displacementY = mLastPos.y - mDownPos.y; + if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) { + if (mDisableHorizontalSwipe + && Math.abs(displacementX) > Math.abs(displacementY)) { + // Horizontal gesture is not allowed in this region + forceCancelGesture(ev); + break; + } + mPassedTouchSlop = true; if (mIsDeferredDownTarget) {