Merge "Don't rotate inputflinger's display" into sc-dev
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
@@ -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];
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -458,6 +480,7 @@ public class PointerLocationView extends View implements InputDeviceListener,
|
||||
}
|
||||
}
|
||||
}
|
||||
canvas.restoreToCount(saveId);
|
||||
}
|
||||
|
||||
private void logMotionEvent(String type, MotionEvent event) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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() {
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.content.res.Resources.NotFoundException;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayViewport;
|
||||
import android.hardware.input.IInputDevicesChangedListener;
|
||||
@@ -69,6 +70,7 @@ import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.VibrationEffect;
|
||||
import android.provider.DeviceConfig;
|
||||
@@ -168,6 +170,9 @@ public class InputManagerService extends IInputManager.Stub
|
||||
/** TODO(b/169067926): Remove this. */
|
||||
private static final boolean UNTRUSTED_TOUCHES_TOAST = false;
|
||||
|
||||
public static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
|
||||
SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
|
||||
|
||||
// Pointer to native input manager service object.
|
||||
private final long mPtr;
|
||||
|
||||
@@ -518,8 +523,51 @@ public class InputManagerService extends IInputManager.Stub
|
||||
nativeReloadDeviceAliases(mPtr);
|
||||
}
|
||||
|
||||
/** Rotates CCW by `delta` 90-degree increments. */
|
||||
private static void rotateBounds(Rect inOutBounds, int parentW, int parentH, int delta) {
|
||||
int rdelta = ((delta % 4) + 4) % 4;
|
||||
int origLeft = inOutBounds.left;
|
||||
switch (rdelta) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
inOutBounds.left = inOutBounds.top;
|
||||
inOutBounds.top = parentW - inOutBounds.right;
|
||||
inOutBounds.right = inOutBounds.bottom;
|
||||
inOutBounds.bottom = parentW - origLeft;
|
||||
return;
|
||||
case 2:
|
||||
inOutBounds.left = parentW - inOutBounds.right;
|
||||
inOutBounds.right = parentW - origLeft;
|
||||
return;
|
||||
case 3:
|
||||
inOutBounds.left = parentH - inOutBounds.bottom;
|
||||
inOutBounds.bottom = inOutBounds.right;
|
||||
inOutBounds.right = parentH - inOutBounds.top;
|
||||
inOutBounds.top = origLeft;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void setDisplayViewportsInternal(List<DisplayViewport> viewports) {
|
||||
nativeSetDisplayViewports(mPtr, viewports.toArray(new DisplayViewport[0]));
|
||||
final DisplayViewport[] vArray = new DisplayViewport[viewports.size()];
|
||||
if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
|
||||
// Remove all viewport operations. They will be built-into the window transforms.
|
||||
for (int i = viewports.size() - 1; i >= 0; --i) {
|
||||
final DisplayViewport v = vArray[i] = viewports.get(i).makeCopy();
|
||||
// deviceWidth/Height are apparently in "rotated" space, so flip them if needed.
|
||||
int dw = (v.orientation % 2) == 0 ? v.deviceWidth : v.deviceHeight;
|
||||
int dh = (v.orientation % 2) == 0 ? v.deviceHeight : v.deviceWidth;
|
||||
v.logicalFrame.set(0, 0, dw, dh);
|
||||
v.physicalFrame.set(0, 0, dw, dh);
|
||||
v.orientation = 0;
|
||||
}
|
||||
} else {
|
||||
for (int i = viewports.size() - 1; i >= 0; --i) {
|
||||
vArray[i] = viewports.get(i);
|
||||
}
|
||||
}
|
||||
nativeSetDisplayViewports(mPtr, vArray);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1002,7 +1002,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
|
||||
final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
|
||||
"PointerEventDispatcher" + mDisplayId, mDisplayId);
|
||||
mPointerEventDispatcher = new PointerEventDispatcher(inputChannel);
|
||||
mPointerEventDispatcher = new PointerEventDispatcher(inputChannel, this);
|
||||
|
||||
// Tap Listeners are supported for:
|
||||
// 1. All physical displays (multi-display).
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static com.android.server.input.InputManagerService.ENABLE_PER_WINDOW_INPUT_ROTATION;
|
||||
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputDevice;
|
||||
import android.view.InputEvent;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowManagerPolicyConstants.PointerEventListener;
|
||||
|
||||
import com.android.server.UiThread;
|
||||
@@ -31,8 +34,11 @@ public class PointerEventDispatcher extends InputEventReceiver {
|
||||
private final ArrayList<PointerEventListener> mListeners = new ArrayList<>();
|
||||
private PointerEventListener[] mListenersArray = new PointerEventListener[0];
|
||||
|
||||
public PointerEventDispatcher(InputChannel inputChannel) {
|
||||
private final DisplayContent mDisplayContent;
|
||||
|
||||
public PointerEventDispatcher(InputChannel inputChannel, DisplayContent dc) {
|
||||
super(inputChannel, UiThread.getHandler().getLooper());
|
||||
mDisplayContent = dc;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,7 +46,16 @@ public class PointerEventDispatcher extends InputEventReceiver {
|
||||
try {
|
||||
if (event instanceof MotionEvent
|
||||
&& (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
|
||||
final MotionEvent motionEvent = (MotionEvent) event;
|
||||
MotionEvent motionEvent = (MotionEvent) event;
|
||||
if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
|
||||
int rotation = mDisplayContent.getRotation();
|
||||
if (rotation != Surface.ROTATION_0) {
|
||||
motionEvent = MotionEvent.obtain(motionEvent);
|
||||
motionEvent.transform(MotionEvent.createRotateMatrix(rotation,
|
||||
mDisplayContent.getDisplayMetrics().widthPixels,
|
||||
mDisplayContent.getDisplayMetrics().heightPixels));
|
||||
}
|
||||
}
|
||||
PointerEventListener[] listeners;
|
||||
synchronized (mListeners) {
|
||||
if (mListenersArray == null) {
|
||||
|
||||
Reference in New Issue
Block a user