diff options
author | Hyunyoung Song <hyunyoungs@google.com> | 2019-06-21 23:24:02 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2019-06-26 21:48:29 +0000 |
commit | 35062f8ed32ea4a868be077fdae37409a700e759 (patch) | |
tree | 1ee077240db54128c95026df6d7b210181a01353 | |
parent | a730a233b8b5d70ae535cd18a9084626253dfb9b (diff) | |
download | android_packages_apps_Trebuchet-35062f8ed32ea4a868be077fdae37409a700e759.tar.gz android_packages_apps_Trebuchet-35062f8ed32ea4a868be077fdae37409a700e759.tar.bz2 android_packages_apps_Trebuchet-35062f8ed32ea4a868be077fdae37409a700e759.zip |
Enable FLAG_SLIPPERY window flag when swipe down on workspace
Bug: 131356741
Test: manual
Change-Id: Ibe0e3a03e7406d5d882a1c63265d6e4e0253983e
-rw-r--r-- | quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java | 68 | ||||
-rw-r--r-- | src/com/android/launcher3/touch/TouchEventTranslator.java | 283 |
2 files changed, 51 insertions, 300 deletions
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java index fee18204e..f5ba3725d 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java @@ -17,17 +17,22 @@ 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; @@ -36,18 +41,29 @@ import java.io.PrintWriter; /** * TouchController for handling touch events that get sent to the StatusBar. Once the - * Once the event delta y passes the touch slop, the events start getting forwarded. + * Once the event delta mDownY 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; @@ -56,7 +72,7 @@ public class StatusBarTouchController implements TouchController { mLauncher = l; // Guard against TAPs by increasing the touch slop. mTouchSlop = 2 * ViewConfiguration.get(l).getScaledTouchSlop(); - mTranslator = new TouchEventTranslator((MotionEvent ev)-> dispatchTouchEvent(ev)); + mDownEvents = new SparseArray<>(); } @Override @@ -64,7 +80,6 @@ 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) { @@ -81,26 +96,31 @@ 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; } - mTranslator.reset(); - mTranslator.setDownParameters(0, ev); + mDownEvents.put(pid, new PointF(ev.getX(), ev.getY())); } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { - // Check!! should only set it only when threshold is not entered. - mTranslator.setDownParameters(ev.getActionIndex(), ev); + // Check!! should only set it only when threshold is not entered. + mDownEvents.put(pid, new PointF(ev.getX(idx), ev.getY(idx))); } if (!mCanIntercept) { return false; } if (action == ACTION_MOVE) { - 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); + 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); return true; } if (Math.abs(dx) > mTouchSlop) { @@ -110,13 +130,27 @@ public class StatusBarTouchController implements TouchController { return false; } - @Override public final boolean onControllerTouchEvent(MotionEvent ev) { - mTranslator.processMotionEvent(ev); + if (ev.getAction() == ACTION_UP || ev.getAction() == ACTION_CANCEL) { + dispatchTouchEvent(ev); + setWindowSlippery(false); + return true; + } 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, @@ -132,4 +166,4 @@ public class StatusBarTouchController implements TouchController { mSysUiProxy = RecentsModel.INSTANCE.get(mLauncher).getSystemUiProxy(); return mSysUiProxy != null; } -} +}
\ No newline at end of file diff --git a/src/com/android/launcher3/touch/TouchEventTranslator.java b/src/com/android/launcher3/touch/TouchEventTranslator.java deleted file mode 100644 index 3fcda9084..000000000 --- a/src/com/android/launcher3/touch/TouchEventTranslator.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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); - } -} |