diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-07-02 04:25:22 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-07-02 04:25:22 +0000 |
commit | 80b93eb963036610ead64a73ed0448b9062c5c36 (patch) | |
tree | 1f2e57c92604850a2352915e5cd07e242730be73 | |
parent | b60777d0e6e5595babbdb685b3aff30352c7ff6d (diff) | |
parent | a0967d21e645569b844e2ab5b22e843689525ce9 (diff) | |
download | android_packages_apps_Trebuchet-80b93eb963036610ead64a73ed0448b9062c5c36.tar.gz android_packages_apps_Trebuchet-80b93eb963036610ead64a73ed0448b9062c5c36.tar.bz2 android_packages_apps_Trebuchet-80b93eb963036610ead64a73ed0448b9062c5c36.zip |
Snap for 5702458 from a0967d21e645569b844e2ab5b22e843689525ce9 to qt-release
Change-Id: Ia11ae0fb421acfc84ac062f284f561ec90895b27
13 files changed, 346 insertions, 57 deletions
diff --git a/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java b/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java index eb0c5b942..057b48bb2 100644 --- a/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java +++ b/go/quickstep/src/com/android/quickstep/FallbackActivityControllerHelper.java @@ -113,4 +113,7 @@ public final class FallbackActivityControllerHelper extends public int getContainerType() { return LauncherLogProto.ContainerType.SIDELOADED_LAUNCHER; } + + @Override + public void onLaunchTaskSuccess(RecentsActivity activity) { } } diff --git a/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java index d5950077d..b0d9cda6b 100644 --- a/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -104,4 +104,9 @@ public final class LauncherActivityControllerHelper extends GoActivityControlHel return launcher != null ? launcher.getStateManager().getState().containerType : LauncherLogProto.ContainerType.APP; } + + @Override + public void onLaunchTaskSuccess(Launcher launcher) { + launcher.getStateManager().moveToRestState(); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java index d14de70c5..5ee08c12d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java @@ -81,7 +81,8 @@ public class BackgroundAppState extends OverviewState { @Override public int getVisibleElements(Launcher launcher) { - return super.getVisibleElements(launcher) & ~RECENTS_CLEAR_ALL_BUTTON; + return super.getVisibleElements(launcher) + & ~RECENTS_CLEAR_ALL_BUTTON & ~VERTICAL_SWIPE_INDICATOR; } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java index cdc271fdd..6c9f46fc4 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java @@ -57,6 +57,8 @@ public class QuickSwitchState extends BackgroundAppState { if (!success) { launcher.getStateManager().goToState(OVERVIEW); tasktolaunch.notifyTaskLaunchFailed(TAG); + } else { + launcher.getStateManager().moveToRestState(); } }, new Handler(Looper.getMainLooper())); } else { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java index 4ae6d87b8..c43155b73 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java @@ -230,4 +230,9 @@ public final class FallbackActivityControllerHelper implements // TODO: probably go back to overview instead. activity.<RecentsView>getOverviewPanel().startHome(); } + + @Override + public void onLaunchTaskSuccess(RecentsActivity activity) { + activity.onTaskLaunched(); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index 07c049642..b2a71a488 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -488,4 +488,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe public void onLaunchTaskFailed(Launcher launcher) { launcher.getStateManager().goToState(OVERVIEW); } + + @Override + public void onLaunchTaskSuccess(Launcher launcher) { + launcher.getStateManager().moveToRestState(); + } }
\ No newline at end of file diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java index 32a92618a..fc29a5663 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java @@ -177,4 +177,8 @@ public final class RecentsActivity extends BaseRecentsActivity { super.onStart(); mFallbackRecentsView.resetTaskVisuals(); } + + public void onTaskLaunched() { + mFallbackRecentsView.resetTaskVisuals(); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index e9aa6d078..f1d1141bc 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -1259,6 +1259,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> mActivityControlHelper.onLaunchTaskFailed(mActivity); nextTask.notifyTaskLaunchFailed(TAG); updateSysUiFlags(1 /* windowProgress == overview */); + } else { + mActivityControlHelper.onLaunchTaskSuccess(mActivity); } }, mMainThreadHandler); doLogGesture(NEW_TASK); diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 71259fd7a..b0968f94c 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -38,7 +38,7 @@ <dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen> <dimen name="motion_pause_detector_speed_slow">0.15dp</dimen> <dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen> - <dimen name="motion_pause_detector_speed_fast">0.5dp</dimen> + <dimen name="motion_pause_detector_speed_fast">1.4dp</dimen> <dimen name="motion_pause_detector_min_displacement_from_app">36dp</dimen> <!-- Launcher app transition --> diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java index f5ba3725d..fee18204e 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java @@ -17,22 +17,17 @@ package com.android.launcher3.uioverrides.touchcontrollers; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_MOVE; -import static android.view.MotionEvent.ACTION_UP; -import static android.view.MotionEvent.ACTION_CANCEL; -import android.graphics.PointF; import android.os.RemoteException; import android.util.Log; -import android.util.SparseArray; import android.view.MotionEvent; import android.view.ViewConfiguration; -import android.view.Window; -import android.view.WindowManager; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.touch.TouchEventTranslator; import com.android.launcher3.util.TouchController; import com.android.quickstep.RecentsModel; import com.android.systemui.shared.recents.ISystemUiProxy; @@ -41,29 +36,18 @@ import java.io.PrintWriter; /** * TouchController for handling touch events that get sent to the StatusBar. Once the - * Once the event delta mDownY passes the touch slop, the events start getting forwarded. + * Once the event delta y passes the touch slop, the events start getting forwarded. * All events are offset by initial Y value of the pointer. */ public class StatusBarTouchController implements TouchController { private static final String TAG = "StatusBarController"; - /** - * Window flag: Enable touches to slide out of a window into neighboring - * windows in mid-gesture instead of being captured for the duration of - * the gesture. - * - * This flag changes the behavior of touch focus for this window only. - * Touches can slide out of the window but they cannot necessarily slide - * back in (unless the other window with touch focus permits it). - */ - private static final int FLAG_SLIPPERY = 0x20000000; - protected final Launcher mLauncher; + protected final TouchEventTranslator mTranslator; private final float mTouchSlop; private ISystemUiProxy mSysUiProxy; private int mLastAction; - private final SparseArray<PointF> mDownEvents; /* If {@code false}, this controller should not handle the input {@link MotionEvent}.*/ private boolean mCanIntercept; @@ -72,7 +56,7 @@ public class StatusBarTouchController implements TouchController { mLauncher = l; // Guard against TAPs by increasing the touch slop. mTouchSlop = 2 * ViewConfiguration.get(l).getScaledTouchSlop(); - mDownEvents = new SparseArray<>(); + mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev)); } @Override @@ -80,6 +64,7 @@ public class StatusBarTouchController implements TouchController { writer.println(prefix + "mCanIntercept:" + mCanIntercept); writer.println(prefix + "mLastAction:" + MotionEvent.actionToString(mLastAction)); writer.println(prefix + "mSysUiProxy available:" + (mSysUiProxy != null)); + } private void dispatchTouchEvent(MotionEvent ev) { @@ -96,31 +81,26 @@ public class StatusBarTouchController implements TouchController { @Override public final boolean onControllerInterceptTouchEvent(MotionEvent ev) { int action = ev.getActionMasked(); - int idx = ev.getActionIndex(); - int pid = ev.getPointerId(idx); if (action == ACTION_DOWN) { mCanIntercept = canInterceptTouch(ev); if (!mCanIntercept) { return false; } - mDownEvents.put(pid, new PointF(ev.getX(), ev.getY())); + mTranslator.reset(); + mTranslator.setDownParameters(0, ev); } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { - // Check!! should only set it only when threshold is not entered. - mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx))); + // Check!! should only set it only when threshold is not entered. + mTranslator.setDownParameters(ev.getActionIndex(), ev); } if (!mCanIntercept) { return false; } if (action == ACTION_MOVE) { - float dy = ev.getY(idx) - mDownEvents.get(pid).y; - float dx = ev.getX(idx) - mDownEvents.get(pid).x; - // Currently input dispatcher will not do touch transfer if there are more than - // one touch pointer. Hence, even if slope passed, only set the slippery flag - // when there is single touch event. (context: InputDispatcher.cpp line 1445) - if (dy > mTouchSlop && dy > Math.abs(dx) && ev.getPointerCount() == 1) { - ev.setAction(ACTION_DOWN); - dispatchTouchEvent(ev); - setWindowSlippery(true); + float dy = ev.getY() - mTranslator.getDownY(); + float dx = ev.getX() - mTranslator.getDownX(); + if (dy > mTouchSlop && dy > Math.abs(dx)) { + mTranslator.dispatchDownEvents(ev); + mTranslator.processMotionEvent(ev); return true; } if (Math.abs(dx) > mTouchSlop) { @@ -130,27 +110,13 @@ public class StatusBarTouchController implements TouchController { return false; } + @Override public final boolean onControllerTouchEvent(MotionEvent ev) { - if (ev.getAction() == ACTION_UP || ev.getAction() == ACTION_CANCEL) { - dispatchTouchEvent(ev); - setWindowSlippery(false); - return true; - } + mTranslator.processMotionEvent(ev); return true; } - private void setWindowSlippery(boolean enable) { - Window w = mLauncher.getWindow(); - WindowManager.LayoutParams wlp = w.getAttributes(); - if (enable) { - wlp.flags |= FLAG_SLIPPERY; - } else { - wlp.flags &= ~FLAG_SLIPPERY; - } - w.setAttributes(wlp); - } - private boolean canInterceptTouch(MotionEvent ev) { if (!mLauncher.isInState(LauncherState.NORMAL) || AbstractFloatingView.getTopOpenViewWithType(mLauncher, @@ -166,4 +132,4 @@ public class StatusBarTouchController implements TouchController { mSysUiProxy = RecentsModel.INSTANCE.get(mLauncher).getSystemUiProxy(); return mSysUiProxy != null; } -}
\ No newline at end of file +} diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index 8675c3e02..cd2c9cb1b 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -95,6 +95,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> { void onLaunchTaskFailed(T activity); + void onLaunchTaskSuccess(T activity); + interface ActivityInitListener { void register(); diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java index b6ddb5fd1..63c8023f6 100644 --- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -15,6 +15,7 @@ */ package com.android.quickstep.views; +import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.anim.Interpolators.ACCEL; @@ -29,6 +30,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.Path.Direction; import android.graphics.Path.Op; +import android.graphics.Rect; import android.util.AttributeSet; import android.view.animation.Interpolator; @@ -36,6 +38,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.uioverrides.states.OverviewState; import com.android.launcher3.util.Themes; import com.android.launcher3.views.ScrimView; import com.android.quickstep.SysUINavigationMode; @@ -145,14 +148,22 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis mRemainingScreenPathValid = false; mShiftRange = mLauncher.getAllAppsController().getShiftRange(); - mMidProgress = OVERVIEW.getVerticalProgress(mLauncher); - mMidAlpha = mMidProgress >= 1 ? 0 - : Themes.getAttrInteger(getContext(), R.attr.allAppsInterimScrimAlpha); + if ((OVERVIEW.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) == 0) { + mMidProgress = 1; + mMidAlpha = 0; + } else { + mMidAlpha = Themes.getAttrInteger(getContext(), R.attr.allAppsInterimScrimAlpha); + Rect hotseatPadding = dp.getHotseatLayoutPadding(); + int hotseatSize = dp.hotseatBarSizePx + dp.getInsets().bottom + - hotseatPadding.bottom - hotseatPadding.top; + float arrowTop = Math.min(hotseatSize, OverviewState.getDefaultSwipeHeight(dp)); + mMidProgress = 1 - (arrowTop / mShiftRange); + } mTopOffset = dp.getInsets().top - mShelfOffset; mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset; - updateColors(); } + updateColors(); updateDragHandleAlpha(); invalidate(); } diff --git a/src/com/android/launcher3/touch/TouchEventTranslator.java b/src/com/android/launcher3/touch/TouchEventTranslator.java new file mode 100644 index 000000000..3fcda9084 --- /dev/null +++ b/src/com/android/launcher3/touch/TouchEventTranslator.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.touch; + +import android.graphics.PointF; +import android.util.Log; +import android.util.Pair; +import android.util.SparseArray; +import android.view.MotionEvent; +import android.view.MotionEvent.PointerCoords; +import android.view.MotionEvent.PointerProperties; + +import java.util.function.Consumer; + +/** + * To minimize the size of the MotionEvent, historic events are not copied and passed via the + * listener. + */ +public class TouchEventTranslator { + + private static final String TAG = "TouchEventTranslator"; + private static final boolean DEBUG = false; + + private class DownState { + long timeStamp; + float downX; + float downY; + public DownState(long timeStamp, float downX, float downY) { + this.timeStamp = timeStamp; + this.downX = downX; + this.downY = downY; + } + }; + private final DownState ZERO = new DownState(0, 0f, 0f); + + private final Consumer<MotionEvent> mListener; + + private final SparseArray<DownState> mDownEvents; + private final SparseArray<PointF> mFingers; + + private final SparseArray<Pair<PointerProperties[], PointerCoords[]>> mCache; + + public TouchEventTranslator(Consumer<MotionEvent> listener) { + mDownEvents = new SparseArray<>(); + mFingers = new SparseArray<>(); + mCache = new SparseArray<>(); + + mListener = listener; + } + + public void reset() { + mDownEvents.clear(); + mFingers.clear(); + } + + public float getDownX() { + return mDownEvents.get(0).downX; + } + + public float getDownY() { + return mDownEvents.get(0).downY; + } + + public void setDownParameters(int idx, MotionEvent e) { + DownState ev = new DownState(e.getEventTime(), e.getX(idx), e.getY(idx)); + mDownEvents.append(idx, ev); + } + + public void dispatchDownEvents(MotionEvent ev) { + for(int i = 0; i < ev.getPointerCount() && i < mDownEvents.size(); i++) { + int pid = ev.getPointerId(i); + put(pid, i, ev.getX(i), 0, mDownEvents.get(i).timeStamp, ev); + } + } + + public void processMotionEvent(MotionEvent ev) { + if (DEBUG) { + printSamples(TAG + " processMotionEvent", ev); + } + int index = ev.getActionIndex(); + float x = ev.getX(index); + float y = ev.getY(index) - mDownEvents.get(index, ZERO).downY; + switch (ev.getActionMasked()) { + case MotionEvent.ACTION_POINTER_DOWN: + int pid = ev.getPointerId(index); + if(mFingers.get(pid, null) != null) { + for(int i=0; i < ev.getPointerCount(); i++) { + pid = ev.getPointerId(i); + position(pid, x, y); + } + generateEvent(ev.getAction(), ev); + } else { + put(pid, index, x, y, ev); + } + break; + case MotionEvent.ACTION_MOVE: + for(int i=0; i < ev.getPointerCount(); i++) { + pid = ev.getPointerId(i); + position(pid, x, y); + } + generateEvent(ev.getAction(), ev); + break; + case MotionEvent.ACTION_POINTER_UP: + case MotionEvent.ACTION_UP: + pid = ev.getPointerId(index); + lift(pid, index, x, y, ev); + break; + case MotionEvent.ACTION_CANCEL: + cancel(ev); + break; + default: + Log.v(TAG, "Didn't process "); + printSamples(TAG, ev); + + } + } + + private TouchEventTranslator put(int id, int index, float x, float y, MotionEvent ev) { + return put(id, index, x, y, ev.getEventTime(), ev); + } + + private TouchEventTranslator put(int id, int index, float x, float y, long ms, MotionEvent ev) { + checkFingerExistence(id, false); + boolean isInitialDown = (mFingers.size() == 0); + + mFingers.put(id, new PointF(x, y)); + int n = mFingers.size(); + + if (mCache.get(n) == null) { + PointerProperties[] properties = new PointerProperties[n]; + PointerCoords[] coords = new PointerCoords[n]; + for (int i = 0; i < n; i++) { + properties[i] = new PointerProperties(); + coords[i] = new PointerCoords(); + } + mCache.put(n, new Pair(properties, coords)); + } + + int action; + if (isInitialDown) { + action = MotionEvent.ACTION_DOWN; + } else { + action = MotionEvent.ACTION_POINTER_DOWN; + // Set the id of the changed pointer. + action |= index << MotionEvent.ACTION_POINTER_INDEX_SHIFT; + } + generateEvent(action, ms, ev); + return this; + } + + public TouchEventTranslator position(int id, float x, float y) { + checkFingerExistence(id, true); + mFingers.get(id).set(x, y); + return this; + } + + private TouchEventTranslator lift(int id, int index, MotionEvent ev) { + checkFingerExistence(id, true); + boolean isFinalUp = (mFingers.size() == 1); + int action; + if (isFinalUp) { + action = MotionEvent.ACTION_UP; + } else { + action = MotionEvent.ACTION_POINTER_UP; + // Set the id of the changed pointer. + action |= index << MotionEvent.ACTION_POINTER_INDEX_SHIFT; + } + generateEvent(action, ev); + mFingers.remove(id); + return this; + } + + private TouchEventTranslator lift(int id, int index, float x, float y, MotionEvent ev) { + checkFingerExistence(id, true); + mFingers.get(id).set(x, y); + return lift(id, index, ev); + } + + public TouchEventTranslator cancel(MotionEvent ev) { + generateEvent(MotionEvent.ACTION_CANCEL, ev); + mFingers.clear(); + return this; + } + + private void checkFingerExistence(int id, boolean shouldExist) { + if (shouldExist != (mFingers.get(id, null) != null)) { + throw new IllegalArgumentException( + shouldExist ? "Finger does not exist" : "Finger already exists"); + } + } + + + /** + * Used to debug MotionEvents being sent/received. + */ + public void printSamples(String msg, MotionEvent ev) { + System.out.printf("%s %s", msg, MotionEvent.actionToString(ev.getActionMasked())); + final int pointerCount = ev.getPointerCount(); + System.out.printf("#%d/%d", ev.getActionIndex(), pointerCount); + System.out.printf(" t=%d:", ev.getEventTime()); + for (int p = 0; p < pointerCount; p++) { + System.out.printf(" id=%d: (%f,%f)", + ev.getPointerId(p), ev.getX(p), ev.getY(p)); + } + System.out.println(); + } + + private void generateEvent(int action, MotionEvent ev) { + generateEvent(action, ev.getEventTime(), ev); + } + + private void generateEvent(int action, long ms, MotionEvent ev) { + Pair<PointerProperties[], PointerCoords[]> state = getFingerState(); + MotionEvent event = MotionEvent.obtain( + mDownEvents.get(0).timeStamp, + ms, + action, + state.first.length, + state.first, + state.second, + ev.getMetaState(), + ev.getButtonState() /* buttonState */, + ev.getXPrecision() /* xPrecision */, + ev.getYPrecision() /* yPrecision */, + ev.getDeviceId(), + ev.getEdgeFlags(), + ev.getSource(), + ev.getFlags() /* flags */); + if (DEBUG) { + printSamples(TAG + " generateEvent", event); + } + if (event.getPointerId(event.getActionIndex()) < 0) { + printSamples(TAG + "generateEvent", event); + throw new IllegalStateException(event.getActionIndex() + " not found in MotionEvent"); + } + mListener.accept(event); + event.recycle(); + } + + /** + * Returns the description of the fingers' state expected by MotionEvent. + */ + private Pair<PointerProperties[], PointerCoords[]> getFingerState() { + int nFingers = mFingers.size(); + + Pair<PointerProperties[], PointerCoords[]> result = mCache.get(nFingers); + PointerProperties[] properties = result.first; + PointerCoords[] coordinates = result.second; + + int index = 0; + for (int i = 0; i < mFingers.size(); i++) { + int id = mFingers.keyAt(i); + PointF location = mFingers.get(id); + + PointerProperties property = properties[i]; + property.id = id; + property.toolType = MotionEvent.TOOL_TYPE_FINGER; + properties[index] = property; + + PointerCoords coordinate = coordinates[i]; + coordinate.x = location.x; + coordinate.y = location.y; + coordinate.pressure = 1.0f; + coordinates[index] = coordinate; + + index++; + } + return mCache.get(nFingers); + } +} |