Loading core/java/android/view/MotionEvent.java +35 −0 Original line number Diff line number Diff line Loading @@ -3768,6 +3768,41 @@ public final class MotionEvent extends InputEvent implements Parcelable { return (getButtonState() & button) == button; } /** * Gets a rotation matrix that (when applied to a motionevent) will rotate that motion event * such that the result coordinates end up in the same physical location on a display whose * coordinates are rotated by `rotation`. * * For example, rotating 0,0 by 90 degrees will move a point from the physical top-left to * the bottom-left of the 90-degree-rotated display. * * @hide */ public static Matrix createRotateMatrix( @Surface.Rotation int rotation, int displayW, int displayH) { if (rotation == Surface.ROTATION_0) { return new Matrix(Matrix.IDENTITY_MATRIX); } // values is row-major float[] values = null; if (rotation == Surface.ROTATION_90) { values = new float[]{0, 1, 0, -1, 0, displayH, 0, 0, 1}; } else if (rotation == Surface.ROTATION_180) { values = new float[]{-1, 0, displayW, 0, -1, displayH, 0, 0, 1}; } else if (rotation == Surface.ROTATION_270) { values = new float[]{0, -1, displayW, 1, 0, 0, 0, 0, 1}; } Matrix toOrient = new Matrix(); toOrient.setValues(values); return toOrient; } public static final @android.annotation.NonNull Parcelable.Creator<MotionEvent> CREATOR = new Parcelable.Creator<MotionEvent>() { public MotionEvent createFromParcel(Parcel in) { Loading core/java/com/android/internal/widget/PointerLocationView.java +24 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.Surface; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; Loading @@ -59,6 +60,9 @@ public class PointerLocationView extends View implements InputDeviceListener, */ private static final String GESTURE_EXCLUSION_PROP = "debug.pointerlocation.showexclusion"; private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION = SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false); public static class PointerState { // Trace of previous points. private float[] mTraceX = new float[32]; Loading Loading @@ -352,6 +356,21 @@ public class PointerLocationView extends View implements InputDeviceListener, .toString(), 1 + itemW * 6, base, mTextPaint); } int saveId = canvas.save(); if (ENABLE_PER_WINDOW_INPUT_ROTATION) { // Rotate negative (since we're rotating the drawing canvas vs the output). canvas.rotate(-90.0f * mContext.getDisplay().getRotation()); switch (mContext.getDisplay().getRotation()) { case Surface.ROTATION_90: canvas.translate(-canvas.getHeight(), 0); break; case Surface.ROTATION_180: canvas.translate(-canvas.getWidth(), -canvas.getHeight()); break; case Surface.ROTATION_270: canvas.translate(0, -canvas.getWidth()); } } // Pointer trace. for (int p = 0; p < NP; p++) { final PointerState ps = mPointers.get(p); Loading Loading @@ -399,7 +418,10 @@ public class PointerLocationView extends View implements InputDeviceListener, if (mCurDown && ps.mCurDown) { // Draw crosshairs. canvas.drawLine(0, ps.mCoords.y, getWidth(), ps.mCoords.y, mTargetPaint); canvas.drawLine(ps.mCoords.x, 0, ps.mCoords.x, getHeight(), mTargetPaint); // Extend crosshairs to cover screen regardless of rotation (ie. since the rotated // canvas can "expose" content past 0 and up-to the largest screen dimension). canvas.drawLine(ps.mCoords.x, -getHeight(), ps.mCoords.x, Math.max(getHeight(), getWidth()), mTargetPaint); // Draw current point. int pressureLevel = (int)(ps.mCoords.pressure * 255); Loading Loading @@ -458,6 +480,7 @@ public class PointerLocationView extends View implements InputDeviceListener, } } } canvas.restoreToCount(saveId); } private void logMotionEvent(String type, MotionEvent event) { Loading core/tests/coretests/src/android/view/MotionEventTest.java +20 −0 Original line number Diff line number Diff line Loading @@ -169,4 +169,24 @@ public class MotionEventTest { assertEquals(0x3 << 30, ID_SOURCE_MASK & event.getId()); } } @Test public void testEventRotation() { final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */, ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */); MotionEvent rot90 = MotionEvent.obtain(event); rot90.transform(MotionEvent.createRotateMatrix(/* 90 deg */1, 1000, 600)); assertEquals(50, (int) rot90.getX()); assertEquals(570, (int) rot90.getY()); MotionEvent rot180 = MotionEvent.obtain(event); rot180.transform(MotionEvent.createRotateMatrix(/* 180 deg */2, 1000, 600)); assertEquals(970, (int) rot180.getX()); assertEquals(550, (int) rot180.getY()); MotionEvent rot270 = MotionEvent.obtain(event); rot270.transform(MotionEvent.createRotateMatrix(/* 270 deg */3, 1000, 600)); assertEquals(950, (int) rot270.getX()); assertEquals(30, (int) rot270.getY()); } } packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java +7 −2 Original line number Diff line number Diff line Loading @@ -16,13 +16,12 @@ package com.android.systemui.shared.system; import android.os.Bundle; import android.graphics.Matrix; import android.os.Looper; import android.view.BatchedInputEventReceiver; import android.view.Choreographer; import android.view.InputChannel; import android.view.InputEvent; import android.view.InputEventSender; import android.view.MotionEvent; /** Loading Loading @@ -53,6 +52,12 @@ public class InputChannelCompat { return target.addBatch(src); } /** @see MotionEvent#createRotateMatrix */ public static Matrix createRotationMatrix( /*@Surface.Rotation*/ int rotation, int displayW, int displayH) { return MotionEvent.createRotateMatrix(rotation, displayW, displayH); } /** * @see BatchedInputEventReceiver */ Loading packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +16 −2 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.Choreographer; import android.view.Display; import android.view.ISystemGestureExclusionListener; import android.view.InputDevice; import android.view.InputEvent; Loading Loading @@ -96,6 +97,9 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa static final boolean DEBUG_MISSING_GESTURE = true; static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture"; private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION = SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false); private ISystemGestureExclusionListener mGestureExclusionListener = new ISystemGestureExclusionListener.Stub() { @Override Loading Loading @@ -505,9 +509,19 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa } private void onInputEvent(InputEvent ev) { if (ev instanceof MotionEvent) { onMotionEvent((MotionEvent) ev); } if (!(ev instanceof MotionEvent)) return; MotionEvent event = (MotionEvent) ev; if (ENABLE_PER_WINDOW_INPUT_ROTATION) { final Display display = mContext.getDisplay(); int rotation = display.getRotation(); if (rotation != Surface.ROTATION_0) { Point sz = new Point(); display.getRealSize(sz); event = MotionEvent.obtain(event); event.transform(MotionEvent.createRotateMatrix(rotation, sz.x, sz.y)); } } onMotionEvent(event); } private void updateMLModelState() { Loading Loading
core/java/android/view/MotionEvent.java +35 −0 Original line number Diff line number Diff line Loading @@ -3768,6 +3768,41 @@ public final class MotionEvent extends InputEvent implements Parcelable { return (getButtonState() & button) == button; } /** * Gets a rotation matrix that (when applied to a motionevent) will rotate that motion event * such that the result coordinates end up in the same physical location on a display whose * coordinates are rotated by `rotation`. * * For example, rotating 0,0 by 90 degrees will move a point from the physical top-left to * the bottom-left of the 90-degree-rotated display. * * @hide */ public static Matrix createRotateMatrix( @Surface.Rotation int rotation, int displayW, int displayH) { if (rotation == Surface.ROTATION_0) { return new Matrix(Matrix.IDENTITY_MATRIX); } // values is row-major float[] values = null; if (rotation == Surface.ROTATION_90) { values = new float[]{0, 1, 0, -1, 0, displayH, 0, 0, 1}; } else if (rotation == Surface.ROTATION_180) { values = new float[]{-1, 0, displayW, 0, -1, displayH, 0, 0, 1}; } else if (rotation == Surface.ROTATION_270) { values = new float[]{0, -1, displayW, 1, 0, 0, 0, 0, 1}; } Matrix toOrient = new Matrix(); toOrient.setValues(values); return toOrient; } public static final @android.annotation.NonNull Parcelable.Creator<MotionEvent> CREATOR = new Parcelable.Creator<MotionEvent>() { public MotionEvent createFromParcel(Parcel in) { Loading
core/java/com/android/internal/widget/PointerLocationView.java +24 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.Surface; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; Loading @@ -59,6 +60,9 @@ public class PointerLocationView extends View implements InputDeviceListener, */ private static final String GESTURE_EXCLUSION_PROP = "debug.pointerlocation.showexclusion"; private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION = SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false); public static class PointerState { // Trace of previous points. private float[] mTraceX = new float[32]; Loading Loading @@ -352,6 +356,21 @@ public class PointerLocationView extends View implements InputDeviceListener, .toString(), 1 + itemW * 6, base, mTextPaint); } int saveId = canvas.save(); if (ENABLE_PER_WINDOW_INPUT_ROTATION) { // Rotate negative (since we're rotating the drawing canvas vs the output). canvas.rotate(-90.0f * mContext.getDisplay().getRotation()); switch (mContext.getDisplay().getRotation()) { case Surface.ROTATION_90: canvas.translate(-canvas.getHeight(), 0); break; case Surface.ROTATION_180: canvas.translate(-canvas.getWidth(), -canvas.getHeight()); break; case Surface.ROTATION_270: canvas.translate(0, -canvas.getWidth()); } } // Pointer trace. for (int p = 0; p < NP; p++) { final PointerState ps = mPointers.get(p); Loading Loading @@ -399,7 +418,10 @@ public class PointerLocationView extends View implements InputDeviceListener, if (mCurDown && ps.mCurDown) { // Draw crosshairs. canvas.drawLine(0, ps.mCoords.y, getWidth(), ps.mCoords.y, mTargetPaint); canvas.drawLine(ps.mCoords.x, 0, ps.mCoords.x, getHeight(), mTargetPaint); // Extend crosshairs to cover screen regardless of rotation (ie. since the rotated // canvas can "expose" content past 0 and up-to the largest screen dimension). canvas.drawLine(ps.mCoords.x, -getHeight(), ps.mCoords.x, Math.max(getHeight(), getWidth()), mTargetPaint); // Draw current point. int pressureLevel = (int)(ps.mCoords.pressure * 255); Loading Loading @@ -458,6 +480,7 @@ public class PointerLocationView extends View implements InputDeviceListener, } } } canvas.restoreToCount(saveId); } private void logMotionEvent(String type, MotionEvent event) { Loading
core/tests/coretests/src/android/view/MotionEventTest.java +20 −0 Original line number Diff line number Diff line Loading @@ -169,4 +169,24 @@ public class MotionEventTest { assertEquals(0x3 << 30, ID_SOURCE_MASK & event.getId()); } } @Test public void testEventRotation() { final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */, ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */); MotionEvent rot90 = MotionEvent.obtain(event); rot90.transform(MotionEvent.createRotateMatrix(/* 90 deg */1, 1000, 600)); assertEquals(50, (int) rot90.getX()); assertEquals(570, (int) rot90.getY()); MotionEvent rot180 = MotionEvent.obtain(event); rot180.transform(MotionEvent.createRotateMatrix(/* 180 deg */2, 1000, 600)); assertEquals(970, (int) rot180.getX()); assertEquals(550, (int) rot180.getY()); MotionEvent rot270 = MotionEvent.obtain(event); rot270.transform(MotionEvent.createRotateMatrix(/* 270 deg */3, 1000, 600)); assertEquals(950, (int) rot270.getX()); assertEquals(30, (int) rot270.getY()); } }
packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java +7 −2 Original line number Diff line number Diff line Loading @@ -16,13 +16,12 @@ package com.android.systemui.shared.system; import android.os.Bundle; import android.graphics.Matrix; import android.os.Looper; import android.view.BatchedInputEventReceiver; import android.view.Choreographer; import android.view.InputChannel; import android.view.InputEvent; import android.view.InputEventSender; import android.view.MotionEvent; /** Loading Loading @@ -53,6 +52,12 @@ public class InputChannelCompat { return target.addBatch(src); } /** @see MotionEvent#createRotateMatrix */ public static Matrix createRotationMatrix( /*@Surface.Rotation*/ int rotation, int displayW, int displayH) { return MotionEvent.createRotateMatrix(rotation, displayW, displayH); } /** * @see BatchedInputEventReceiver */ Loading
packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +16 −2 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.Choreographer; import android.view.Display; import android.view.ISystemGestureExclusionListener; import android.view.InputDevice; import android.view.InputEvent; Loading Loading @@ -96,6 +97,9 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa static final boolean DEBUG_MISSING_GESTURE = true; static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture"; private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION = SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false); private ISystemGestureExclusionListener mGestureExclusionListener = new ISystemGestureExclusionListener.Stub() { @Override Loading Loading @@ -505,9 +509,19 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa } private void onInputEvent(InputEvent ev) { if (ev instanceof MotionEvent) { onMotionEvent((MotionEvent) ev); } if (!(ev instanceof MotionEvent)) return; MotionEvent event = (MotionEvent) ev; if (ENABLE_PER_WINDOW_INPUT_ROTATION) { final Display display = mContext.getDisplay(); int rotation = display.getRotation(); if (rotation != Surface.ROTATION_0) { Point sz = new Point(); display.getRealSize(sz); event = MotionEvent.obtain(event); event.transform(MotionEvent.createRotateMatrix(rotation, sz.x, sz.y)); } } onMotionEvent(event); } private void updateMLModelState() { Loading