Merge "Refactor MagnificationController out to its own class"
This commit is contained in:
committed by
Android (Google) Code Review
commit
978db40983
@@ -91,7 +91,6 @@ import android.view.accessibility.IAccessibilityManagerClient;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.content.PackageMonitor;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
@@ -180,6 +179,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
|
||||
private final MainHandler mMainHandler;
|
||||
|
||||
private MagnificationController mMagnificationController;
|
||||
|
||||
private InteractionBridge mInteractionBridge;
|
||||
|
||||
private AlertDialog mEnableTouchExplorationDialog;
|
||||
@@ -1936,6 +1937,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
MagnificationController getMagnificationController() {
|
||||
if (mMagnificationController == null) {
|
||||
mMagnificationController = new MagnificationController(mContext, this);
|
||||
}
|
||||
return mMagnificationController;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents an accessibility service. It stores all per service
|
||||
* data required for the service management, provides API for starting/stopping the
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.accessibility;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.util.Property;
|
||||
import android.util.Slog;
|
||||
import android.view.MagnificationSpec;
|
||||
import android.view.WindowManagerInternal;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
|
||||
/**
|
||||
* This class is used to control and query the state of display magnification
|
||||
* from the accessibility manager and related classes. It is responsible for
|
||||
* holding the current state of magnification and animation, and it handles
|
||||
* communication between the accessibility manager and window manager.
|
||||
*/
|
||||
class MagnificationController {
|
||||
private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName();
|
||||
|
||||
private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;
|
||||
private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false;
|
||||
|
||||
private static final String PROPERTY_NAME_MAGNIFICATION_SPEC = "magnificationSpec";
|
||||
|
||||
private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain();
|
||||
private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();
|
||||
|
||||
private final Region mMagnifiedBounds = new Region();
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
private final AccessibilityManagerService mAms;
|
||||
private final WindowManagerInternal mWindowManager;
|
||||
private final ValueAnimator mTransformationAnimator;
|
||||
|
||||
public MagnificationController(Context context, AccessibilityManagerService ams) {
|
||||
mAms = ams;
|
||||
mWindowManager = LocalServices.getService(WindowManagerInternal.class);
|
||||
|
||||
final Property<MagnificationController, MagnificationSpec> property =
|
||||
Property.of(MagnificationController.class, MagnificationSpec.class,
|
||||
PROPERTY_NAME_MAGNIFICATION_SPEC);
|
||||
final MagnificationSpecEvaluator evaluator = new MagnificationSpecEvaluator();
|
||||
final long animationDuration = context.getResources().getInteger(
|
||||
R.integer.config_longAnimTime);
|
||||
mTransformationAnimator = ObjectAnimator.ofObject(this, property, evaluator,
|
||||
mSentMagnificationSpec, mCurrentMagnificationSpec);
|
||||
mTransformationAnimator.setDuration(animationDuration);
|
||||
mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if magnification is active, e.g. the scale
|
||||
* is > 1, {@code false} otherwise
|
||||
*/
|
||||
public boolean isMagnifying() {
|
||||
return mCurrentMagnificationSpec.scale > 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the magnified region.
|
||||
*
|
||||
* @param region the region to set
|
||||
* @param updateSpec {@code true} to update the scale and center based on
|
||||
* the region bounds, {@code false} to leave them as-is
|
||||
*/
|
||||
public void setMagnifiedRegion(Region region, boolean updateSpec) {
|
||||
mMagnifiedBounds.set(region);
|
||||
|
||||
if (updateSpec) {
|
||||
final Rect magnifiedFrame = mTempRect;
|
||||
region.getBounds(magnifiedFrame);
|
||||
final float scale = mSentMagnificationSpec.scale;
|
||||
final float offsetX = mSentMagnificationSpec.offsetX;
|
||||
final float offsetY = mSentMagnificationSpec.offsetY;
|
||||
final float centerX = (-offsetX + magnifiedFrame.width() / 2) / scale;
|
||||
final float centerY = (-offsetY + magnifiedFrame.height() / 2) / scale;
|
||||
setScaleAndMagnifiedRegionCenter(scale, centerX, centerY, false);
|
||||
} else {
|
||||
mAms.onMagnificationStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the magnified region contains the specified
|
||||
* screen-relative coordinates.
|
||||
*
|
||||
* @param x the screen-relative X coordinate to check
|
||||
* @param y the screen-relative Y coordinate to check
|
||||
* @return {@code true} if the coordinate is contained within the
|
||||
* magnified region, or {@code false} otherwise
|
||||
*/
|
||||
public boolean magnifiedRegionContains(float x, float y) {
|
||||
return mMagnifiedBounds.contains((int) x, (int) y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the specified rect with the bounds of the magnified
|
||||
* region.
|
||||
*
|
||||
* @param outBounds rect to populate with the bounds of the magnified
|
||||
* region
|
||||
*/
|
||||
public void getMagnifiedBounds(Rect outBounds) {
|
||||
mMagnifiedBounds.getBounds(outBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the magnification scale. If an animation is in progress,
|
||||
* this reflects the end state of the animation.
|
||||
*
|
||||
* @return the scale
|
||||
*/
|
||||
public float getScale() {
|
||||
return mCurrentMagnificationSpec.scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X offset of the magnification viewport. If an animation
|
||||
* is in progress, this reflects the end state of the animation.
|
||||
*
|
||||
* @return the X offset
|
||||
*/
|
||||
public float getOffsetX() {
|
||||
return mCurrentMagnificationSpec.offsetX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Y offset of the magnification viewport. If an animation
|
||||
* is in progress, this reflects the end state of the animation.
|
||||
*
|
||||
* @return the Y offset
|
||||
*/
|
||||
public float getOffsetY() {
|
||||
return mCurrentMagnificationSpec.offsetY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scale currently used by the window manager. If an
|
||||
* animation is in progress, this reflects the current state of the
|
||||
* animation.
|
||||
*
|
||||
* @return the scale currently used by the window manager
|
||||
*/
|
||||
public float getSentScale() {
|
||||
return mSentMagnificationSpec.scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X offset currently used by the window manager. If an
|
||||
* animation is in progress, this reflects the current state of the
|
||||
* animation.
|
||||
*
|
||||
* @return the X offset currently used by the window manager
|
||||
*/
|
||||
public float getSentOffsetX() {
|
||||
return mSentMagnificationSpec.offsetX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Y offset currently used by the window manager. If an
|
||||
* animation is in progress, this reflects the current state of the
|
||||
* animation.
|
||||
*
|
||||
* @return the Y offset currently used by the window manager
|
||||
*/
|
||||
public float getSentOffsetY() {
|
||||
return mSentMagnificationSpec.offsetY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the magnification scale and center, optionally animating the
|
||||
* transition.
|
||||
*
|
||||
* @param animate {@code true} to animate the transition, {@code false}
|
||||
* to transition immediately
|
||||
*/
|
||||
public void reset(boolean animate) {
|
||||
if (mTransformationAnimator.isRunning()) {
|
||||
mTransformationAnimator.cancel();
|
||||
}
|
||||
mCurrentMagnificationSpec.clear();
|
||||
if (animate) {
|
||||
animateMagnificationSpec(mSentMagnificationSpec,
|
||||
mCurrentMagnificationSpec);
|
||||
} else {
|
||||
setMagnificationSpec(mCurrentMagnificationSpec);
|
||||
}
|
||||
final Rect bounds = mTempRect;
|
||||
bounds.setEmpty();
|
||||
mAms.onMagnificationStateChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the magnified region around the specified pivot point,
|
||||
* optionally animating the transition. If animation is disabled, the
|
||||
* transition is immediate.
|
||||
*
|
||||
* @param scale the target scale, must be >= 1
|
||||
* @param animate {@code true} to animate the transition, {@code false}
|
||||
* to transition immediately
|
||||
*/
|
||||
public void setScale(float scale, float pivotX, float pivotY, boolean animate) {
|
||||
final Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
final MagnificationSpec spec = mCurrentMagnificationSpec;
|
||||
final float oldScale = spec.scale;
|
||||
final float oldCenterX = (-spec.offsetX + magnifiedFrame.width() / 2) / oldScale;
|
||||
final float oldCenterY = (-spec.offsetY + magnifiedFrame.height() / 2) / oldScale;
|
||||
final float normPivotX = (-spec.offsetX + pivotX) / oldScale;
|
||||
final float normPivotY = (-spec.offsetY + pivotY) / oldScale;
|
||||
final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
|
||||
final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
|
||||
final float centerX = normPivotX + offsetX;
|
||||
final float centerY = normPivotY + offsetY;
|
||||
setScaleAndMagnifiedRegionCenter(scale, centerX, centerY, animate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the center of the magnified region, optionally animating the
|
||||
* transition. If animation is disabled, the transition is immediate.
|
||||
*
|
||||
* @param centerX the screen-relative X coordinate around which to
|
||||
* center
|
||||
* @param centerY the screen-relative Y coordinate around which to
|
||||
* center
|
||||
* @param animate {@code true} to animate the transition, {@code false}
|
||||
* to transition immediately
|
||||
*/
|
||||
public void setMagnifiedRegionCenter(float centerX, float centerY, boolean animate) {
|
||||
setScaleAndMagnifiedRegionCenter(mCurrentMagnificationSpec.scale, centerX, centerY,
|
||||
animate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scale and center of the magnified region, optionally
|
||||
* animating the transition. If animation is disabled, the transition
|
||||
* is immediate.
|
||||
*
|
||||
* @param scale the target scale, must be >= 1
|
||||
* @param centerX the screen-relative X coordinate around which to
|
||||
* center and scale
|
||||
* @param centerY the screen-relative Y coordinate around which to
|
||||
* center and scale
|
||||
* @param animate {@code true} to animate the transition, {@code false}
|
||||
* to transition immediately
|
||||
*/
|
||||
public void setScaleAndMagnifiedRegionCenter(float scale, float centerX, float centerY,
|
||||
boolean animate) {
|
||||
if (Float.compare(mCurrentMagnificationSpec.scale, scale) == 0
|
||||
&& Float.compare(mCurrentMagnificationSpec.offsetX, centerX) == 0
|
||||
&& Float.compare(mCurrentMagnificationSpec.offsetY, centerY) == 0) {
|
||||
return;
|
||||
}
|
||||
if (mTransformationAnimator.isRunning()) {
|
||||
mTransformationAnimator.cancel();
|
||||
}
|
||||
if (DEBUG_MAGNIFICATION_CONTROLLER) {
|
||||
Slog.i(LOG_TAG, "scale: " + scale + " offsetX: " + centerX + " offsetY: " + centerY);
|
||||
}
|
||||
updateMagnificationSpec(scale, centerX, centerY);
|
||||
if (animate) {
|
||||
animateMagnificationSpec(mSentMagnificationSpec,
|
||||
mCurrentMagnificationSpec);
|
||||
} else {
|
||||
setMagnificationSpec(mCurrentMagnificationSpec);
|
||||
}
|
||||
mAms.onMagnificationStateChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets the center of the magnified region.
|
||||
*
|
||||
* @param offsetX the amount in pixels to offset the X center
|
||||
* @param offsetY the amount in pixels to offset the Y center
|
||||
*/
|
||||
public void offsetMagnifiedRegionCenter(float offsetX, float offsetY) {
|
||||
final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
|
||||
mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX,
|
||||
getMinOffsetX()), 0);
|
||||
final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
|
||||
mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY,
|
||||
getMinOffsetY()), 0);
|
||||
setMagnificationSpec(mCurrentMagnificationSpec);
|
||||
}
|
||||
|
||||
private void updateMagnificationSpec(float scale, float magnifiedCenterX,
|
||||
float magnifiedCenterY) {
|
||||
final Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
mCurrentMagnificationSpec.scale = scale;
|
||||
final int viewportWidth = magnifiedFrame.width();
|
||||
final float nonNormOffsetX = viewportWidth / 2 - magnifiedCenterX * scale;
|
||||
mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX,
|
||||
getMinOffsetX()), 0);
|
||||
final int viewportHeight = magnifiedFrame.height();
|
||||
final float nonNormOffsetY = viewportHeight / 2 - magnifiedCenterY * scale;
|
||||
mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY,
|
||||
getMinOffsetY()), 0);
|
||||
}
|
||||
|
||||
private float getMinOffsetX() {
|
||||
final Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
final float viewportWidth = magnifiedFrame.width();
|
||||
return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale;
|
||||
}
|
||||
|
||||
private float getMinOffsetY() {
|
||||
final Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
final float viewportHeight = magnifiedFrame.height();
|
||||
return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale;
|
||||
}
|
||||
|
||||
private void animateMagnificationSpec(MagnificationSpec fromSpec,
|
||||
MagnificationSpec toSpec) {
|
||||
mTransformationAnimator.setObjectValues(fromSpec, toSpec);
|
||||
mTransformationAnimator.start();
|
||||
}
|
||||
|
||||
private void setMagnificationSpec(MagnificationSpec spec) {
|
||||
if (DEBUG_SET_MAGNIFICATION_SPEC) {
|
||||
Slog.i(LOG_TAG, "Sending: " + spec);
|
||||
}
|
||||
mSentMagnificationSpec.scale = spec.scale;
|
||||
mSentMagnificationSpec.offsetX = spec.offsetX;
|
||||
mSentMagnificationSpec.offsetY = spec.offsetY;
|
||||
mWindowManager.setMagnificationSpec(MagnificationSpec.obtain(spec));
|
||||
}
|
||||
|
||||
private static class MagnificationSpecEvaluator implements TypeEvaluator<MagnificationSpec> {
|
||||
private final MagnificationSpec mTempTransformationSpec = MagnificationSpec.obtain();
|
||||
|
||||
@Override
|
||||
public MagnificationSpec evaluate(float fraction, MagnificationSpec fromSpec,
|
||||
MagnificationSpec toSpec) {
|
||||
final MagnificationSpec result = mTempTransformationSpec;
|
||||
result.scale = fromSpec.scale + (toSpec.scale - fromSpec.scale) * fraction;
|
||||
result.offsetX = fromSpec.offsetX + (toSpec.offsetX - fromSpec.offsetX) * fraction;
|
||||
result.offsetY = fromSpec.offsetY + (toSpec.offsetY - fromSpec.offsetY) * fraction;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package com.android.server.accessibility;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -31,14 +28,12 @@ import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Property;
|
||||
import android.util.Slog;
|
||||
import android.util.TypedValue;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MagnificationSpec;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.MotionEvent.PointerCoords;
|
||||
import android.view.MotionEvent.PointerProperties;
|
||||
@@ -48,7 +43,6 @@ import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManagerInternal;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.server.LocalServices;
|
||||
@@ -101,10 +95,8 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
|
||||
private static final boolean DEBUG_STATE_TRANSITIONS = false;
|
||||
private static final boolean DEBUG_DETECTING = false;
|
||||
private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;
|
||||
private static final boolean DEBUG_PANNING = false;
|
||||
private static final boolean DEBUG_SCALING = false;
|
||||
private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false;
|
||||
|
||||
private static final int STATE_DELEGATING = 1;
|
||||
private static final int STATE_DETECTING = 2;
|
||||
@@ -134,8 +126,6 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
private final MagnifiedContentInteractonStateHandler mMagnifiedContentInteractonStateHandler;
|
||||
private final StateViewportDraggingHandler mStateViewportDraggingHandler;
|
||||
|
||||
private final AccessibilityManagerService mAms;
|
||||
|
||||
private final int mUserId;
|
||||
|
||||
private final int mTapTimeSlop = ViewConfiguration.getJumpTapTimeout();
|
||||
@@ -143,10 +133,6 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
private final int mTapDistanceSlop;
|
||||
private final int mMultiTapDistanceSlop;
|
||||
|
||||
private final long mLongAnimationDuration;
|
||||
|
||||
private final Region mMagnifiedBounds = new Region();
|
||||
|
||||
private EventStreamTransformation mNext;
|
||||
|
||||
private int mCurrentState;
|
||||
@@ -194,13 +180,10 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
mContext = context;
|
||||
mUserId = userId;
|
||||
mWindowManager = LocalServices.getService(WindowManagerInternal.class);
|
||||
mAms = service;
|
||||
|
||||
mMultiTapTimeSlop = ViewConfiguration.getDoubleTapTimeout()
|
||||
+ mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_screen_magnification_multi_tap_adjustment);
|
||||
mLongAnimationDuration = context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_longAnimTime);
|
||||
mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
mMultiTapDistanceSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
|
||||
|
||||
@@ -209,7 +192,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
mMagnifiedContentInteractonStateHandler = new MagnifiedContentInteractonStateHandler(
|
||||
context);
|
||||
|
||||
mMagnificationController = new MagnificationController(mLongAnimationDuration);
|
||||
mMagnificationController = service.getMagnificationController();
|
||||
mScreenStateObserver = new ScreenStateObserver(context, mMagnificationController);
|
||||
|
||||
mWindowManager.setMagnificationCallbacks(this);
|
||||
@@ -230,19 +213,9 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
// If there was a rotation we have to update the center of the magnified
|
||||
// region since the old offset X/Y may be out of its acceptable range for
|
||||
// the new display width and height.
|
||||
if (mUpdateMagnificationSpecOnNextBoundsChange) {
|
||||
mUpdateMagnificationSpecOnNextBoundsChange = false;
|
||||
MagnificationSpec spec = mMagnificationController.getMagnificationSpec();
|
||||
Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
final float scale = spec.scale;
|
||||
final float centerX = (-spec.offsetX + magnifiedFrame.width() / 2) / scale;
|
||||
final float centerY = (-spec.offsetY + magnifiedFrame.height() / 2) / scale;
|
||||
mMagnificationController.setScaleAndMagnifiedRegionCenter(scale, centerX,
|
||||
centerY, false);
|
||||
}
|
||||
mMagnifiedBounds.set(bounds);
|
||||
mAms.onMagnificationStateChanged();
|
||||
mMagnificationController.setMagnifiedRegion(
|
||||
bounds, mUpdateMagnificationSpecOnNextBoundsChange);
|
||||
mUpdateMagnificationSpecOnNextBoundsChange = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -257,7 +230,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
|
||||
private void handleOnRectangleOnScreenRequested(int left, int top, int right, int bottom) {
|
||||
Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
mMagnificationController.getMagnifiedBounds(magnifiedFrame);
|
||||
if (!magnifiedFrame.intersects(left, top, right, bottom)) {
|
||||
return;
|
||||
}
|
||||
@@ -314,10 +287,12 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
}
|
||||
|
||||
private void getMagnifiedFrameInContentCoords(Rect rect) {
|
||||
MagnificationSpec spec = mMagnificationController.getMagnificationSpec();
|
||||
mMagnifiedBounds.getBounds(rect);
|
||||
rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
|
||||
rect.scale(1.0f / spec.scale);
|
||||
final float scale = mMagnificationController.getSentScale();
|
||||
final float offsetX = mMagnificationController.getSentOffsetX();
|
||||
final float offsetY = mMagnificationController.getSentOffsetY();
|
||||
mMagnificationController.getMagnifiedBounds(rect);
|
||||
rect.offset((int) -offsetX, (int) -offsetY);
|
||||
rect.scale(1.0f / scale);
|
||||
}
|
||||
|
||||
private void resetMagnificationIfNeeded() {
|
||||
@@ -421,7 +396,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
final float eventX = event.getX();
|
||||
final float eventY = event.getY();
|
||||
if (mMagnificationController.isMagnifying()
|
||||
&& mMagnifiedBounds.contains((int) eventX, (int) eventY)) {
|
||||
&& mMagnificationController.magnifiedRegionContains(eventX, eventY)) {
|
||||
final float scale = mMagnificationController.getScale();
|
||||
final float scaledOffsetX = mMagnificationController.getOffsetX();
|
||||
final float scaledOffsetY = mMagnificationController.getOffsetY();
|
||||
@@ -623,7 +598,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
}
|
||||
final float eventX = event.getX();
|
||||
final float eventY = event.getY();
|
||||
if (mMagnifiedBounds.contains((int) eventX, (int) eventY)) {
|
||||
if (mMagnificationController.magnifiedRegionContains(eventX, eventY)) {
|
||||
if (mLastMoveOutsideMagnifiedRegion) {
|
||||
mLastMoveOutsideMagnifiedRegion = false;
|
||||
mMagnificationController.setMagnifiedRegionCenter(eventX,
|
||||
@@ -696,8 +671,8 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
|
||||
if (!mMagnifiedBounds.contains((int) event.getX(),
|
||||
(int) event.getY())) {
|
||||
if (!mMagnificationController.magnifiedRegionContains(
|
||||
event.getX(), event.getY())) {
|
||||
transitionToDelegatingStateAndClear();
|
||||
return;
|
||||
}
|
||||
@@ -738,7 +713,8 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
return;
|
||||
}
|
||||
mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD);
|
||||
if (!mMagnifiedBounds.contains((int) event.getX(), (int) event.getY())) {
|
||||
if (!mMagnificationController.magnifiedRegionContains(
|
||||
event.getX(), event.getY())) {
|
||||
transitionToDelegatingStateAndClear();
|
||||
return;
|
||||
}
|
||||
@@ -947,184 +923,6 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio
|
||||
}
|
||||
}
|
||||
|
||||
private final class MagnificationController {
|
||||
|
||||
private static final String PROPERTY_NAME_MAGNIFICATION_SPEC =
|
||||
"magnificationSpec";
|
||||
|
||||
private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain();
|
||||
|
||||
private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
private final ValueAnimator mTransformationAnimator;
|
||||
|
||||
public MagnificationController(long animationDuration) {
|
||||
Property<MagnificationController, MagnificationSpec> property =
|
||||
Property.of(MagnificationController.class, MagnificationSpec.class,
|
||||
PROPERTY_NAME_MAGNIFICATION_SPEC);
|
||||
TypeEvaluator<MagnificationSpec> evaluator = new TypeEvaluator<MagnificationSpec>() {
|
||||
private final MagnificationSpec mTempTransformationSpec =
|
||||
MagnificationSpec.obtain();
|
||||
@Override
|
||||
public MagnificationSpec evaluate(float fraction, MagnificationSpec fromSpec,
|
||||
MagnificationSpec toSpec) {
|
||||
MagnificationSpec result = mTempTransformationSpec;
|
||||
result.scale = fromSpec.scale
|
||||
+ (toSpec.scale - fromSpec.scale) * fraction;
|
||||
result.offsetX = fromSpec.offsetX + (toSpec.offsetX - fromSpec.offsetX)
|
||||
* fraction;
|
||||
result.offsetY = fromSpec.offsetY + (toSpec.offsetY - fromSpec.offsetY)
|
||||
* fraction;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
mTransformationAnimator = ObjectAnimator.ofObject(this, property,
|
||||
evaluator, mSentMagnificationSpec, mCurrentMagnificationSpec);
|
||||
mTransformationAnimator.setDuration((long) (animationDuration));
|
||||
mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
|
||||
}
|
||||
|
||||
public boolean isMagnifying() {
|
||||
return mCurrentMagnificationSpec.scale > 1.0f;
|
||||
}
|
||||
|
||||
public void reset(boolean animate) {
|
||||
if (mTransformationAnimator.isRunning()) {
|
||||
mTransformationAnimator.cancel();
|
||||
}
|
||||
mCurrentMagnificationSpec.clear();
|
||||
if (animate) {
|
||||
animateMangificationSpec(mSentMagnificationSpec,
|
||||
mCurrentMagnificationSpec);
|
||||
} else {
|
||||
setMagnificationSpec(mCurrentMagnificationSpec);
|
||||
}
|
||||
Rect bounds = mTempRect;
|
||||
bounds.setEmpty();
|
||||
mAms.onMagnificationStateChanged();
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return mCurrentMagnificationSpec.scale;
|
||||
}
|
||||
|
||||
public float getOffsetX() {
|
||||
return mCurrentMagnificationSpec.offsetX;
|
||||
}
|
||||
|
||||
public float getOffsetY() {
|
||||
return mCurrentMagnificationSpec.offsetY;
|
||||
}
|
||||
|
||||
public void setScale(float scale, float pivotX, float pivotY, boolean animate) {
|
||||
Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
MagnificationSpec spec = mCurrentMagnificationSpec;
|
||||
final float oldScale = spec.scale;
|
||||
final float oldCenterX = (-spec.offsetX + magnifiedFrame.width() / 2) / oldScale;
|
||||
final float oldCenterY = (-spec.offsetY + magnifiedFrame.height() / 2) / oldScale;
|
||||
final float normPivotX = (-spec.offsetX + pivotX) / oldScale;
|
||||
final float normPivotY = (-spec.offsetY + pivotY) / oldScale;
|
||||
final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
|
||||
final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
|
||||
final float centerX = normPivotX + offsetX;
|
||||
final float centerY = normPivotY + offsetY;
|
||||
setScaleAndMagnifiedRegionCenter(scale, centerX, centerY, animate);
|
||||
}
|
||||
|
||||
public void setMagnifiedRegionCenter(float centerX, float centerY, boolean animate) {
|
||||
setScaleAndMagnifiedRegionCenter(mCurrentMagnificationSpec.scale, centerX, centerY,
|
||||
animate);
|
||||
}
|
||||
|
||||
public void offsetMagnifiedRegionCenter(float offsetX, float offsetY) {
|
||||
final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
|
||||
mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX,
|
||||
getMinOffsetX()), 0);
|
||||
final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
|
||||
mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY,
|
||||
getMinOffsetY()), 0);
|
||||
setMagnificationSpec(mCurrentMagnificationSpec);
|
||||
}
|
||||
|
||||
public void setScaleAndMagnifiedRegionCenter(float scale, float centerX, float centerY,
|
||||
boolean animate) {
|
||||
if (Float.compare(mCurrentMagnificationSpec.scale, scale) == 0
|
||||
&& Float.compare(mCurrentMagnificationSpec.offsetX,
|
||||
centerX) == 0
|
||||
&& Float.compare(mCurrentMagnificationSpec.offsetY,
|
||||
centerY) == 0) {
|
||||
return;
|
||||
}
|
||||
if (mTransformationAnimator.isRunning()) {
|
||||
mTransformationAnimator.cancel();
|
||||
}
|
||||
if (DEBUG_MAGNIFICATION_CONTROLLER) {
|
||||
Slog.i(LOG_TAG, "scale: " + scale + " offsetX: " + centerX
|
||||
+ " offsetY: " + centerY);
|
||||
}
|
||||
updateMagnificationSpec(scale, centerX, centerY);
|
||||
if (animate) {
|
||||
animateMangificationSpec(mSentMagnificationSpec,
|
||||
mCurrentMagnificationSpec);
|
||||
} else {
|
||||
setMagnificationSpec(mCurrentMagnificationSpec);
|
||||
}
|
||||
mAms.onMagnificationStateChanged();
|
||||
}
|
||||
|
||||
public void updateMagnificationSpec(float scale, float magnifiedCenterX,
|
||||
float magnifiedCenterY) {
|
||||
Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
mCurrentMagnificationSpec.scale = scale;
|
||||
final int viewportWidth = magnifiedFrame.width();
|
||||
final float nonNormOffsetX = viewportWidth / 2 - magnifiedCenterX * scale;
|
||||
mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX,
|
||||
getMinOffsetX()), 0);
|
||||
final int viewportHeight = magnifiedFrame.height();
|
||||
final float nonNormOffsetY = viewportHeight / 2 - magnifiedCenterY * scale;
|
||||
mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY,
|
||||
getMinOffsetY()), 0);
|
||||
}
|
||||
|
||||
private float getMinOffsetX() {
|
||||
Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
final float viewportWidth = magnifiedFrame.width();
|
||||
return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale;
|
||||
}
|
||||
|
||||
private float getMinOffsetY() {
|
||||
Rect magnifiedFrame = mTempRect;
|
||||
mMagnifiedBounds.getBounds(magnifiedFrame);
|
||||
final float viewportHeight = magnifiedFrame.height();
|
||||
return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale;
|
||||
}
|
||||
|
||||
private void animateMangificationSpec(MagnificationSpec fromSpec,
|
||||
MagnificationSpec toSpec) {
|
||||
mTransformationAnimator.setObjectValues(fromSpec, toSpec);
|
||||
mTransformationAnimator.start();
|
||||
}
|
||||
|
||||
public MagnificationSpec getMagnificationSpec() {
|
||||
return mSentMagnificationSpec;
|
||||
}
|
||||
|
||||
public void setMagnificationSpec(MagnificationSpec spec) {
|
||||
if (DEBUG_SET_MAGNIFICATION_SPEC) {
|
||||
Slog.i(LOG_TAG, "Sending: " + spec);
|
||||
}
|
||||
mSentMagnificationSpec.scale = spec.scale;
|
||||
mSentMagnificationSpec.offsetX = spec.offsetX;
|
||||
mSentMagnificationSpec.offsetY = spec.offsetY;
|
||||
mWindowManager.setMagnificationSpec(MagnificationSpec.obtain(spec));
|
||||
}
|
||||
}
|
||||
|
||||
private final class ScreenStateObserver extends BroadcastReceiver {
|
||||
private static final int MESSAGE_ON_SCREEN_STATE_CHANGE = 1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user