Merge "Implement pinch to resize."
This commit is contained in:
@@ -390,9 +390,9 @@ public final class SystemUiDeviceConfigFlags {
|
||||
public static final String CHOOSER_TARGET_RANKING_ENABLED = "chooser_target_ranking_enabled";
|
||||
|
||||
/**
|
||||
* (boolean) Whether to enable user-drag resizing for PIP.
|
||||
* (boolean) Whether to enable pinch resizing for PIP.
|
||||
*/
|
||||
public static final String PIP_USER_RESIZE = "pip_user_resize";
|
||||
public static final String PIP_PINCH_RESIZE = "pip_pinch_resize";
|
||||
|
||||
/**
|
||||
* (float) Bottom height in DP for Back Gesture.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.android.systemui.pip.phone;
|
||||
|
||||
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_USER_RESIZE;
|
||||
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_PINCH_RESIZE;
|
||||
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_BOTTOM;
|
||||
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT;
|
||||
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
|
||||
@@ -46,6 +46,7 @@ import android.view.InputEvent;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.InputMonitor;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.android.internal.policy.TaskResizingAlgorithm;
|
||||
@@ -67,6 +68,8 @@ import java.util.function.Function;
|
||||
public class PipResizeGestureHandler {
|
||||
|
||||
private static final String TAG = "PipResizeGestureHandler";
|
||||
private static final float PINCH_THRESHOLD = 0.05f;
|
||||
private static final float STARTING_SCALE_FACTOR = 1.0f;
|
||||
|
||||
private static final int INVALID_SYSUI_STATE_MASK =
|
||||
SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
|
||||
@@ -83,6 +86,7 @@ public class PipResizeGestureHandler {
|
||||
private final int mDisplayId;
|
||||
private final Executor mMainExecutor;
|
||||
private final SysUiState mSysUiState;
|
||||
private final ScaleGestureDetector mScaleGestureDetector;
|
||||
private final Region mTmpRegion = new Region();
|
||||
|
||||
private final PointF mDownPoint = new PointF();
|
||||
@@ -105,8 +109,10 @@ public class PipResizeGestureHandler {
|
||||
private boolean mAllowGesture;
|
||||
private boolean mIsAttached;
|
||||
private boolean mIsEnabled;
|
||||
private boolean mEnableUserResize;
|
||||
private boolean mEnablePinchResize;
|
||||
private boolean mThresholdCrossed;
|
||||
private boolean mUsingPinchToZoom = false;
|
||||
private float mScaleFactor = STARTING_SCALE_FACTOR;
|
||||
|
||||
private InputMonitor mInputMonitor;
|
||||
private InputEventReceiver mInputEventReceiver;
|
||||
@@ -136,17 +142,73 @@ public class PipResizeGestureHandler {
|
||||
context.getDisplay().getRealSize(mMaxSize);
|
||||
reloadResources();
|
||||
|
||||
mEnableUserResize = DeviceConfig.getBoolean(
|
||||
mScaleGestureDetector = new ScaleGestureDetector(context,
|
||||
new ScaleGestureDetector.OnScaleGestureListener() {
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
mScaleFactor *= detector.getScaleFactor();
|
||||
|
||||
if (!mThresholdCrossed
|
||||
&& (mScaleFactor > (STARTING_SCALE_FACTOR + PINCH_THRESHOLD)
|
||||
|| mScaleFactor < (STARTING_SCALE_FACTOR - PINCH_THRESHOLD))) {
|
||||
mThresholdCrossed = true;
|
||||
mInputMonitor.pilferPointers();
|
||||
}
|
||||
if (mThresholdCrossed) {
|
||||
int height = Math.min(mMaxSize.y, Math.max(mMinSize.y,
|
||||
(int) (mScaleFactor * mLastDownBounds.height())));
|
||||
int width = Math.min(mMaxSize.x, Math.max(mMinSize.x,
|
||||
(int) (mScaleFactor * mLastDownBounds.width())));
|
||||
int top, bottom, left, right;
|
||||
|
||||
if ((mCtrlType & CTRL_TOP) != 0) {
|
||||
top = mLastDownBounds.bottom - height;
|
||||
bottom = mLastDownBounds.bottom;
|
||||
} else {
|
||||
top = mLastDownBounds.top;
|
||||
bottom = mLastDownBounds.top + height;
|
||||
}
|
||||
|
||||
if ((mCtrlType & CTRL_LEFT) != 0) {
|
||||
left = mLastDownBounds.right - width;
|
||||
right = mLastDownBounds.right;
|
||||
} else {
|
||||
left = mLastDownBounds.left;
|
||||
right = mLastDownBounds.left + width;
|
||||
}
|
||||
|
||||
mLastResizeBounds.set(left, top, right, bottom);
|
||||
mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds,
|
||||
mLastResizeBounds,
|
||||
null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
setCtrlTypeForPinchToZoom();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
mScaleFactor = STARTING_SCALE_FACTOR;
|
||||
finishResize();
|
||||
}
|
||||
});
|
||||
|
||||
mEnablePinchResize = DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
PIP_USER_RESIZE,
|
||||
/* defaultValue = */ true);
|
||||
PIP_PINCH_RESIZE,
|
||||
/* defaultValue = */ false);
|
||||
deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor,
|
||||
new DeviceConfig.OnPropertiesChangedListener() {
|
||||
@Override
|
||||
public void onPropertiesChanged(DeviceConfig.Properties properties) {
|
||||
if (properties.getKeyset().contains(PIP_USER_RESIZE)) {
|
||||
mEnableUserResize = properties.getBoolean(
|
||||
PIP_USER_RESIZE, /* defaultValue = */ true);
|
||||
if (properties.getKeyset().contains(PIP_PINCH_RESIZE)) {
|
||||
mEnablePinchResize = properties.getBoolean(
|
||||
PIP_PINCH_RESIZE, /* defaultValue = */ false);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -193,7 +255,7 @@ public class PipResizeGestureHandler {
|
||||
}
|
||||
|
||||
private void updateIsEnabled() {
|
||||
boolean isEnabled = mIsAttached && mEnableUserResize;
|
||||
boolean isEnabled = mIsAttached;
|
||||
if (isEnabled == mIsEnabled) {
|
||||
return;
|
||||
}
|
||||
@@ -211,7 +273,11 @@ public class PipResizeGestureHandler {
|
||||
|
||||
private void onInputEvent(InputEvent ev) {
|
||||
if (ev instanceof MotionEvent) {
|
||||
onMotionEvent((MotionEvent) ev);
|
||||
if (mUsingPinchToZoom) {
|
||||
mScaleGestureDetector.onTouchEvent((MotionEvent) ev);
|
||||
} else {
|
||||
onDragCornerResize((MotionEvent) ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,8 +320,51 @@ public class PipResizeGestureHandler {
|
||||
}
|
||||
|
||||
public boolean willStartResizeGesture(MotionEvent ev) {
|
||||
return mEnableUserResize && isInValidSysUiState()
|
||||
&& isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY());
|
||||
if (isInValidSysUiState()) {
|
||||
switch (ev.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// Always pass the DOWN event to the ScaleGestureDetector
|
||||
mScaleGestureDetector.onTouchEvent(ev);
|
||||
if (isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY())) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
if (mEnablePinchResize && ev.getPointerCount() == 2) {
|
||||
mUsingPinchToZoom = true;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setCtrlTypeForPinchToZoom() {
|
||||
final Rect currentPipBounds = mMotionHelper.getBounds();
|
||||
mLastDownBounds.set(mMotionHelper.getBounds());
|
||||
|
||||
Rect movementBounds = mMovementBoundsSupplier.apply(currentPipBounds);
|
||||
mDisplayBounds.set(movementBounds.left,
|
||||
movementBounds.top,
|
||||
movementBounds.right + currentPipBounds.width(),
|
||||
movementBounds.bottom + currentPipBounds.height());
|
||||
|
||||
if (currentPipBounds.left == mDisplayBounds.left) {
|
||||
mCtrlType |= CTRL_RIGHT;
|
||||
} else {
|
||||
mCtrlType |= CTRL_LEFT;
|
||||
}
|
||||
|
||||
if (currentPipBounds.top > mDisplayBounds.top + mDisplayBounds.height()) {
|
||||
mCtrlType |= CTRL_TOP;
|
||||
} else {
|
||||
mCtrlType |= CTRL_BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
private void setCtrlType(int x, int y) {
|
||||
@@ -295,7 +404,7 @@ public class PipResizeGestureHandler {
|
||||
return (mSysUiState.getFlags() & INVALID_SYSUI_STATE_MASK) == 0;
|
||||
}
|
||||
|
||||
private void onMotionEvent(MotionEvent ev) {
|
||||
private void onDragCornerResize(MotionEvent ev) {
|
||||
int action = ev.getActionMasked();
|
||||
float x = ev.getX();
|
||||
float y = ev.getY();
|
||||
@@ -345,28 +454,33 @@ public class PipResizeGestureHandler {
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (!mLastResizeBounds.isEmpty()) {
|
||||
mUserResizeBounds.set(mLastResizeBounds);
|
||||
mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
|
||||
(Rect bounds) -> {
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
mMotionHelper.synchronizePinnedStackBounds();
|
||||
mUpdateMovementBoundsRunnable.run();
|
||||
resetState();
|
||||
});
|
||||
});
|
||||
mPipUiEventLogger.log(
|
||||
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE);
|
||||
} else {
|
||||
resetState();
|
||||
}
|
||||
finishResize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void finishResize() {
|
||||
if (!mLastResizeBounds.isEmpty()) {
|
||||
mUserResizeBounds.set(mLastResizeBounds);
|
||||
mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
|
||||
(Rect bounds) -> {
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
mMotionHelper.synchronizePinnedStackBounds();
|
||||
mUpdateMovementBoundsRunnable.run();
|
||||
resetState();
|
||||
});
|
||||
});
|
||||
mPipUiEventLogger.log(
|
||||
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE);
|
||||
} else {
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetState() {
|
||||
mCtrlType = CTRL_NONE;
|
||||
mUsingPinchToZoom = false;
|
||||
mAllowGesture = false;
|
||||
mThresholdCrossed = false;
|
||||
}
|
||||
@@ -397,7 +511,7 @@ public class PipResizeGestureHandler {
|
||||
pw.println(innerPrefix + "mAllowGesture=" + mAllowGesture);
|
||||
pw.println(innerPrefix + "mIsAttached=" + mIsAttached);
|
||||
pw.println(innerPrefix + "mIsEnabled=" + mIsEnabled);
|
||||
pw.println(innerPrefix + "mEnableUserResize=" + mEnableUserResize);
|
||||
pw.println(innerPrefix + "mEnablePinchResize=" + mEnablePinchResize);
|
||||
pw.println(innerPrefix + "mThresholdCrossed=" + mThresholdCrossed);
|
||||
}
|
||||
|
||||
|
||||
@@ -650,8 +650,7 @@ public class PipTouchHandler {
|
||||
}
|
||||
|
||||
MotionEvent ev = (MotionEvent) inputEvent;
|
||||
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN
|
||||
&& mPipResizeGestureHandler.willStartResizeGesture(ev)) {
|
||||
if (mPipResizeGestureHandler.willStartResizeGesture(ev)) {
|
||||
// Initialize the touch state for the gesture, but immediately reset to invalidate the
|
||||
// gesture
|
||||
mTouchState.onTouchEvent(ev);
|
||||
|
||||
Reference in New Issue
Block a user