Forwarding touch events from TouchInteractionService to Launcher
when launcher window is visible Change-Id: I418994c2e2a5559c28c36875ac7aff589a15fac5
This commit is contained in:
parent
635329a5ab
commit
0607cf03ea
|
@ -62,6 +62,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks {
|
|||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mSnapshotView = findViewById(R.id.snapshot);
|
||||
mIconView = findViewById(R.id.icon);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,15 @@
|
|||
*/
|
||||
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_POINTER_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static android.view.MotionEvent.INVALID_POINTER_ID;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.Service;
|
||||
|
@ -29,6 +36,7 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
|
@ -37,9 +45,12 @@ import android.view.Choreographer;
|
|||
import android.view.Display;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.MainThreadExecutor;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
|
@ -51,9 +62,12 @@ import com.android.systemui.shared.recents.model.RecentsTaskLoader;
|
|||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.BackgroundExecutor;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Service connected by system-UI for handling touch interaction.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class TouchInteractionService extends Service {
|
||||
|
||||
private static final String TAG = "TouchInteractionService";
|
||||
|
@ -73,6 +87,10 @@ public class TouchInteractionService extends Service {
|
|||
}
|
||||
};
|
||||
|
||||
private final Consumer<MotionEvent> mOtherActivityTouchConsumer
|
||||
= this::handleTouchDownOnOtherActivity;
|
||||
private final Consumer<MotionEvent> mNoOpTouchConsumer = (ev) -> {};
|
||||
|
||||
private ActivityManagerWrapper mAM;
|
||||
private RunningTaskInfo mRunningTask;
|
||||
private Intent mHomeIntent;
|
||||
|
@ -80,8 +98,6 @@ public class TouchInteractionService extends Service {
|
|||
private MotionEventQueue mEventQueue;
|
||||
private MainThreadExecutor mMainThreadExecutor;
|
||||
|
||||
private int mDisplayRotation;
|
||||
private final Point mDisplaySize = new Point();
|
||||
private final PointF mDownPos = new PointF();
|
||||
private final PointF mLastPos = new PointF();
|
||||
private int mActivePointerId = INVALID_POINTER_ID;
|
||||
|
@ -90,6 +106,7 @@ public class TouchInteractionService extends Service {
|
|||
private NavBarSwipeInteractionHandler mInteractionHandler;
|
||||
|
||||
private ISystemUiProxy mISystemUiProxy;
|
||||
private Consumer<MotionEvent> mCurrentConsumer = mNoOpTouchConsumer;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
|
@ -127,25 +144,31 @@ public class TouchInteractionService extends Service {
|
|||
}
|
||||
|
||||
private void handleMotionEvent(MotionEvent ev) {
|
||||
if (ev.getActionMasked() != MotionEvent.ACTION_DOWN && mVelocityTracker == null) {
|
||||
if (ev.getActionMasked() == ACTION_DOWN) {
|
||||
mRunningTask = mAM.getRunningTask();
|
||||
|
||||
if (mRunningTask == null) {
|
||||
mCurrentConsumer = mNoOpTouchConsumer;
|
||||
} else if (mRunningTask.topActivity.equals(mLauncher)) {
|
||||
mCurrentConsumer = getLauncherConsumer();
|
||||
} else {
|
||||
mCurrentConsumer = mOtherActivityTouchConsumer;
|
||||
}
|
||||
}
|
||||
mCurrentConsumer.accept(ev);
|
||||
}
|
||||
|
||||
private void handleTouchDownOnOtherActivity(MotionEvent ev) {
|
||||
if (ev.getActionMasked() != ACTION_DOWN && mVelocityTracker == null) {
|
||||
return;
|
||||
}
|
||||
switch (ev.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
case ACTION_DOWN: {
|
||||
TraceHelper.beginSection("TouchInt");
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
mDownPos.set(ev.getX(), ev.getY());
|
||||
mLastPos.set(mDownPos);
|
||||
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
|
||||
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
|
||||
display.getRealSize(mDisplaySize);
|
||||
mDisplayRotation = display.getRotation();
|
||||
|
||||
mRunningTask = mAM.getRunningTask();
|
||||
if (mRunningTask == null || mRunningTask.topActivity.equals(mLauncher)) {
|
||||
// TODO: We could drive all-apps in this case. For now just ignore swipe.
|
||||
break;
|
||||
}
|
||||
|
||||
if (mVelocityTracker == null) {
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
|
@ -159,7 +182,7 @@ public class TouchInteractionService extends Service {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_POINTER_UP: {
|
||||
case ACTION_POINTER_UP: {
|
||||
int ptrIdx = ev.getActionIndex();
|
||||
int ptrId = ev.getPointerId(ptrIdx);
|
||||
if (ptrId == mActivePointerId) {
|
||||
|
@ -173,7 +196,7 @@ public class TouchInteractionService extends Service {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
case ACTION_MOVE: {
|
||||
int pointerIndex = ev.findPointerIndex(mActivePointerId);
|
||||
if (pointerIndex == INVALID_POINTER_ID) {
|
||||
break;
|
||||
|
@ -192,17 +215,19 @@ public class TouchInteractionService extends Service {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
case ACTION_CANCEL:
|
||||
// TODO: Should be different than ACTION_UP
|
||||
case MotionEvent.ACTION_UP: {
|
||||
case ACTION_UP: {
|
||||
TraceHelper.endSection("TouchInt");
|
||||
|
||||
endInteraction();
|
||||
mCurrentConsumer = mNoOpTouchConsumer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void startTouchTracking() {
|
||||
// Create the shared handler
|
||||
final NavBarSwipeInteractionHandler handler =
|
||||
|
@ -260,9 +285,12 @@ public class TouchInteractionService extends Service {
|
|||
|
||||
TraceHelper.beginSection("TaskSnapshot");
|
||||
// TODO: We are using some hardcoded layers for now, to best approximate the activity layers
|
||||
Point displaySize = new Point();
|
||||
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
|
||||
display.getRealSize(displaySize);
|
||||
try {
|
||||
return mISystemUiProxy.screenshot(new Rect(), mDisplaySize.x, mDisplaySize.y, 0, 100000,
|
||||
false, mDisplayRotation).toBitmap();
|
||||
return mISystemUiProxy.screenshot(new Rect(), displaySize.x, displaySize.y, 0, 100000,
|
||||
false, display.getRotation()).toBitmap();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error capturing snapshot", e);
|
||||
return null;
|
||||
|
@ -270,4 +298,76 @@ public class TouchInteractionService extends Service {
|
|||
TraceHelper.endSection("TaskSnapshot");
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<MotionEvent> getLauncherConsumer() {
|
||||
|
||||
Launcher launcher = (Launcher) LauncherAppState.getInstance(this).getModel().getCallback();
|
||||
if (launcher == null) {
|
||||
return mNoOpTouchConsumer;
|
||||
}
|
||||
|
||||
View target = launcher.getDragLayer();
|
||||
if (!target.getWindowId().isFocused()) {
|
||||
return mNoOpTouchConsumer;
|
||||
}
|
||||
return new LauncherTouchConsumer(target);
|
||||
}
|
||||
|
||||
private class LauncherTouchConsumer implements Consumer<MotionEvent> {
|
||||
|
||||
private final View mTarget;
|
||||
private final int[] mLocationOnScreen = new int[2];
|
||||
|
||||
private boolean mTrackingStarted = false;
|
||||
|
||||
LauncherTouchConsumer(View target) {
|
||||
mTarget = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MotionEvent ev) {
|
||||
int action = ev.getActionMasked();
|
||||
if (action == ACTION_DOWN) {
|
||||
mTrackingStarted = false;
|
||||
mDownPos.set(ev.getX(), ev.getY());
|
||||
mTouchSlop = ViewConfiguration.get(mTarget.getContext()).getScaledTouchSlop();
|
||||
} else if (!mTrackingStarted) {
|
||||
switch (action) {
|
||||
case ACTION_POINTER_UP:
|
||||
case ACTION_POINTER_DOWN:
|
||||
if (!mTrackingStarted) {
|
||||
mCurrentConsumer = mNoOpTouchConsumer;
|
||||
}
|
||||
break;
|
||||
case ACTION_MOVE: {
|
||||
float displacement = ev.getY() - mDownPos.y;
|
||||
if (Math.abs(displacement) >= mTouchSlop) {
|
||||
mTrackingStarted = true;
|
||||
mTarget.getLocationOnScreen(mLocationOnScreen);
|
||||
|
||||
// Send a down event only when mTouchSlop is crossed.
|
||||
MotionEvent down = MotionEvent.obtain(ev);
|
||||
down.setAction(ACTION_DOWN);
|
||||
sendEvent(down);
|
||||
down.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mTrackingStarted) {
|
||||
sendEvent(ev);
|
||||
}
|
||||
|
||||
if (action == ACTION_UP || action == ACTION_CANCEL) {
|
||||
mCurrentConsumer = mNoOpTouchConsumer;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendEvent(MotionEvent ev) {
|
||||
ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
|
||||
mTarget.dispatchTouchEvent(ev);
|
||||
ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue