Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0229e29 authored by Daniel Sandler's avatar Daniel Sandler
Browse files

Fix notification gestures.

Broken by recent changes to ScaleGestureDetector, which we
were using incorrectly.

Change-Id: Ie5a7981cc14873d34de9041f59b5de442c948a61
parent 7ffa04b1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -67,6 +67,6 @@
    <integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>

    <!-- The length of the vibration when the notificaiotn pops open. -->
    <integer name="one_finger_pop_duration_ms">10</integer>
    <integer name="blinds_pop_duration_ms">10</integer>
</resources>
+4 −1
Original line number Diff line number Diff line
@@ -152,5 +152,8 @@
    <dimen name="carrier_label_height">24dp</dimen>

    <!-- The distance you can pull a notificaiton before it pops open -->
    <dimen name="one_finger_pop_limit">32dp</dimen>
    <dimen name="blinds_pop_threshold">32dp</dimen>

    <!-- The size of the gesture span needed to activate the "pull" notification expansion -->
    <dimen name="pull_span_min">25dp</dimen>
</resources>
+139 −101
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
    private static final long EXPAND_DURATION = 250;
    private static final long GLOW_DURATION = 150;

    // Set to false to disable focus-based gestures (two-finger pull).
    // Set to false to disable focus-based gestures (spread-finger vertical pull).
    private static final boolean USE_DRAG = true;
    // Set to false to disable scale-based gestures (both horizontal and vertical).
    private static final boolean USE_SPAN = true;
@@ -69,8 +69,12 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
    @SuppressWarnings("unused")
    private Context mContext;

    private boolean mStretching;
    private boolean mPullingWithOneFinger;
    private boolean mExpanding;
    private static final int NONE    = 0;
    private static final int BLINDS  = 1<<0;
    private static final int PULL    = 1<<1;
    private static final int STRETCH = 1<<2;
    private int mExpansionStyle = NONE;
    private boolean mWatchingForPull;
    private boolean mHasPopped;
    private View mEventSource;
@@ -86,8 +90,9 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
    private int mLastMotionY;
    private float mPopLimit;
    private int mPopDuration;
    private float mPullGestureMinXSpan;
    private Callback mCallback;
    private ScaleGestureDetector mDetector;
    private ScaleGestureDetector mSGD;
    private ViewScaler mScaler;
    private ObjectAnimator mScaleAnimation;
    private AnimatorSet mGlowAnimationSet;
