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

Commit e36393a9 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement magnification viewport pan shortcuts." into main

parents 12d762b6 4f1a8330
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -125,7 +125,10 @@ public final class KeyGestureEvent {
    public static final int KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK = 75;
    public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 76;
    public static final int KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB = 77;

    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT = 78;
    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT = 79;
    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP = 80;
    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN = 81;

    public static final int FLAG_CANCELLED = 1;

@@ -217,7 +220,11 @@ public final class KeyGestureEvent {
            KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION,
            KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK,
            KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW,
            KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB
            KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB,
            KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT,
            KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT,
            KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP,
            KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface KeyGestureType {
@@ -792,6 +799,14 @@ public final class KeyGestureEvent {
                return "KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW";
            case KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB:
                return "KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB";
            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT:
                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT";
            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT:
                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT";
            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP:
                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP";
            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN:
                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN";
            default:
                return Integer.toHexString(value);
        }
+32 −5
Original line number Diff line number Diff line
@@ -245,22 +245,45 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
                    final boolean complete =
                            event.getAction() == KeyGestureEvent.ACTION_GESTURE_COMPLETE
                                    && !event.isCancelled();

                    // TODO(b/355499907): Receive and handle held key gestures, which can be used
                    // for continuous scaling and panning. In addition, handle multiple pan gestures
                    // at the same time (e.g. user may try to pan diagonally) reasonably, including
                    // decreasing diagonal movement by sqrt(2) to make it appear the same speed
                    // as non-diagonal movement.

                    if (!complete) {
                        return false;
                    }

                    final int gestureType = event.getKeyGestureType();
                    final int displayId = isDisplayIdValid(event.getDisplayId())
                            ? event.getDisplayId() : Display.DEFAULT_DISPLAY;

                    switch (gestureType) {
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN:
                            if (complete) {
                                mAms.getMagnificationController().scaleMagnificationByStep(
                                        displayId, MagnificationController.ZOOM_DIRECTION_IN);
                            }
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT:
                            if (complete) {
                                mAms.getMagnificationController().scaleMagnificationByStep(
                                        displayId, MagnificationController.ZOOM_DIRECTION_OUT);
                            }
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_LEFT);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_RIGHT);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_UP);
                            return true;
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN:
                            mAms.getMagnificationController().panMagnificationByStep(
                                    displayId, MagnificationController.PAN_DIRECTION_DOWN);
                            return true;
                    }
                    return false;
@@ -270,7 +293,11 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
                public boolean isKeyGestureSupported(int gestureType) {
                    return switch (gestureType) {
                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT -> true;
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP,
                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN -> true;
                        default -> false;
                    };
                }
+144 −7
Original line number Diff line number Diff line
@@ -35,14 +35,19 @@ import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseDoubleArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.TypedValue;
import android.view.Display;
import android.view.accessibility.MagnificationAnimationCallback;

import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
@@ -102,6 +107,7 @@ public class MagnificationController implements MagnificationConnectionManager.C
    /** Whether the platform supports window magnification feature. */
    private final boolean mSupportWindowMagnification;
    private final MagnificationScaleStepProvider mScaleStepProvider;
    private final MagnificationPanStepProvider mPanStepProvider;

    private final Executor mBackgroundExecutor;

@@ -132,7 +138,7 @@ public class MagnificationController implements MagnificationConnectionManager.C
            .UiChangesForAccessibilityCallbacks> mAccessibilityCallbacksDelegateArray =
            new SparseArray<>();

    // Direction magnifier scale can be altered.
    // Direction magnification scale can be altered.
    public static final int ZOOM_DIRECTION_IN = 0;
    public static final int ZOOM_DIRECTION_OUT = 1;

@@ -140,6 +146,16 @@ public class MagnificationController implements MagnificationConnectionManager.C
    public @interface ZoomDirection {
    }

    // Directions magnification center can be moved.
    public static final int PAN_DIRECTION_LEFT = 0;
    public static final int PAN_DIRECTION_RIGHT = 1;
    public static final int PAN_DIRECTION_UP = 2;
    public static final int PAN_DIRECTION_DOWN = 3;

    @IntDef({PAN_DIRECTION_LEFT, PAN_DIRECTION_RIGHT, PAN_DIRECTION_UP, PAN_DIRECTION_DOWN})
    public @interface PanDirection {
    }

    /**
     * A callback to inform the magnification transition result on the given display.
     */
