diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index b9f95ccfa4..cded799831 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -19,7 +19,7 @@ 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_POINTER_DOWN; -import static android.view.MotionEvent.ACTION_POINTER_UP; +import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT; import static android.view.MotionEvent.ACTION_UP; import static com.android.systemui.shared.system.ActivityManagerWrapper @@ -52,6 +52,7 @@ import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.ChoreographerCompat; import com.android.systemui.shared.system.NavigationBarCompat.HitTarget; + import java.io.FileDescriptor; import java.io.PrintWriter; @@ -299,7 +300,7 @@ public class TouchInteractionService extends Service { mActivityHelper = activityHelper; mActivity = activity; mTarget = activity.getDragLayer(); - mTouchSlop = ViewConfiguration.get(mTarget.getContext()).getScaledTouchSlop(); + mTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop(); mStartingInActivityBounds = startingInActivityBounds; mQuickScrubController = mActivity.getOverviewPanel() @@ -324,12 +325,6 @@ public class TouchInteractionService extends Service { mDownPos.set(ev.getX(), ev.getY()); } else if (!mTrackingStarted) { switch (action) { - case ACTION_POINTER_UP: - case ACTION_POINTER_DOWN: - if (!mTrackingStarted) { - mInvalidated = true; - } - break; case ACTION_CANCEL: case ACTION_UP: startTouchTracking(ev, true /* updateLocationOffset */); @@ -359,15 +354,26 @@ public class TouchInteractionService extends Service { } // Send down touch event - MotionEvent down = MotionEvent.obtain(ev); + MotionEvent down = MotionEvent.obtainNoHistory(ev); down.setAction(ACTION_DOWN); sendEvent(down); - down.recycle(); mTrackingStarted = true; + // Send pointer down for remaining pointers. + int pointerCount = ev.getPointerCount(); + for (int i = 1; i < pointerCount; i++) { + down.setAction(ACTION_POINTER_DOWN | (i << ACTION_POINTER_INDEX_SHIFT)); + sendEvent(down); + } + + down.recycle(); } private void sendEvent(MotionEvent ev) { + if (!mTarget.verifyTouchDispatch(this, ev)) { + mInvalidated = true; + return; + } int flags = ev.getEdgeFlags(); ev.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR); ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]); diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java index 1faca152b6..5b8df1399d 100644 --- a/src/com/android/launcher3/views/BaseDragLayer.java +++ b/src/com/android/launcher3/views/BaseDragLayer.java @@ -16,6 +16,10 @@ package com.android.launcher3.views; +import static android.view.MotionEvent.ACTION_CANCEL; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_UP; + import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import android.content.Context; @@ -79,6 +83,9 @@ public abstract class BaseDragLayer protected TouchController mActiveController; private TouchCompleteListener mTouchCompleteListener; + // Object controlling the current touch interaction + private Object mCurrentTouchOwner; + public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) { super(context, attrs); mActivity = (T) ActivityContext.lookupContext(context); @@ -94,7 +101,7 @@ public abstract class BaseDragLayer public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); - if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (action == ACTION_UP || action == ACTION_CANCEL) { if (mTouchCompleteListener != null) { mTouchCompleteListener.onTouchComplete(); } @@ -177,7 +184,7 @@ public abstract class BaseDragLayer @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); - if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (action == ACTION_UP || action == ACTION_CANCEL) { if (mTouchCompleteListener != null) { mTouchCompleteListener.onTouchComplete(); } @@ -192,6 +199,37 @@ public abstract class BaseDragLayer } } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return verifyTouchDispatch(this, ev) && super.dispatchTouchEvent(ev); + } + + /** + * Returns true if the {@param caller} is allowed to dispatch {@param ev} on this view, + * false otherwise. + */ + public boolean verifyTouchDispatch(Object caller, MotionEvent ev) { + int action = ev.getAction(); + if (action == ACTION_DOWN) { + if (mCurrentTouchOwner != null) { + // Another touch in progress. + ev.setAction(ACTION_CANCEL); + super.dispatchTouchEvent(ev); + ev.setAction(action); + } + mCurrentTouchOwner = caller; + return true; + } + if (mCurrentTouchOwner != caller) { + // Someone else is controlling the touch + return false; + } + if (action == ACTION_UP || action == ACTION_CANCEL) { + mCurrentTouchOwner = null; + } + return true; + } + /** * Determine the rect of the descendant in this DragLayer's coordinates *