@@ -122,7 +127,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
            if (height < 0) {
                height = mView.getMeasuredHeight();
            }
            return (float) height;
            return height;
        }
        public int getNaturalHeight(int maximum) {
            ViewGroup.LayoutParams lp = mView.getLayoutParams();
@@ -161,8 +166,9 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        mGravity = Gravity.TOP;
        mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
        mScaleAnimation.setDuration(EXPAND_DURATION);
        mPopLimit = mContext.getResources().getDimension(R.dimen.one_finger_pop_limit);
        mPopDuration = mContext.getResources().getInteger(R.integer.one_finger_pop_duration_ms);
        mPopLimit = mContext.getResources().getDimension(R.dimen.blinds_pop_threshold);
        mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
        mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);

        AnimatorListenerAdapter glowVisibilityController = new AnimatorListenerAdapter() {
            @Override
@@ -193,32 +199,49 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        final ViewConfiguration configuration = ViewConfiguration.get(mContext);
        mTouchSlop = configuration.getScaledTouchSlop();

        mDetector =
                new ScaleGestureDetector(context,
        mSGD = new ScaleGestureDetector(context,
                                         new ScaleGestureDetector.SimpleOnScaleGestureListener() {
            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                if (DEBUG_SCALE) Slog.v(TAG, "onscalebegin()");
                float x = detector.getFocusX();
                float y = detector.getFocusY();
                float focusX = detector.getFocusX();
                float focusY = detector.getFocusY();

                // your fingers have to be somewhat close to the bounds of the view in question
                mInitialTouchFocusY = detector.getFocusY();
                mInitialTouchFocusY = focusY;
                mInitialTouchSpan = Math.abs(detector.getCurrentSpan());
                if (DEBUG_SCALE) Slog.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");

                mStretching = initScale(findView(x, y));
                return mStretching;
                final View underFocus = findView(focusX, focusY);
                if (underFocus != null) {
                    startExpanding(underFocus, STRETCH);
                }
                return mExpanding;
            }

            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                if (DEBUG_SCALE) Slog.v(TAG, "onscale() on " + mCurrView);
                updateExpansion();
                return true;
            }

            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                if (DEBUG_SCALE) Slog.v(TAG, "onscaleend()");
                // I guess we're alone now
                if (DEBUG_SCALE) Slog.d(TAG, "scale end");
                finishExpanding(false);
                clearView();
            }
        });
    }

    private void updateExpansion() {
        // are we scaling or dragging?
                float span = Math.abs(detector.getCurrentSpan()) - mInitialTouchSpan;
        float span = Math.abs(mSGD.getCurrentSpan()) - mInitialTouchSpan;
        span *= USE_SPAN ? 1f : 0f;
                float drag = detector.getFocusY() - mInitialTouchFocusY;
        float drag = mSGD.getFocusY() - mInitialTouchFocusY;
        drag *= USE_DRAG ? 1f : 0f;
        drag *= mGravity == Gravity.BOTTOM ? -1f : 1f;
        float pull = Math.abs(drag) + Math.abs(span) + 1f;
@@ -228,19 +251,6 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        mScaler.setHeight(newHeight);

        setGlow(calculateGlow(target, newHeight));
                return true;
            }

            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                if (DEBUG_SCALE) Slog.v(TAG, "onscaleend()");
                // I guess we're alone now
                if (DEBUG_SCALE) Slog.d(TAG, "scale end");
                finishScale(false);
                clearView();
                mStretching = false;
            }
        });
    }

    private float clamp(float target) {
@@ -255,8 +265,8 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        if (mEventSource != null) {
            int[] location = new int[2];
            mEventSource.getLocationOnScreen(location);
            x += (float) location[0];
            y += (float) location[1];
            x += location[0];
            y += location[1];
            v = mCallback.getChildAtRawPosition(x, y);
        } else {
            v = mCallback.getChildAtPosition(x, y);
@@ -274,14 +284,14 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        if (mEventSource != null) {
            int[] location = new int[2];
            mEventSource.getLocationOnScreen(location);
            x += (float) location[0];
            y += (float) location[1];
            x += location[0];
            y += location[1];
            if (DEBUG) Slog.d(TAG, "  to global (" + x + ", " + y + ")");
        }
        int[] location = new int[2];
        v.getLocationOnScreen(location);
        x -= (float) location[0];
        y -= (float) location[1];
        x -= location[0];
        y -= location[1];
        if (DEBUG) Slog.d(TAG, "  to local (" + x + ", " + y + ")");
        if (DEBUG) Slog.d(TAG, "  inside (" + v.getWidth() + ", " + v.getHeight() + ")");
        boolean inside = (x > 0f && y > 0f && x < v.getWidth() & y < v.getHeight());
@@ -303,7 +313,7 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
    private float calculateGlow(float target, float actual) {
        // glow if overscale
        if (DEBUG_GLOW) Slog.d(TAG, "target: " + target + " actual: " + actual);
        float stretch = (float) Math.abs((target - actual) / mMaximumStretch);
        float stretch = Math.abs((target - actual) / mMaximumStretch);
        float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
        if (DEBUG_GLOW) Slog.d(TAG, "stretch: " + stretch + " strength: " + strength);
        return (GLOW_BASE + strength * (1f - GLOW_BASE));
@@ -340,32 +350,54 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
                View.INVISIBLE : View.VISIBLE);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (DEBUG) Slog.d(TAG, "interceptTouch: act=" + (ev.getAction()) +
                         " stretching=" + mStretching +
                         " onefinger=" + mPullingWithOneFinger);
        // check for a two-finger gesture
        mDetector.onTouchEvent(ev);
        if (mStretching) {
        final int action = ev.getAction();
        if (DEBUG_SCALE) Slog.d(TAG, "intercept: act=" + MotionEvent.actionToString(action) +
                         " expanding=" + mExpanding +
                         (0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
                         (0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
                         (0 != (mExpansionStyle & STRETCH) ? " (stretch)" : ""));
        // check for a spread-finger vertical pull gesture
        mSGD.onTouchEvent(ev);
        final int x = (int) mSGD.getFocusX();
        final int y = (int) mSGD.getFocusY();
        if (mExpanding) {
            return true;
        } else {
            final int action = ev.getAction();
            if ((action == MotionEvent.ACTION_MOVE) && mPullingWithOneFinger) {
            if ((action == MotionEvent.ACTION_MOVE) && 0 != (mExpansionStyle & BLINDS)) {
                // we've begun Venetian blinds style expansion
                return true;
            }
            final float xspan = mSGD.getCurrentSpanX();
            if ((action == MotionEvent.ACTION_MOVE &&
                    xspan > mPullGestureMinXSpan &&
                    xspan > mSGD.getCurrentSpanY())) {
                // detect a vertical pulling gesture with fingers somewhat separated
                if (DEBUG_SCALE) Slog.v(TAG, "got pull gesture (xspan=" + xspan + "px)");

                mInitialTouchFocusY = y;

                final View underFocus = findView(x, y);
                if (underFocus != null) {
                    startExpanding(underFocus, PULL);
                }
                return true;
            }
            if (mScrollView != null && mScrollView.getScrollY() > 0) {
                return false;
            }
            // Now look for other gestures
            switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_MOVE: {
                if (mWatchingForPull) {
                    final int x = (int) ev.getX();
                    final int y = (int) ev.getY();
                    final int yDiff = y - mLastMotionY;
                    if (yDiff > mTouchSlop) {
                        if (DEBUG) Slog.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                        mLastMotionY = y;
                        mPullingWithOneFinger = initScale(findView(x, y));
                        if (mPullingWithOneFinger) {
                        final View underFocus = findView(x, y);
                        if (underFocus != null) {
                            startExpanding(underFocus, BLINDS);
                            mInitialTouchY = mLastMotionY;
                            mHasPopped = false;
                        }
@@ -375,35 +407,35 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
            }

            case MotionEvent.ACTION_DOWN:
                mWatchingForPull = isInside(mScrollView, ev.getX(), ev.getY());
                mLastMotionY = (int) ev.getY();
                mWatchingForPull = isInside(mScrollView, x, y);
                mLastMotionY = y;
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (mPullingWithOneFinger) {
                    finishScale(false);
                if (DEBUG) Slog.d(TAG, "up/cancel");
                finishExpanding(false);
                clearView();
                }
                mPullingWithOneFinger = false;
                mWatchingForPull = false;
                break;
            }
            return mPullingWithOneFinger;
            return mExpanding;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + (action) +
                         " stretching=" + mStretching +
                         " onefinger=" + mPullingWithOneFinger);
        if (mStretching) {
            mDetector.onTouchEvent(ev);
        }
        if (DEBUG_SCALE) Slog.d(TAG, "touch: act=" + MotionEvent.actionToString(action) +
                " expanding=" + mExpanding +
                (0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
                (0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
                (0 != (mExpansionStyle & STRETCH) ? " (stretch)" : ""));

        mSGD.onTouchEvent(ev);

        switch (action) {
            case MotionEvent.ACTION_MOVE: {
                if (mPullingWithOneFinger) {
                if (0 != (mExpansionStyle & BLINDS)) {
                    final float rawHeight = ev.getY() - mInitialTouchY + mOldHeight;
                    final float newHeight = clamp(rawHeight);
                    final boolean wasClosed = (mOldHeight == mSmallSize);
@@ -430,35 +462,39 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
                        setGlow(calculateGlow(4f * pull, 0f));
                    }

                    final int x = (int) ev.getX();
                    final int y = (int) ev.getY();
                    View underPointer = findView(x, y);
                    if (isFinished && underPointer != null && underPointer != mCurrView) {
                        finishScale(false);
                        initScale(underPointer);
                        mInitialTouchY = ev.getY();
                    final int x = (int) mSGD.getFocusX();
                    final int y = (int) mSGD.getFocusY();
                    View underFocus = findView(x, y);
                    if (isFinished && underFocus != null && underFocus != mCurrView) {
                        finishExpanding(false); // @@@ needed?
                        startExpanding(underFocus, BLINDS);
                        mInitialTouchY = y;
                        mHasPopped = false;
                    }
                    return true;
                }

                if (mExpanding) {
                    updateExpansion();
                    return true;
                }

                break;
            }
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (DEBUG) Slog.d(TAG, "cancel");
                mStretching = false;
                if (mPullingWithOneFinger) {
                    finishScale(false);
                    mPullingWithOneFinger = false;
                }
                if (DEBUG) Slog.d(TAG, "up/cancel");
                finishExpanding(false);
                clearView();
                break;
        }
        return true;
    }
    private boolean initScale(View v) {
        if (v != null) {
            if (DEBUG) Slog.d(TAG, "scale begins on view: " + v);

    private void startExpanding(View v, int expandType) {
        mExpanding = true;
        mExpansionStyle = expandType; 
        if (DEBUG) Slog.d(TAG, "scale type " + expandType + " beginning on view: " + v);
        mCallback.setUserLockedChild(v, true);
        setView(v);
        setGlow(GLOW_BASE);
@@ -474,13 +510,11 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
        if (DEBUG) Slog.d(TAG, "got mOldHeight: " + mOldHeight +
                    " mNaturalHeight: " + mNaturalHeight);
        v.getParent().requestDisallowInterceptTouchEvent(true);
            return true;
        } else {
            return false;
        }
    }

    private void finishScale(boolean force) {
    private void finishExpanding(boolean force) {
        if (!mExpanding) return;

        float currentHeight = mScaler.getHeight();
        float targetHeight = mSmallSize;
        float h = mScaler.getHeight();
@@ -501,6 +535,10 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {
            mScaleAnimation.start();
        }
        mCallback.setUserLockedChild(mCurrView, false);

        mExpanding = false;
        mExpansionStyle = NONE;

        if (DEBUG) Slog.d(TAG, "scale was finished on view: " + mCurrView);
    }

@@ -527,8 +565,8 @@ public class ExpandHelper implements Gefingerpoken, OnClickListener {

    @Override
    public void onClick(View v) {
        initScale(v);
        finishScale(true);
        startExpanding(v, STRETCH);
        finishExpanding(true);
        clearView();
    }