@@ -188,6 +204,87 @@ public class MagnificationController implements MagnificationConnectionManager.C
        }
    }

    /**
     * An interface to configure how much the magnification center should be affected when panning
     * in steps.
     */
    public interface MagnificationPanStepProvider {
        /**
         * Calculate the next value based on the current scale.
         *
         * @param currentScale The current magnification scale value.
         * @param displayId The displayId for the display being magnified.
         * @return The next pan step value.
         */
        float nextPanStep(float currentScale, int displayId);
    }

    public static class DefaultMagnificationPanStepProvider implements
            MagnificationPanStepProvider, DisplayManager.DisplayListener {
        // We want panning to be 40 dip per keystroke at scale 2, and 1 dip per keystroke at scale
        // 20. This can be defined using y = mx + b to get the slope and intercept.
        // This works even if the device does not allow magnification up to 20x; we will still get
        // a reasonable lineary ramp of panning movement for each scale step.
        private static final float DEFAULT_SCALE = 2.0f;
        private static final float PAN_STEP_AT_DEFAULT_SCALE_DIP = 40.0f;
        private static final float SCALE_FOR_1_DIP_PAN = 20.0f;

        private SparseDoubleArray mPanStepSlopes;
        private SparseDoubleArray mPanStepIntercepts;

        private final DisplayManager mDisplayManager;

        DefaultMagnificationPanStepProvider(Context context) {
            mDisplayManager = context.getSystemService(DisplayManager.class);
            mDisplayManager.registerDisplayListener(this, /*handler=*/null);
            mPanStepSlopes = new SparseDoubleArray();
            mPanStepIntercepts = new SparseDoubleArray();
        }

        @Override
        public void onDisplayAdded(int displayId) {
            updateForDisplay(displayId);
        }

        @Override
        public void onDisplayChanged(int displayId) {
            updateForDisplay(displayId);
        }

        @Override
        public void onDisplayRemoved(int displayId) {
            mPanStepSlopes.delete(displayId);
            mPanStepIntercepts.delete(displayId);
        }

        @Override
        public float nextPanStep(float currentScale, int displayId) {
            if (mPanStepSlopes.indexOfKey(displayId) < 0) {
                updateForDisplay(displayId);
            }
            return Math.max((float) (mPanStepSlopes.get(displayId) * currentScale
                    + mPanStepIntercepts.get(displayId)), 1);
        }

        private void updateForDisplay(int displayId) {
            Display display = mDisplayManager.getDisplay(displayId);
            if (display == null) {
                return;
            }
            DisplayMetrics metrics = new DisplayMetrics();
            display.getMetrics(metrics);
            final float panStepAtDefaultScaleInPx = TypedValue.convertDimensionToPixels(
                    TypedValue.COMPLEX_UNIT_DIP, PAN_STEP_AT_DEFAULT_SCALE_DIP, metrics);
            final float panStepAtMaxScaleInPx = TypedValue.convertDimensionToPixels(
                    TypedValue.COMPLEX_UNIT_DIP, 1.0f, metrics);
            final float panStepSlope = (panStepAtMaxScaleInPx - panStepAtDefaultScaleInPx)
                    / (SCALE_FOR_1_DIP_PAN - DEFAULT_SCALE);
            mPanStepSlopes.put(displayId, panStepSlope);
            mPanStepIntercepts.put(displayId,
                    panStepAtDefaultScaleInPx - panStepSlope * DEFAULT_SCALE);
        }
    }

    public MagnificationController(AccessibilityManagerService ams, Object lock,
            Context context, MagnificationScaleProvider scaleProvider,
            Executor backgroundExecutor) {
@@ -201,6 +298,7 @@ public class MagnificationController implements MagnificationConnectionManager.C
        mSupportWindowMagnification = context.getPackageManager().hasSystemFeature(
                FEATURE_WINDOW_MAGNIFICATION);
        mScaleStepProvider = new DefaultMagnificationScaleStepProvider();
        mPanStepProvider = new DefaultMagnificationPanStepProvider(mContext);

        mAlwaysOnMagnificationFeatureFlag = new AlwaysOnMagnificationFeatureFlag(context);
        mAlwaysOnMagnificationFeatureFlag.addOnChangedListener(
@@ -935,13 +1033,12 @@ public class MagnificationController implements MagnificationConnectionManager.C
    }

    /**
     * Scales the magnifier on the given display one step in/out based on the zoomIn param.
     * Scales the magnifier on the given display one step in/out based on the direction param.
     *
     * @param displayId The logical display id.
     * @param direction Whether the scale should be zoomed in or out.
     * @return {@code true} if the magnification scale was affected.
     */
    public boolean scaleMagnificationByStep(int displayId, @ZoomDirection int direction) {
    public void scaleMagnificationByStep(int displayId, @ZoomDirection int direction) {
        if (getFullScreenMagnificationController().isActivated(displayId)) {
            final float magnificationScale = getFullScreenMagnificationController().getScale(
                    displayId);
@@ -950,7 +1047,6 @@ public class MagnificationController implements MagnificationConnectionManager.C
            getFullScreenMagnificationController().setScaleAndCenter(displayId,
                    nextMagnificationScale,
                    Float.NaN, Float.NaN, true, MAGNIFICATION_GESTURE_HANDLER_ID);
            return nextMagnificationScale != magnificationScale;
        }

        if (getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId)) {
@@ -959,10 +1055,51 @@ public class MagnificationController implements MagnificationConnectionManager.C
            final float nextMagnificationScale = mScaleStepProvider.nextScaleStep(
                    magnificationScale, direction);
            getMagnificationConnectionManager().setScale(displayId, nextMagnificationScale);
            return nextMagnificationScale != magnificationScale;
        }
    }

        return false;
    /**
     * Pans the magnifier on the given display one step left/right/up/down based on the direction
     * param.
     *
     * @param displayId The logical display id.
     * @param direction Whether the direction should be left/right/up/down.
     */
    public void panMagnificationByStep(int displayId, @PanDirection int direction) {
        final boolean fullscreenActivated =
                getFullScreenMagnificationController().isActivated(displayId);
        final boolean windowActivated =
                getMagnificationConnectionManager().isWindowMagnifierEnabled(displayId);
        if (!fullscreenActivated && !windowActivated) {
            return;
        }

        final float scale = fullscreenActivated
                ? getFullScreenMagnificationController().getScale(displayId)
                        : getMagnificationConnectionManager().getScale(displayId);
        final float step = mPanStepProvider.nextPanStep(scale, displayId);

        float offsetX = 0;
        float offsetY = 0;
        if (direction == PAN_DIRECTION_LEFT) {
            offsetX = -step;
        } else if (direction == PAN_DIRECTION_RIGHT) {
            offsetX = step;
        } else if (direction == PAN_DIRECTION_UP) {
            offsetY = -step;
        } else if (direction == PAN_DIRECTION_DOWN) {
            offsetY = step;
        }

        if (fullscreenActivated) {
            final float centerX = getFullScreenMagnificationController().getCenterX(displayId);
            final float centerY = getFullScreenMagnificationController().getCenterY(displayId);
            getFullScreenMagnificationController().setScaleAndCenter(displayId, scale,
                    centerX + offsetX, centerY + offsetY, true, MAGNIFICATION_GESTURE_HANDLER_ID);
        } else {
            getMagnificationConnectionManager().moveWindowMagnification(displayId, offsetX,
                    offsetY);
        }
    }

    private final class DisableMagnificationCallback implements
+12 −0
Original line number Diff line number Diff line
@@ -221,6 +221,18 @@ final class InputGestureManager {
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_EQUALS,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_LEFT,
                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_RIGHT,
                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_UP,
                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_DOWN,
                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN));
            systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_M,
                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                    KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION));
+233 −8

File changed.

Preview size limit exceeded, changes collapsed.

Loading