use of android.view.MagnificationSpec in project android_frameworks_base by crdroidandroid.
the class MagnificationController method updateMagnificationSpecLocked.
/**
* Updates the current magnification spec.
*
* @param scale the magnification scale
* @param centerX the unscaled, screen-relative X coordinate of the center
* of the viewport, or {@link Float#NaN} to leave unchanged
* @param centerY the unscaled, screen-relative Y coordinate of the center
* of the viewport, or {@link Float#NaN} to leave unchanged
* @return {@code true} if the magnification spec changed or {@code false}
* otherwise
*/
private boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY) {
// Handle defaults.
if (Float.isNaN(centerX)) {
centerX = getCenterX();
}
if (Float.isNaN(centerY)) {
centerY = getCenterY();
}
if (Float.isNaN(scale)) {
scale = getScale();
}
// Ensure requested center is within the magnification region.
if (!magnificationRegionContains(centerX, centerY)) {
return false;
}
// Compute changes.
final MagnificationSpec currSpec = mCurrentMagnificationSpec;
boolean changed = false;
final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
if (Float.compare(currSpec.scale, normScale) != 0) {
currSpec.scale = normScale;
changed = true;
}
final float nonNormOffsetX = mMagnificationBounds.width() / 2.0f + mMagnificationBounds.left - centerX * scale;
final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
if (Float.compare(currSpec.offsetX, offsetX) != 0) {
currSpec.offsetX = offsetX;
changed = true;
}
final float nonNormOffsetY = mMagnificationBounds.height() / 2.0f + mMagnificationBounds.top - centerY * scale;
final float offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
if (Float.compare(currSpec.offsetY, offsetY) != 0) {
currSpec.offsetY = offsetY;
changed = true;
}
if (changed) {
onMagnificationChangedLocked();
}
return changed;
}
use of android.view.MagnificationSpec in project android_frameworks_base by crdroidandroid.
the class MagnificationController method onMagnificationRegionChanged.
/**
* Update our copy of the current magnification region
*
* @param magnified the magnified region
* @param updateSpec {@code true} to update the scale and center based on
* the region bounds, {@code false} to leave them as-is
*/
private void onMagnificationRegionChanged(Region magnified, boolean updateSpec) {
synchronized (mLock) {
if (!mRegistered) {
// Don't update if we've unregistered
return;
}
boolean magnificationChanged = false;
boolean boundsChanged = false;
if (!mMagnificationRegion.equals(magnified)) {
mMagnificationRegion.set(magnified);
mMagnificationRegion.getBounds(mMagnificationBounds);
boundsChanged = true;
}
if (updateSpec) {
final MagnificationSpec sentSpec = mSpecAnimationBridge.mSentMagnificationSpec;
final float scale = sentSpec.scale;
final float offsetX = sentSpec.offsetX;
final float offsetY = sentSpec.offsetY;
// Compute the new center and update spec as needed.
final float centerX = (mMagnificationBounds.width() / 2.0f + mMagnificationBounds.left - offsetX) / scale;
final float centerY = (mMagnificationBounds.height() / 2.0f + mMagnificationBounds.top - offsetY) / scale;
magnificationChanged = setScaleAndCenterLocked(scale, centerX, centerY, false, INVALID_ID);
}
// If magnification changed we already notified for the change.
if (boundsChanged && updateSpec && !magnificationChanged) {
onMagnificationChangedLocked();
}
}
}
use of android.view.MagnificationSpec in project android_frameworks_base by crdroidandroid.
the class MagnificationController method resetLocked.
private boolean resetLocked(boolean animate) {
if (!mRegistered) {
return false;
}
final MagnificationSpec spec = mCurrentMagnificationSpec;
final boolean changed = !spec.isNop();
if (changed) {
spec.clear();
onMagnificationChangedLocked();
}
mIdOfLastServiceToMagnify = INVALID_ID;
mSpecAnimationBridge.updateSentSpec(spec, animate);
return changed;
}
use of android.view.MagnificationSpec in project android_frameworks_base by crdroidandroid.
the class MagnificationController method offsetMagnifiedRegionCenter.
/**
* 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
* @param id the ID of the service requesting the change
*/
public void offsetMagnifiedRegionCenter(float offsetX, float offsetY, int id) {
synchronized (mLock) {
if (!mRegistered) {
return;
}
final MagnificationSpec currSpec = mCurrentMagnificationSpec;
final float nonNormOffsetX = currSpec.offsetX - offsetX;
currSpec.offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
final float nonNormOffsetY = currSpec.offsetY - offsetY;
currSpec.offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
if (id != INVALID_ID) {
mIdOfLastServiceToMagnify = id;
}
mSpecAnimationBridge.updateSentSpec(currSpec, false);
}
}
use of android.view.MagnificationSpec in project platform_frameworks_base by android.
the class WindowStateAnimator method computeShownFrameLocked.
void computeShownFrameLocked() {
final boolean selfTransformation = mHasLocalTransformation;
Transformation attachedTransformation = (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation) ? mAttachedWinAnimator.mTransformation : null;
Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation) ? mAppAnimator.transformation : null;
// Wallpapers are animated based on the "real" window they
// are currently targeting.
final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
if (wallpaperAnimator.mHasLocalTransformation && wallpaperAnimator.mAnimation != null && !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
attachedTransformation = wallpaperAnimator.mTransformation;
if (DEBUG_WALLPAPER && attachedTransformation != null) {
Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
}
}
final AppWindowAnimator wpAppAnimator = wallpaperTarget.mAppToken == null ? null : wallpaperTarget.mAppToken.mAppAnimator;
if (wpAppAnimator != null && wpAppAnimator.hasTransformation && wpAppAnimator.animation != null && !wpAppAnimator.animation.getDetachWallpaper()) {
appTransformation = wpAppAnimator.transformation;
if (DEBUG_WALLPAPER && appTransformation != null) {
Slog.v(TAG, "WP target app xform: " + appTransformation);
}
}
}
final int displayId = mWin.getDisplayId();
final ScreenRotationAnimation screenRotationAnimation = mAnimator.getScreenRotationAnimationLocked(displayId);
final boolean screenAnimation = screenRotationAnimation != null && screenRotationAnimation.isAnimating();
mHasClipRect = false;
if (selfTransformation || attachedTransformation != null || appTransformation != null || screenAnimation) {
// cache often used attributes locally
final Rect frame = mWin.mFrame;
final float[] tmpFloats = mService.mTmpFloats;
final Matrix tmpMatrix = mWin.mTmpMatrix;
// Compute the desired transformation.
if (screenAnimation && screenRotationAnimation.isRotating()) {
// If we are doing a screen animation, the global rotation
// applied to windows can result in windows that are carefully
// aligned with each other to slightly separate, allowing you
// to see what is behind them. An unsightly mess. This...
// thing... magically makes it call good: scale each window
// slightly (two pixels larger in each dimension, from the
// window's center).
final float w = frame.width();
final float h = frame.height();
if (w >= 1 && h >= 1) {
tmpMatrix.setScale(1 + 2 / w, 1 + 2 / h, w / 2, h / 2);
} else {
tmpMatrix.reset();
}
} else {
tmpMatrix.reset();
}
tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
if (selfTransformation) {
tmpMatrix.postConcat(mTransformation.getMatrix());
}
if (attachedTransformation != null) {
tmpMatrix.postConcat(attachedTransformation.getMatrix());
}
tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
if (appTransformation != null) {
tmpMatrix.postConcat(appTransformation.getMatrix());
}
if (screenAnimation) {
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
}
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
MagnificationSpec spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
applyMagnificationSpec(spec, tmpMatrix);
}
// "convert" it into SurfaceFlinger's format
// (a 2x2 matrix + an offset)
// Here we must not transform the position of the surface
// since it is already included in the transformation.
//Slog.i(TAG_WM, "Transform: " + matrix);
mHaveMatrix = true;
tmpMatrix.getValues(tmpFloats);
mDsDx = tmpFloats[Matrix.MSCALE_X];
mDtDx = tmpFloats[Matrix.MSKEW_Y];
mDsDy = tmpFloats[Matrix.MSKEW_X];
mDtDy = tmpFloats[Matrix.MSCALE_Y];
float x = tmpFloats[Matrix.MTRANS_X];
float y = tmpFloats[Matrix.MTRANS_Y];
mWin.mShownPosition.set(Math.round(x), Math.round(y));
// Now set the alpha... but because our current hardware
// can't do alpha transformation on a non-opaque surface,
// turn it off if we are running an animation that is also
// transforming since it is more important to have that
// animation be smooth.
mShownAlpha = mAlpha;
if (!mService.mLimitedAlphaCompositing || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) && x == frame.left && y == frame.top))) {
//Slog.i(TAG_WM, "Applying alpha transform");
if (selfTransformation) {
mShownAlpha *= mTransformation.getAlpha();
}
if (attachedTransformation != null) {
mShownAlpha *= attachedTransformation.getAlpha();
}
if (appTransformation != null) {
mShownAlpha *= appTransformation.getAlpha();
if (appTransformation.hasClipRect()) {
mClipRect.set(appTransformation.getClipRect());
mHasClipRect = true;
// bounds to compensate for this.
if (mWin.layoutInParentFrame()) {
mClipRect.offset((mWin.mContainingFrame.left - mWin.mFrame.left), mWin.mContainingFrame.top - mWin.mFrame.top);
}
}
}
if (screenAnimation) {
mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
}
} else {
//Slog.i(TAG_WM, "Not applying alpha transform");
}
if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV) && (mShownAlpha == 1.0 || mShownAlpha == 0.0))
Slog.v(TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null") + " attached=" + (attachedTransformation == null ? "null" : attachedTransformation.getAlpha()) + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha()) + " screen=" + (screenAnimation ? screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
return;
} else if (mIsWallpaper && mService.mWindowPlacerLocked.mWallpaperActionPending) {
return;
} else if (mWin.isDragResizeChanged()) {
// with new geometry.
return;
}
if (WindowManagerService.localLOGV)
Slog.v(TAG, "computeShownFrameLocked: " + this + " not attached, mAlpha=" + mAlpha);
MagnificationSpec spec = null;
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
}
if (spec != null) {
final Rect frame = mWin.mFrame;
final float[] tmpFloats = mService.mTmpFloats;
final Matrix tmpMatrix = mWin.mTmpMatrix;
tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
applyMagnificationSpec(spec, tmpMatrix);
tmpMatrix.getValues(tmpFloats);
mHaveMatrix = true;
mDsDx = tmpFloats[Matrix.MSCALE_X];
mDtDx = tmpFloats[Matrix.MSKEW_Y];
mDsDy = tmpFloats[Matrix.MSKEW_X];
mDtDy = tmpFloats[Matrix.MSCALE_Y];
float x = tmpFloats[Matrix.MTRANS_X];
float y = tmpFloats[Matrix.MTRANS_Y];
mWin.mShownPosition.set(Math.round(x), Math.round(y));
mShownAlpha = mAlpha;
} else {
mWin.mShownPosition.set(mWin.mFrame.left, mWin.mFrame.top);
if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
mWin.mShownPosition.offset(mWin.mXOffset, mWin.mYOffset);
}
mShownAlpha = mAlpha;
mHaveMatrix = false;
mDsDx = mWin.mGlobalScale;
mDtDx = 0;
mDsDy = 0;
mDtDy = mWin.mGlobalScale;
}
}
Aggregations