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

Commit 6d04712d authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Allow simultaneous scale and pan in magnified state.

1. Before in magnified state the user was able to only scale or
   pan. Based on user input this change allows performing pan
   or scale or both. If the user scales more than a threshold
   we are performing a scale and independently of that if the
   use pans more than a threshold we are performing a pan.

bug:7138928

Change-Id: Ic1511500ba3369091dcfd070669d3e4f0286fbe5
parent 0c381504
Loading
Loading
Loading
Loading
+46 −60
Original line number Original line Diff line number Diff line
@@ -114,17 +114,15 @@ public final class ScreenMagnifier implements EventStreamTransformation {
    private static final boolean DEBUG_VIEWPORT_WINDOW = false;
    private static final boolean DEBUG_VIEWPORT_WINDOW = false;
    private static final boolean DEBUG_WINDOW_TRANSITIONS = false;
    private static final boolean DEBUG_WINDOW_TRANSITIONS = false;
    private static final boolean DEBUG_ROTATION = false;
    private static final boolean DEBUG_ROTATION = false;
    private static final boolean DEBUG_GESTURE_DETECTOR = false;
    private static final boolean DEBUG_SCALE_GESTURE_DETECTOR = false;
    private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false;
    private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false;


    private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName();
    private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName();


    private static final int STATE_DELEGATING = 1;
    private static final int STATE_DELEGATING = 1;
    private static final int STATE_DETECTING = 2;
    private static final int STATE_DETECTING = 2;
    private static final int STATE_SCALING = 3;
    private static final int STATE_VIEWPORT_DRAGGING = 4;
    private static final int STATE_VIEWPORT_DRAGGING = 4;
    private static final int STATE_PANNING = 5;
    private static final int STATE_MAGNIFIED_INTERACTION = 6;
    private static final int STATE_DECIDE_PAN_OR_SCALE = 6;


    private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
    private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
    private static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
    private static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
@@ -203,12 +201,10 @@ public final class ScreenMagnifier implements EventStreamTransformation {
            case STATE_VIEWPORT_DRAGGING: {
            case STATE_VIEWPORT_DRAGGING: {
                mStateViewportDraggingHandler.onMotionEvent(event, policyFlags);
                mStateViewportDraggingHandler.onMotionEvent(event, policyFlags);
            } break;
            } break;
            case STATE_SCALING:
            case STATE_MAGNIFIED_INTERACTION: {
            case STATE_PANNING:
            case STATE_DECIDE_PAN_OR_SCALE: {
                // Handled by the gesture detector. Since the detector
                // Handled by the gesture detector. Since the detector
                // needs all touch events to work properly we cannot
                // needs all touch events to work properly we cannot
                // call it only for these states.
                // call it only for this state.
            } break;
            } break;
            default: {
            default: {
                throw new IllegalStateException("Unknown state: " + mCurrentState);
                throw new IllegalStateException("Unknown state: " + mCurrentState);
@@ -326,14 +322,8 @@ public final class ScreenMagnifier implements EventStreamTransformation {
                case STATE_VIEWPORT_DRAGGING: {
                case STATE_VIEWPORT_DRAGGING: {
                    Slog.i(LOG_TAG, "mCurrentState: STATE_VIEWPORT_DRAGGING");
                    Slog.i(LOG_TAG, "mCurrentState: STATE_VIEWPORT_DRAGGING");
                } break;
                } break;
                case STATE_SCALING: {
                case STATE_MAGNIFIED_INTERACTION: {
                    Slog.i(LOG_TAG, "mCurrentState: STATE_SCALING");
                    Slog.i(LOG_TAG, "mCurrentState: STATE_MAGNIFIED_INTERACTION");
                } break;
                case STATE_PANNING: {
                    Slog.i(LOG_TAG, "mCurrentState: STATE_PANNING");
                } break;
                case STATE_DECIDE_PAN_OR_SCALE: {
                    Slog.i(LOG_TAG, "mCurrentState: STATE_DECIDE_PAN_OR_SCALE");
                } break;
                } break;
                default: {
                default: {
                    throw new IllegalArgumentException("Unknown state: " + state);
                    throw new IllegalArgumentException("Unknown state: " + state);
@@ -347,7 +337,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
        private static final float MIN_SCALE = 1.3f;
        private static final float MIN_SCALE = 1.3f;
        private static final float MAX_SCALE = 5.0f;
        private static final float MAX_SCALE = 5.0f;


        private static final float DETECT_SCALING_THRESHOLD = 0.25f;
        private static final float DETECT_SCALING_THRESHOLD = 0.30f;
        private static final int DETECT_PANNING_THRESHOLD_DIP = 30;
        private static final int DETECT_PANNING_THRESHOLD_DIP = 30;


        private final float mScaledDetectPanningThreshold;
        private final float mScaledDetectPanningThreshold;
@@ -366,6 +356,9 @@ public final class ScreenMagnifier implements EventStreamTransformation {
        private float mScaleFocusX = Float.NaN;
        private float mScaleFocusX = Float.NaN;
        private float mScaleFocusY = Float.NaN;
        private float mScaleFocusY = Float.NaN;


        private boolean mScaling;
        private boolean mPanning;

        public GestureDetector(Context context) {
        public GestureDetector(Context context) {
            final float density = context.getResources().getDisplayMetrics().density;
            final float density = context.getResources().getDisplayMetrics().density;
            mScaledDetectPanningThreshold = DETECT_PANNING_THRESHOLD_DIP * density;
            mScaledDetectPanningThreshold = DETECT_PANNING_THRESHOLD_DIP * density;
@@ -383,8 +376,9 @@ public final class ScreenMagnifier implements EventStreamTransformation {
            }
            }
            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                clear();
                clear();
                if (mCurrentState == STATE_SCALING) {
                final float scale = mMagnificationController.getScale();
                    persistScale(mMagnificationController.getScale());
                if (scale != getPersistedScale()) {
                    persistScale(scale);
                }
                }
                transitionToState(STATE_DETECTING);
                transitionToState(STATE_DETECTING);
            }
            }
@@ -398,38 +392,36 @@ public final class ScreenMagnifier implements EventStreamTransformation {
                case STATE_VIEWPORT_DRAGGING: {
                case STATE_VIEWPORT_DRAGGING: {
                    return true;
                    return true;
                }
                }
                case STATE_DECIDE_PAN_OR_SCALE: {
                case STATE_MAGNIFIED_INTERACTION: {
                    mCurrScaleFactor = mScaleGestureDetector.getScaleFactor();
                    mCurrScaleFactor = mScaleGestureDetector.getScaleFactor();
                    final float scaleDelta = Math.abs(1.0f - mCurrScaleFactor * mPrevScaleFactor);
                    final float scaleDelta = Math.abs(1.0f - mCurrScaleFactor * mPrevScaleFactor);
                    if (DEBUG_GESTURE_DETECTOR) {
                    if (DEBUG_SCALE_GESTURE_DETECTOR) {
                        Slog.i(LOG_TAG, "scaleDelta: " + scaleDelta);
                        Slog.i(LOG_TAG, "scaleDelta: " + scaleDelta);
                    }
                    }
                    if (scaleDelta > DETECT_SCALING_THRESHOLD) {
                    if (!mScaling && scaleDelta > DETECT_SCALING_THRESHOLD) {
                        performScale(detector, true);
                        mScaling = true;
                        clear();
                        clearContextualState();
                        transitionToState(STATE_SCALING);
                        return true;
                        return true;
                    }
                    }
                    if (mScaling) {
                        performScale(detector);
                    }
                    mCurrPan = (float) MathUtils.dist(
                    mCurrPan = (float) MathUtils.dist(
                            mScaleGestureDetector.getFocusX(),
                            mScaleGestureDetector.getFocusX(),
                            mScaleGestureDetector.getFocusY(),
                            mScaleGestureDetector.getFocusY(),
                            mInitialFocus.x, mInitialFocus.y);
                            mInitialFocus.x, mInitialFocus.y);
                    final float panDelta = mCurrPan + mPrevPan;
                    final float panDelta = mCurrPan + mPrevPan;
                    if (DEBUG_GESTURE_DETECTOR) {
                    if (DEBUG_SCALE_GESTURE_DETECTOR) {
                        Slog.i(LOG_TAG, "panDelta: " + panDelta);
                        Slog.i(LOG_TAG, "panDelta: " + panDelta);
                    }
                    }
                    if (panDelta > mScaledDetectPanningThreshold) {
                    if (!mPanning && panDelta > mScaledDetectPanningThreshold) {
                        performPan(detector, true);
                        mPanning = true;
                        clear();
                        clearContextualState();
                        transitionToState(STATE_PANNING);
                        return true;
                        return true;
                    }
                    }
                } break;
                    if (mPanning) {
                case STATE_SCALING: {
                        performPan(detector);
                    performScale(detector, false);
                    }
                } break;
                case STATE_PANNING: {
                    performPan(detector, false);
                } break;
                } break;
            }
            }
            return false;
            return false;
@@ -437,32 +429,26 @@ public final class ScreenMagnifier implements EventStreamTransformation {


        @Override
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            switch (mCurrentState) {
                case STATE_DECIDE_PAN_OR_SCALE: {
            mPrevScaleFactor *= mCurrScaleFactor;
            mPrevScaleFactor *= mCurrScaleFactor;
                    mPrevPan += mCurrPan;
                    mPrevFocus.x = mInitialFocus.x = detector.getFocusX();
                    mPrevFocus.y = mInitialFocus.y = detector.getFocusY();
                } break;
                case STATE_SCALING: {
                    mPrevScaleFactor = 1.0f;
            mCurrScale = Float.NaN;
            mCurrScale = Float.NaN;
                } break;
                case STATE_PANNING: {
            mPrevPan += mCurrPan;
            mPrevPan += mCurrPan;
            mPrevFocus.x = mInitialFocus.x = detector.getFocusX();
            mPrevFocus.x = mInitialFocus.x = detector.getFocusX();
            mPrevFocus.y = mInitialFocus.y = detector.getFocusY();
            mPrevFocus.y = mInitialFocus.y = detector.getFocusY();
                } break;
            }
            return true;
            return true;
        }
        }


        @Override
        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
        public void onScaleEnd(ScaleGestureDetector detector) {
            clear();
            clearContextualState();
        }
        }


        public void clear() {
        public void clear() {
            clearContextualState();
            mScaling = false;
            mPanning = false;
        }

        private void clearContextualState() {
            mCurrScaleFactor = 1.0f;
            mCurrScaleFactor = 1.0f;
            mPrevScaleFactor = 1.0f;
            mPrevScaleFactor = 1.0f;
            mPrevPan = 0;
            mPrevPan = 0;
@@ -474,7 +460,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
            mScaleFocusY = Float.NaN;
            mScaleFocusY = Float.NaN;
        }
        }


        private void performPan(ScaleGestureDetector detector, boolean animate) {
        private void performPan(ScaleGestureDetector detector) {
            if (Float.compare(mPrevFocus.x, Float.NaN) == 0
            if (Float.compare(mPrevFocus.x, Float.NaN) == 0
                    && Float.compare(mPrevFocus.y, Float.NaN) == 0) {
                    && Float.compare(mPrevFocus.y, Float.NaN) == 0) {
                mPrevFocus.set(detector.getFocusX(), detector.getFocusY());
                mPrevFocus.set(detector.getFocusX(), detector.getFocusY());
@@ -491,11 +477,11 @@ public final class ScreenMagnifier implements EventStreamTransformation {
                Slog.i(LOG_TAG, "Panned content by scrollX: " + scrollX
                Slog.i(LOG_TAG, "Panned content by scrollX: " + scrollX
                        + " scrollY: " + scrollY);
                        + " scrollY: " + scrollY);
            }
            }
            mMagnificationController.setMagnifiedRegionCenter(centerX, centerY, animate);
            mMagnificationController.setMagnifiedRegionCenter(centerX, centerY, false);
            mPrevFocus.set(detector.getFocusX(), detector.getFocusY());
            mPrevFocus.set(detector.getFocusX(), detector.getFocusY());
        }
        }


        private void performScale(ScaleGestureDetector detector, boolean animate) {
        private void performScale(ScaleGestureDetector detector) {
            if (Float.compare(mCurrScale, Float.NaN) == 0) {
            if (Float.compare(mCurrScale, Float.NaN) == 0) {
                mCurrScale = mMagnificationController.getScale();
                mCurrScale = mMagnificationController.getScale();
                return;
                return;
@@ -513,7 +499,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
                mScaleFocusY = detector.getFocusY();
                mScaleFocusY = detector.getFocusY();
            }
            }
            mMagnificationController.setScale(normalizedNewScale, mScaleFocusX,
            mMagnificationController.setScale(normalizedNewScale, mScaleFocusX,
                    mScaleFocusY, animate);
                    mScaleFocusY, false);
        }
        }
    }
    }


@@ -528,7 +514,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
                }
                }
                case MotionEvent.ACTION_POINTER_DOWN: {
                case MotionEvent.ACTION_POINTER_DOWN: {
                    clear();
                    clear();
                    transitionToState(STATE_SCALING);
                    transitionToState(STATE_MAGNIFIED_INTERACTION);
                } break;
                } break;
                case MotionEvent.ACTION_MOVE: {
                case MotionEvent.ACTION_MOVE: {
                    if (event.getPointerCount() != 1) {
                    if (event.getPointerCount() != 1) {
@@ -632,7 +618,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
                } break;
                } break;
                case MotionEvent.ACTION_POINTER_DOWN: {
                case MotionEvent.ACTION_POINTER_DOWN: {
                    if (mMagnificationController.isMagnifying()) {
                    if (mMagnificationController.isMagnifying()) {
                        transitionToState(STATE_DECIDE_PAN_OR_SCALE);
                        transitionToState(STATE_MAGNIFIED_INTERACTION);
                        clear();
                        clear();
                    } else {
                    } else {
                        transitionToDelegatingStateAndClear();
                        transitionToDelegatingStateAndClear();